Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ HelenOS.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
 @ "ia64" Intel IA-64
 @ "mips32" MIPS 32-bit
+@ "mips64" MIPS 64-bit
 @ "ppc32" PowerPC 32-bit (iMac G4)
 @ "sparc64" Sun UltraSPARC 64-bit
@@ -48,4 +49,8 @@
 
 % Machine type
+@ "msim" MSIM
+! [PLATFORM=mips64] MACHINE (choice)
+
+% Machine type
 @ "i460GX" i460GX chipset machine
 @ "ski" Ski ia64 simulator
@@ -54,5 +59,4 @@
 % Machine type
 @ "generic" Generic Sun workstation or server
-@ "serengeti" Serengeti system
 ! [PLATFORM=sparc64] MACHINE (choice)
 
@@ -69,4 +73,5 @@
 @ "athlon_xp" Athlon XP
 @ "athlon_mp" Athlon MP
+@ "i486" i486
 ! [PLATFORM=ia32] PROCESSOR (choice)
 
@@ -81,11 +86,8 @@
 ! [PLATFORM=sparc64&MACHINE=generic] PROCESSOR (choice)
 
-% CPU type
-@ "us3"
-! [PLATFORM=sparc64&MACHINE=serengeti] PROCESSOR (choice)
-
 % RAM disk format
 @ "tmpfs" TMPFS image
 @ "fat" FAT16 image
+@ "ext2fs" EXT2 image
 ! RDFMT (choice)
 
@@ -122,4 +124,8 @@
 
 % Kernel architecture
+@ "mips64"
+! [PLATFORM=mips64] KARCH (choice)
+
+% Kernel architecture
 @ "ppc32"
 ! [PLATFORM=ppc32] KARCH (choice)
@@ -165,4 +171,8 @@
 
 % User space architecture
+@ "mips64"
+! [PLATFORM=mips64] UARCH (choice)
+
+% User space architecture
 @ "ppc32"
 ! [PLATFORM=ppc32] UARCH (choice)
@@ -206,4 +216,8 @@
 @ "mips32"
 ! [PLATFORM=mips32] BARCH (choice)
+
+% Boot architecture
+@ "mips64"
+! [PLATFORM=mips64] BARCH (choice)
 
 % Boot architecture
@@ -229,4 +243,8 @@
 @ "ecoff"
 ! [PLATFORM=mips32&(MACHINE=bgxemul|MACHINE=lgxemul)] IMAGE (choice)
+
+% Image format
+@ "binary"
+! [PLATFORM=mips64] IMAGE (choice)
 
 
@@ -256,5 +274,5 @@
 @ "gcc_cross" GNU C Compiler (cross-compiler)
 @ "gcc_native" GNU C Compiler (native)
-! [PLATFORM=arm32|PLATFORM=mips32|PLATFORM=ppc32] COMPILER (choice)
+! [PLATFORM=arm32|PLATFORM=mips32|PLATFORM=mips64|PLATFORM=ppc32] COMPILER (choice)
 
 % Compiler
@@ -292,14 +310,14 @@
 
 % Page hash table support
-! [PLATFORM=ia64|PLATFORM=sparc64] CONFIG_PAGE_HT (y)
+! [PLATFORM=ia64|PLATFORM=mips64|PLATFORM=sparc64] CONFIG_PAGE_HT (y)
 
 % Software integer division support
-! [PLATFORM=abs32le|PLATFORM=ia32|PLATFORM=arm32|PLATFORM=ia64|PLATFORM=mips32|PLATFORM=ppc32] CONFIG_SOFTINT (y)
+! [PLATFORM=abs32le|PLATFORM=ia32|PLATFORM=arm32|PLATFORM=ia64|PLATFORM=mips32|PLATFORM=mips64|PLATFORM=ppc32] CONFIG_SOFTINT (y)
 
 % ASID support
-! [PLATFORM=ia64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_ASID (y)
+! [PLATFORM=ia64|PLATFORM=mips32|PLATFORM=mips64|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_ASID (y)
 
 % ASID FIFO support
-! [PLATFORM=ia64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_ASID_FIFO (y)
+! [PLATFORM=ia64|PLATFORM=mips32|PLATFORM=mips64|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_ASID_FIFO (y)
 
 % OpenFirmware tree support
@@ -322,5 +340,5 @@
 
 % Support for SMP
-! [(PLATFORM=ia32&PROCESSOR!=athlon_xp)|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)|PLATFORM=abs32le] CONFIG_SMP (y/n)
+! [(PLATFORM=ia32&PROCESSOR!=athlon_xp)|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ia64|(PLATFORM=mips32&MACHINE=msim)|(PLATFORM=mips64&MACHINE=msim)|PLATFORM=abs32le] CONFIG_SMP (y/n)
 
 % Debug build
@@ -379,5 +397,5 @@
 @ "generic" Keyboard or serial line
 @ "none" No input device
-! [PLATFORM=ia32|(PLATFORM=arm32&MACHINE=testarm)|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_HID_IN (choice)
+! [PLATFORM=ia32|(PLATFORM=arm32&MACHINE=testarm)|PLATFORM=amd64|PLATFORM=mips32|PLATFORM=mips64|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_HID_IN (choice)
 
 % Input device class
@@ -395,5 +413,5 @@
 @ "generic" Monitor or serial line
 @ "none" No output device
-! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ppc32|(PLATFORM=ia64&MACHINE=i460GX)|(PLATFORM=mips32&MACHINE=msim)] CONFIG_HID_OUT (choice)
+! [PLATFORM=ia32|PLATFORM=amd64|PLATFORM=sparc64|PLATFORM=ppc32|(PLATFORM=ia64&MACHINE=i460GX)|(PLATFORM=mips32&MACHINE=msim)|(PLATFORM=mips64&MACHINE=msim)] CONFIG_HID_OUT (choice)
 
 % Output device class
@@ -417,9 +435,12 @@
 ! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=ia64&MACHINE=i460GX] CONFIG_PC_KBD (y/n)
 
+% PC keyboard support
+! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=arm32&MACHINE=integratorcp] CONFIG_PC_KBD (y/n)
+
 % Support for msim/GXemul keyboard
-! [CONFIG_HID_IN=generic&PLATFORM=mips32] CONFIG_MIPS_KBD (y/n)
+! [CONFIG_HID_IN=generic&(PLATFORM=mips32|PLATFORM=mips64)] CONFIG_MIPS_KBD (y/n)
 
 % Support for msim/GXemul printer
-! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&PLATFORM=mips32] CONFIG_MIPS_PRN (y/n)
+! [(CONFIG_HID_OUT=generic|CONFIG_HID_OUT=serial)&(PLATFORM=mips32|PLATFORM=mips64)] CONFIG_MIPS_PRN (y/n)
 
 % Support for GXemul keyboard
@@ -444,13 +465,4 @@
 ! [PLATFORM=arm32&MACHINE=gta02] CONFIG_S3C24XX_IRQC (y)
 
-% Support for Z8530 controller
-! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=sparc64&MACHINE=generic] CONFIG_Z8530 (y/n)
-
-% Support for Serengeti console
-! [CONFIG_HID_OUT=generic&PLATFORM=sparc64&MACHINE=serengeti] CONFIG_SGCN_PRN (y/n)
-
-% Support for Serengeti keyboard
-! [CONFIG_HID_IN=generic&PLATFORM=sparc64&MACHINE=serengeti] CONFIG_SGCN_KBD (y/n)
-
 % Support for i8042 controller
 ! [CONFIG_PC_KBD=y] CONFIG_I8042 (y)
@@ -460,5 +472,5 @@
 
 % Sun keyboard support
-! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=sparc64&MACHINE=generic&(CONFIG_NS16550=y|CONFIG_Z8530=y)] CONFIG_SUN_KBD (y)
+! [(CONFIG_HID_IN=generic|CONFIG_HID_IN=keyboard)&PLATFORM=sparc64&MACHINE=generic&CONFIG_NS16550=y] CONFIG_SUN_KBD (y)
 
 % Macintosh ADB keyboard support
@@ -472,5 +484,5 @@
 
 % Serial line input module
-! [CONFIG_DSRLNIN=y|(PLATFORM=arm32&MACHINE=gta02)|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)|(PLATFORM=sparc64&MACHINE=serengeti&CONFIG_SGCN_KBD=y)|(PLATFORM=sparc64&PROCESSOR=sun4v)] CONFIG_SRLN (y)
+! [CONFIG_DSRLNIN=y|(PLATFORM=arm32&MACHINE=gta02)|(PLATFORM=ia64&MACHINE=i460GX&CONFIG_NS16550=y)|(PLATFORM=ia64&MACHINE=ski)|(PLATFORM=sparc64&PROCESSOR=sun4v)] CONFIG_SRLN (y)
 
 % EGA support
@@ -519,9 +531,18 @@
 ! [PLATFORM=sparc64&CONFIG_SMP=y] CONFIG_AP (y/n)
 
-% Use Block Address Translation by the loader
-! [PLATFORM=ppc32] CONFIG_BAT (y/n)
-
-% Preserve A.OUT header in isofs.b
-! [PLATFORM=sparc64&MACHINE=generic] CONFIG_AOUT_ISOFS_B (y)
+% Dynamic linking support
+! [PLATFORM=ia32] CONFIG_RTLD (n/y)
+! [PLATFORM=abs32le|PLATFORM=amd64|PLATFORM=arm32|PLATFORM=ia64|PLATFORM=mips32|PLATFORM=ppc32|PLATFORM=sparc64] CONFIG_RTLD (n)
+
+% Build shared libraries
+! [CONFIG_RTLD=y] CONFIG_BUILD_SHARED_LIBS (n/y)
+! [CONFIG_RTLD=n] CONFIG_BUILD_SHARED_LIBS (n)
+
+% Link against shared libraries
+! [CONFIG_BUILD_SHARED_LIBS=y] CONFIG_USE_SHARED_LIBS (n/y)
+! [CONFIG_BUILD_SHARED_LIBS=n] CONFIG_USE_SHARED_LIBS (n)
+
+% Launch (devman) test drivers
+! [CONFIG_DEBUG=y] CONFIG_TEST_DRIVERS (n/y)
 
 % Load disk drivers on startup
@@ -546,5 +567,15 @@
 ! [CONFIG_STRIP_BINARIES!=y] CONFIG_LINE_DEBUG (n/y)
 
-% Launch (devman) test drivers
-! [CONFIG_DEBUG=y] CONFIG_TEST_DRIVERS (y/n)
-
+# USB settings 
+
+% USB release build (less logging)
+! CONFIG_USB_RELEASE_BUILD (y/n)
+
+% Start virtual USB host controller
+! CONFIG_RUN_VIRTUAL_USB_HC (n/y)
+
+% OHCI root hub port power switching
+@ "no" All root hub ports are always powered.
+@ "ganged" Root hub ports are all powered or all off.
+@ "per_port" Powered status of every root hub port is independent.
+![PLATFORM=ia32|PLATFORM=amd64] OHCI_POWER_SWITCH (choice)
Index: Makefile
===================================================================
--- Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -54,5 +54,5 @@
 
 cscope:
-	find kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
+	find abi kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
 
 # Pre-integration build check
@@ -106,2 +106,4 @@
 	$(MAKE) -C uspace clean
 	$(MAKE) -C boot clean
+
+-include Makefile.local
Index: abi/include/ddi/arg.h
===================================================================
--- abi/include/ddi/arg.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/ddi/arg.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2006 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 genericddi
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_DDI_ARG_H_
+#define ABI_DDI_ARG_H_
+
+/** Structure encapsulating arguments for SYS_PHYSMEM_MAP syscall. */
+typedef struct {
+	/** ID of the destination task. */
+	uint64_t task_id;
+	/** Physical address of starting frame. */
+	void *phys_base;
+	/** Virtual address of starting page. */
+	void *virt_base;
+	/** Number of pages to map. */
+	size_t pages;
+	/** Address space area flags for the mapping. */
+	unsigned int flags;
+} ddi_memarg_t;
+
+/** Structure encapsulating arguments for SYS_ENABLE_IOSPACE syscall. */
+typedef struct {
+	uint64_t task_id;  /**< ID of the destination task. */
+	void *ioaddr;      /**< Starting I/O space address. */
+	size_t size;       /**< Number of bytes. */
+} ddi_ioarg_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/ddi/irq.h
===================================================================
--- abi/include/ddi/irq.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/ddi/irq.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2006 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 genericddi
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_DDI_IRQ_H_
+#define ABI_DDI_IRQ_H_
+
+typedef enum {
+	/** Read 1 byte from the I/O space. */
+	CMD_PIO_READ_8 = 1,
+	/** Read 2 bytes from the I/O space. */
+	CMD_PIO_READ_16,
+	/** Read 4 bytes from the I/O space. */
+	CMD_PIO_READ_32,
+	
+	/** Write 1 byte to the I/O space. */
+	CMD_PIO_WRITE_8,
+	/** Write 2 bytes to the I/O space. */
+	CMD_PIO_WRITE_16,
+	/** Write 4 bytes to the I/O space. */
+	CMD_PIO_WRITE_32,
+	
+	/**
+	 * Write 1 byte from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_8,
+	/**
+	 * Write 2 bytes from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_16,
+	/**
+	 * Write 4 bytes from the source argument
+	 * to the I/O space.
+	 */
+	CMD_PIO_WRITE_A_32,
+	
+	/** Read 1 byte from the memory space. */
+	CMD_MEM_READ_8,
+	/** Read 2 bytes from the memory space. */
+	CMD_MEM_READ_16,
+	/** Read 4 bytes from the memory space. */
+	CMD_MEM_READ_32,
+	
+	/** Write 1 byte to the memory space. */
+	CMD_MEM_WRITE_8,
+	/** Write 2 bytes to the memory space. */
+	CMD_MEM_WRITE_16,
+	/** Write 4 bytes to the memory space. */
+	CMD_MEM_WRITE_32,
+	
+	/** Write 1 byte from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_8,
+	/** Write 2 bytes from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_16,
+	/** Write 4 bytes from the source argument to the memory space. */
+	CMD_MEM_WRITE_A_32,
+	
+	/**
+	 * Perform a bit masking on the source argument
+	 * and store the result into the destination argument.
+	 */
+	CMD_BTEST,
+	
+	/**
+	 * Predicate the execution of the following
+	 * N commands by the boolean value of the source
+	 * argument.
+	 */
+	CMD_PREDICATE,
+	
+	/** Accept the interrupt. */
+	CMD_ACCEPT,
+	
+	/** Decline the interrupt. */
+	CMD_DECLINE,
+	CMD_LAST
+} irq_cmd_type;
+
+typedef struct {
+	irq_cmd_type cmd;
+	void *addr;
+	uint32_t value;
+	uintptr_t srcarg;
+	uintptr_t dstarg;
+} irq_cmd_t;
+
+typedef struct {
+	size_t cmdcount;
+	irq_cmd_t *cmds;
+} irq_code_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/elf.h
===================================================================
--- abi/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * 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_ELF_H_
+#define ABI_ELF_H_
+
+/**
+ * Current ELF version
+ */
+#define EV_CURRENT  1
+
+/**
+ * ELF types
+ */
+#define ET_NONE    0       /* No type */
+#define ET_REL     1       /* Relocatable file */
+#define ET_EXEC    2       /* Executable */
+#define ET_DYN     3       /* Shared object */
+#define ET_CORE    4       /* Core */
+#define ET_LOPROC  0xff00  /* Processor specific */
+#define ET_HIPROC  0xffff  /* Processor specific */
+
+/**
+ * ELF machine types
+ */
+#define EM_NO           0   /* No machine */
+#define EM_SPARC        2   /* SPARC */
+#define EM_386          3   /* i386 */
+#define EM_MIPS         8   /* MIPS RS3000 */
+#define EM_MIPS_RS3_LE  10  /* MIPS RS3000 LE */
+#define EM_PPC          20  /* PPC32 */
+#define EM_PPC64        21  /* PPC64 */
+#define EM_ARM          40  /* ARM */
+#define EM_SPARCV9      43  /* SPARC64 */
+#define EM_IA_64        50  /* IA-64 */
+#define EM_X86_64       62  /* AMD64/EMT64 */
+
+/**
+ * ELF identification indexes
+ */
+#define EI_MAG0        0
+#define EI_MAG1        1
+#define EI_MAG2        2
+#define EI_MAG3        3
+#define EI_CLASS       4   /* File class */
+#define EI_DATA        5   /* Data encoding */
+#define EI_VERSION     6   /* File version */
+#define EI_OSABI       7
+#define EI_ABIVERSION  8
+#define EI_PAD         9   /* Start of padding bytes */
+#define EI_NIDENT      16  /* ELF identification table size */
+
+/**
+ * ELF magic number
+ */
+#define ELFMAG0  0x7f
+#define ELFMAG1  'E'
+#define ELFMAG2  'L'
+#define ELFMAG3  'F'
+
+/**
+ * ELF file classes
+ */
+#define ELFCLASSNONE  0
+#define ELFCLASS32    1
+#define ELFCLASS64    2
+
+/**
+ * ELF data encoding types
+ */
+#define ELFDATANONE  0
+#define ELFDATA2LSB  1  /* Least significant byte first (little endian) */
+#define ELFDATA2MSB  2  /* Most signigicant byte first (big endian) */
+
+/**
+ * ELF section types
+ */
+#define SHT_NULL      0
+#define SHT_PROGBITS  1
+#define SHT_SYMTAB    2
+#define SHT_STRTAB    3
+#define SHT_RELA      4
+#define SHT_HASH      5
+#define SHT_DYNAMIC   6
+#define SHT_NOTE      7
+#define SHT_NOBITS    8
+#define SHT_REL       9
+#define SHT_SHLIB     10
+#define SHT_DYNSYM    11
+#define SHT_LOOS      0x60000000
+#define SHT_HIOS      0x6fffffff
+#define SHT_LOPROC    0x70000000
+#define SHT_HIPROC    0x7fffffff
+#define SHT_LOUSER    0x80000000
+#define SHT_HIUSER    0xffffffff
+
+/**
+ * ELF section flags
+ */
+#define SHF_WRITE      0x1
+#define SHF_ALLOC      0x2
+#define SHF_EXECINSTR  0x4
+#define SHF_TLS        0x400
+#define SHF_MASKPROC   0xf0000000
+
+/** Macros for decomposing elf_symbol.st_info into binging and type */
+#define ELF_ST_BIND(i)     ((i) >> 4)
+#define ELF_ST_TYPE(i)     ((i) & 0x0f)
+#define ELF_ST_INFO(b, t)  (((b) << 4) + ((t) & 0x0f))
+
+/**
+ * Symbol binding
+ */
+#define STB_LOCAL   0
+#define STB_GLOBAL  1
+#define STB_WEAK    2
+#define STB_LOPROC  13
+#define STB_HIPROC  15
+
+/**
+ * Symbol types
+ */
+#define STT_NOTYPE   0
+#define STT_OBJECT   1
+#define STT_FUNC     2
+#define STT_SECTION  3
+#define STT_FILE     4
+#define STT_LOPROC   13
+#define STT_HIPROC   15
+
+/**
+ * Program segment types
+ */
+#define PT_NULL     0
+#define PT_LOAD     1
+#define PT_DYNAMIC  2
+#define PT_INTERP   3
+#define PT_NOTE     4
+#define PT_SHLIB    5
+#define PT_PHDR     6
+#define PT_LOPROC   0x70000000
+#define PT_HIPROC   0x7fffffff
+
+/**
+ * Program segment attributes.
+ */
+#define PF_X  1
+#define PF_W  2
+#define PF_R  4
+
+/**
+ * ELF data types
+ *
+ * These types are found to be identical in both 32-bit and 64-bit
+ * ELF object file specifications. They are the only types used
+ * in ELF header.
+ */
+typedef uint64_t elf_xword;
+typedef int64_t elf_sxword;
+typedef uint32_t elf_word;
+typedef int32_t elf_sword;
+typedef uint16_t elf_half;
+
+/**
+ * 32-bit ELF data types.
+ *
+ * These types are specific for 32-bit format.
+ */
+typedef uint32_t elf32_addr;
+typedef uint32_t elf32_off;
+
+/**
+ * 64-bit ELF data types.
+ *
+ * These types are specific for 64-bit format.
+ */
+typedef uint64_t elf64_addr;
+typedef uint64_t elf64_off;
+
+/** ELF header */
+struct elf32_header {
+	uint8_t e_ident[EI_NIDENT];
+	elf_half e_type;
+	elf_half e_machine;
+	elf_word e_version;
+	elf32_addr e_entry;
+	elf32_off e_phoff;
+	elf32_off e_shoff;
+	elf_word e_flags;
+	elf_half e_ehsize;
+	elf_half e_phentsize;
+	elf_half e_phnum;
+	elf_half e_shentsize;
+	elf_half e_shnum;
+	elf_half e_shstrndx;
+};
+
+struct elf64_header {
+	uint8_t e_ident[EI_NIDENT];
+	elf_half e_type;
+	elf_half e_machine;
+	elf_word e_version;
+	elf64_addr e_entry;
+	elf64_off e_phoff;
+	elf64_off e_shoff;
+	elf_word e_flags;
+	elf_half e_ehsize;
+	elf_half e_phentsize;
+	elf_half e_phnum;
+	elf_half e_shentsize;
+	elf_half e_shnum;
+	elf_half e_shstrndx;
+};
+
+/**
+ * ELF segment header.
+ * Segments headers are also known as program headers.
+ */
+struct elf32_segment_header {
+	elf_word p_type;
+	elf32_off p_offset;
+	elf32_addr p_vaddr;
+	elf32_addr p_paddr;
+	elf_word p_filesz;
+	elf_word p_memsz;
+	elf_word p_flags;
+	elf_word p_align;
+};
+
+struct elf64_segment_header {
+	elf_word p_type;
+	elf_word p_flags;
+	elf64_off p_offset;
+	elf64_addr p_vaddr;
+	elf64_addr p_paddr;
+	elf_xword p_filesz;
+	elf_xword p_memsz;
+	elf_xword p_align;
+};
+
+/**
+ * ELF section header
+ */
+struct elf32_section_header {
+	elf_word sh_name;
+	elf_word sh_type;
+	elf_word sh_flags;
+	elf32_addr sh_addr;
+	elf32_off sh_offset;
+	elf_word sh_size;
+	elf_word sh_link;
+	elf_word sh_info;
+	elf_word sh_addralign;
+	elf_word sh_entsize;
+};
+
+struct elf64_section_header {
+	elf_word sh_name;
+	elf_word sh_type;
+	elf_xword sh_flags;
+	elf64_addr sh_addr;
+	elf64_off sh_offset;
+	elf_xword sh_size;
+	elf_word sh_link;
+	elf_word sh_info;
+	elf_xword sh_addralign;
+	elf_xword sh_entsize;
+};
+
+/**
+ * ELF symbol table entry
+ */
+struct elf32_symbol {
+	elf_word st_name;
+	elf32_addr st_value;
+	elf_word st_size;
+	uint8_t st_info;
+	uint8_t st_other;
+	elf_half st_shndx;
+};
+
+struct elf64_symbol {
+	elf_word st_name;
+	uint8_t st_info;
+	uint8_t st_other;
+	elf_half st_shndx;
+	elf64_addr st_value;
+	elf_xword st_size;
+};
+
+/*
+ * ELF note segment entry
+ */
+struct elf32_note {
+	elf_word namesz;
+	elf_word descsz;
+	elf_word type;
+};
+
+/*
+ * NOTE: namesz, descsz and type should be 64-bits wide (elf_xword)
+ * per the 64-bit ELF spec. The Linux kernel however screws up and
+ * defines them as Elf64_Word, which is 32-bits wide(!). We are trying
+ * to make our core files compatible with Linux GDB target so we copy
+ * the blunder here.
+ */
+struct elf64_note {
+	elf_word namesz;
+	elf_word descsz;
+	elf_word type;
+};
+
+#ifdef __32_BITS__
+typedef struct elf32_header elf_header_t;
+typedef struct elf32_segment_header elf_segment_header_t;
+typedef struct elf32_section_header elf_section_header_t;
+typedef struct elf32_symbol elf_symbol_t;
+typedef struct elf32_note elf_note_t;
+#endif
+
+#ifdef __64_BITS__
+typedef struct elf64_header elf_header_t;
+typedef struct elf64_segment_header elf_segment_header_t;
+typedef struct elf64_section_header elf_section_header_t;
+typedef struct elf64_symbol elf_symbol_t;
+typedef struct elf64_note elf_note_t;
+#endif
+
+#endif
+
+/** @}
+ */
Index: abi/include/errno.h
===================================================================
--- abi/include/errno.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/errno.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_ERRNO_H_
+#define ABI_ERRNO_H_
+
+/**
+ * Values in the range [-1, -255] are kernel error codes,
+ * values in the range [-256, -512] are user error codes.
+ */
+
+#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 */
+
+/*
+ * Answerbox closed connection, call
+ * sys_ipc_hangup() to close the connection.
+ * Used by answerbox to close the connection.
+ */
+#define EHANGUP        -7
+
+/*
+ * The other party encountered an error when
+ * receiving the call.
+ */
+#define EPARTY         -8
+
+#define EEXISTS        -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. */
+
+#endif
+
+/** @}
+ */
Index: abi/include/fb/visuals.h
===================================================================
--- abi/include/fb/visuals.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/fb/visuals.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/** @addtogroup genarch
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_VISUALS_H_
+#define ABI_VISUALS_H_
+
+typedef enum {
+	VISUAL_UNKNOWN = 0,
+	VISUAL_INDIRECT_8,
+	VISUAL_RGB_5_5_5_LE,
+	VISUAL_RGB_5_5_5_BE,
+	VISUAL_RGB_5_6_5_LE,
+	VISUAL_RGB_5_6_5_BE,
+	VISUAL_BGR_8_8_8,
+	VISUAL_BGR_0_8_8_8,
+	VISUAL_BGR_8_8_8_0,
+	VISUAL_RGB_8_8_8,
+	VISUAL_RGB_0_8_8_8,
+	VISUAL_RGB_8_8_8_0
+} visual_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/ipc/event.h
===================================================================
--- abi/include/ipc/event.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/ipc/event.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2009 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_IPC_EVENT_H_
+#define ABI_IPC_EVENT_H_
+
+/** Global events */
+typedef enum event_type {
+	/** New data available in kernel log */
+	EVENT_KLOG = 0,
+	/** Returning from kernel console to uspace */
+	EVENT_KCONSOLE,
+	/** A task/thread has faulted and will be terminated */
+	EVENT_FAULT,
+	EVENT_END
+} event_type_t;
+
+/** Per-task events. */
+typedef enum event_task_type {
+	EVENT_TASK_STATE_CHANGE = EVENT_END,
+	EVENT_TASK_END
+} event_task_type_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/ipc/ipc.h
===================================================================
--- abi/include/ipc/ipc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/ipc/ipc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genericipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_IPC_IPC_H_
+#define ABI_IPC_IPC_H_
+
+/** Length of data being transfered with IPC call
+ *
+ * The uspace may not be able to utilize full length
+ *
+ */
+#define IPC_CALL_LEN  6
+
+/** Maximum active async calls per phone */
+#define IPC_MAX_ASYNC_CALLS  4
+
+/* Flags for calls */
+
+/** This is answer to a call */
+#define IPC_CALL_ANSWERED  (1 << 0)
+
+/** Answer will not be passed to userspace, will be discarded */
+#define IPC_CALL_DISCARD_ANSWER  (1 << 1)
+
+/** Call was forwarded */
+#define IPC_CALL_FORWARDED  (1 << 2)
+
+/** Identify connect_me_to answer */
+#define IPC_CALL_CONN_ME_TO  (1 << 3)
+
+/** Interrupt notification */
+#define IPC_CALL_NOTIF  (1 << 4)
+
+
+/** 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
+#define IPC_CALLRET_TEMPORARY  -2
+
+
+/* Macros for manipulating calling data */
+#define IPC_SET_RETVAL(data, retval)  ((data).args[0] = (retval))
+#define IPC_SET_IMETHOD(data, val)    ((data).args[0] = (val))
+#define IPC_SET_ARG1(data, val)       ((data).args[1] = (val))
+#define IPC_SET_ARG2(data, val)       ((data).args[2] = (val))
+#define IPC_SET_ARG3(data, val)       ((data).args[3] = (val))
+#define IPC_SET_ARG4(data, val)       ((data).args[4] = (val))
+#define IPC_SET_ARG5(data, val)       ((data).args[5] = (val))
+
+#define IPC_GET_IMETHOD(data)  ((data).args[0])
+#define IPC_GET_RETVAL(data)   ((data).args[0])
+
+#define IPC_GET_ARG1(data)  ((data).args[1])
+#define IPC_GET_ARG2(data)  ((data).args[2])
+#define IPC_GET_ARG3(data)  ((data).args[3])
+#define IPC_GET_ARG4(data)  ((data).args[4])
+#define IPC_GET_ARG5(data)  ((data).args[5])
+
+/* Forwarding flags. */
+#define IPC_FF_NONE  0
+
+/**
+ * The call will be routed as though it was initially sent via the phone used to
+ * forward it. This feature is intended to support the situation in which the
+ * forwarded call needs to be handled by the same connection fibril as any other
+ * calls that were initially sent by the forwarder to the same destination. This
+ * flag has no imapct on routing replies.
+ */
+#define IPC_FF_ROUTE_FROM_ME  (1 << 0)
+
+/* Data transfer flags. */
+#define IPC_XF_NONE  0
+
+/** Restrict the transfer size if necessary. */
+#define IPC_XF_RESTRICT  (1 << 0)
+
+/** User-defined IPC methods */
+#define IPC_FIRST_USER_METHOD  1024
+
+#endif
+
+/** @}
+ */
Index: abi/include/ipc/methods.h
===================================================================
--- abi/include/ipc/methods.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/ipc/methods.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genericipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_IPC_METHODS_H_
+#define ABI_IPC_METHODS_H_
+
+/* Well known phone descriptors */
+#define PHONE_NS  0
+
+/** Kernel IPC interfaces
+ *
+ */
+#define IPC_IF_KERNEL  0
+
+/** System-specific IPC methods
+ *
+ * These methods have special behaviour. These methods also
+ * have the implicit kernel interface zero (0).
+ *
+ */
+
+/** This message is sent to answerbox when the phone is hung up
+ *
+ * The numerical value zero (0) of this method is important,
+ * so as the value can be easily tested in conditions.
+ *
+ */
+#define IPC_M_PHONE_HUNGUP  0
+
+/** Clone connection.
+ *
+ * The calling task clones one of its phones for the callee.
+ *
+ * - ARG1 - The caller sets ARG1 to the phone of the cloned connection.
+ *        - The callee gets the new phone from ARG1.
+ *
+ * - on answer, the callee acknowledges the new connection by sending EOK back
+ *   or the kernel closes it
+ *
+ */
+#define IPC_M_CONNECTION_CLONE  1
+
+/** Protocol for CONNECT - ME
+ *
+ * Through this call, the recipient learns about the new cloned connection.
+ *
+ * - ARG5 - the kernel sets ARG5 to contain the hash of the used phone
+ * - on answer, the callee acknowledges the new connection by sending EOK back
+ *   or the kernel closes it
+ *
+ */
+#define IPC_M_CONNECT_ME  2
+
+/** Protocol for CONNECT - TO - ME
+ *
+ * Calling process asks the callee to create a callback connection,
+ * so that it can start initiating new messages.
+ *
+ * The protocol for negotiating is:
+ * - sys_connect_to_me - sends a message IPC_M_CONNECT_TO_ME
+ * - recipient         - upon receipt tries to allocate new phone
+ *                       - if it fails, responds with ELIMIT
+ *                     - passes call to userspace. If userspace
+ *                       responds with error, phone is deallocated and
+ *                       error is sent back to caller. Otherwise 
+ *                       the call is accepted and the response is sent back.
+ *                     - the hash of the allocated phone is passed to userspace
+ *                       (on the receiving side) as ARG5 of the call.
+ *
+ */
+#define IPC_M_CONNECT_TO_ME  3
+
+/** Protocol for CONNECT - ME - TO
+ *
+ * Calling process asks the callee to create for him a new connection.
+ * E.g. the caller wants a name server to connect him to print server.
+ *
+ * The protocol for negotiating is:
+ * - sys_connect_me_to - send a synchronous message to name server
+ *                       indicating that it wants to be connected to some
+ *                       service
+ *                     - arg1/2/3 are user specified, arg5 contains
+ *                       address of the phone that should be connected
+ *                       (TODO: it leaks to userspace)
+ *  - recipient        -  if ipc_answer == 0, then accept connection
+ *                     -  otherwise connection refused
+ *                     -  recepient may forward message.
+ *
+ */
+#define IPC_M_CONNECT_ME_TO  4
+
+/** Send as_area over IPC.
+ * - ARG1 - source as_area base address
+ * - ARG2 - size of source as_area (filled automatically by kernel)
+ * - ARG3 - flags of the as_area being sent
+ *
+ * on answer, the recipient must set:
+ * - ARG1 - dst as_area base adress
+ *
+ */
+#define IPC_M_SHARE_OUT  5
+
+/** Receive as_area over IPC.
+ * - ARG1 - destination as_area base address
+ * - ARG2 - destination as_area size
+ * - ARG3 - user defined argument
+ *
+ * on answer, the recipient must set:
+ *
+ * - ARG1 - source as_area base address
+ * - ARG2 - flags that will be used for sharing
+ *
+ */
+#define IPC_M_SHARE_IN  6
+
+/** Send data to another address space over IPC.
+ * - ARG1 - source address space virtual address
+ * - ARG2 - size of data to be copied, may be overriden by the recipient
+ *
+ * on answer, the recipient must set:
+ *
+ * - ARG1 - final destination address space virtual address
+ * - ARG2 - final size of data to be copied
+ *
+ */
+#define IPC_M_DATA_WRITE  7
+
+/** Receive data from another address space over IPC.
+ * - ARG1 - destination virtual address in the source address space
+ * - ARG2 - size of data to be received, may be cropped by the recipient 
+ *
+ * on answer, the recipient must set:
+ *
+ * - ARG1 - source virtual address in the destination address space
+ * - ARG2 - final size of data to be copied
+ *
+ */
+#define IPC_M_DATA_READ  8
+
+/** Authorize change of recipient's state in a third party task.
+ * - ARG1 - user protocol defined data
+ * - ARG2 - user protocol defined data
+ * - ARG3 - user protocol defined data
+ * - ARG5 - sender's phone to the third party task
+ *
+ * on EOK answer, the recipient must set:
+ *
+ * - ARG1 - recipient's phone to the third party task
+ */
+#define IPC_M_STATE_CHANGE_AUTHORIZE	9
+
+/** Debug the recipient.
+ * - ARG1 - specifies the debug method (from udebug_method_t)
+ * - other arguments are specific to the debug method
+ *
+ */
+#define IPC_M_DEBUG 10
+
+/** Last system IPC method */
+#define IPC_M_LAST_SYSTEM  511
+
+#endif
+
+/** @}
+ */
Index: abi/include/mm/as.h
===================================================================
--- abi/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genericmm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_AS_H_
+#define ABI_AS_H_
+
+/** Address space area flags. */
+#define AS_AREA_READ       1
+#define AS_AREA_WRITE      2
+#define AS_AREA_EXEC       4
+#define AS_AREA_CACHEABLE  8
+
+/** Address space area info exported to uspace. */
+typedef struct {
+	/** Starting address */
+	uintptr_t start_addr;
+	
+	/** Area size */
+	size_t size;
+	
+	/** Area flags */
+	unsigned int flags;
+} as_area_info_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/proc/uarg.h
===================================================================
--- abi/include/proc/uarg.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/proc/uarg.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2006 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 genericproc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_PROC_UARG_H_
+#define ABI_PROC_UARG_H_
+
+/** Structure passed to uinit kernel thread as argument. */
+typedef struct uspace_arg {
+	void *uspace_entry;
+	void *uspace_stack;
+	
+	void (* uspace_thread_function)();
+	void *uspace_thread_arg;
+	
+	struct uspace_arg *uspace_uarg;
+} uspace_arg_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/synch.h
===================================================================
--- abi/include/synch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/synch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2001-2004 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 sync
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_SYNCH_H_
+#define ABI_SYNCH_H_
+
+/** Request with no timeout. */
+#define SYNCH_NO_TIMEOUT  0
+
+/** No flags specified. */
+#define SYNCH_FLAGS_NONE           0
+/** Non-blocking operation request. */
+#define SYNCH_FLAGS_NON_BLOCKING   (1 << 0)
+/** Interruptible operation. */
+#define SYNCH_FLAGS_INTERRUPTIBLE  (1 << 1)
+
+/** Could not satisfy the request without going to sleep. */
+#define ESYNCH_WOULD_BLOCK  1
+/** Timeout occurred. */
+#define ESYNCH_TIMEOUT      2
+/** Sleep was interrupted. */
+#define ESYNCH_INTERRUPTED  4
+/** Operation succeeded without sleeping. */
+#define ESYNCH_OK_ATOMIC    8
+/** Operation succeeded and did sleep. */
+#define ESYNCH_OK_BLOCKED   16
+
+#define SYNCH_FAILED(rc) \
+	((rc) & (ESYNCH_WOULD_BLOCK | ESYNCH_TIMEOUT | ESYNCH_INTERRUPTED))
+
+#define SYNCH_OK(rc) \
+	((rc) & (ESYNCH_OK_ATOMIC | ESYNCH_OK_BLOCKED))
+
+#endif
+
+/** @}
+ */
Index: abi/include/syscall.h
===================================================================
--- abi/include/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_SYSCALL_H_
+#define ABI_SYSCALL_H_
+
+typedef enum {
+	SYS_KLOG = 0,
+	SYS_TLS_SET = 1,  /* Hardcoded for AMD64, IA-32 (fibril.S in uspace) */
+	
+	SYS_THREAD_CREATE,
+	SYS_THREAD_EXIT,
+	SYS_THREAD_GET_ID,
+	SYS_THREAD_USLEEP,
+	SYS_THREAD_UDELAY,
+	
+	SYS_TASK_GET_ID,
+	SYS_TASK_SET_NAME,
+	SYS_TASK_KILL,
+	SYS_TASK_EXIT,
+	SYS_PROGRAM_SPAWN_LOADER,
+	
+	SYS_FUTEX_SLEEP,
+	SYS_FUTEX_WAKEUP,
+	SYS_SMC_COHERENCE,
+	
+	SYS_AS_AREA_CREATE,
+	SYS_AS_AREA_RESIZE,
+	SYS_AS_AREA_CHANGE_FLAGS,
+	SYS_AS_AREA_DESTROY,
+	SYS_AS_GET_UNMAPPED_AREA,
+	
+	SYS_PAGE_FIND_MAPPING,
+	
+	SYS_IPC_CALL_SYNC_FAST,
+	SYS_IPC_CALL_SYNC_SLOW,
+	SYS_IPC_CALL_ASYNC_FAST,
+	SYS_IPC_CALL_ASYNC_SLOW,
+	SYS_IPC_ANSWER_FAST,
+	SYS_IPC_ANSWER_SLOW,
+	SYS_IPC_FORWARD_FAST,
+	SYS_IPC_FORWARD_SLOW,
+	SYS_IPC_WAIT,
+	SYS_IPC_POKE,
+	SYS_IPC_HANGUP,
+	SYS_IPC_CONNECT_KBOX,
+	
+	SYS_EVENT_SUBSCRIBE,
+	SYS_EVENT_UNMASK,
+	
+	SYS_CAP_GRANT,
+	SYS_CAP_REVOKE,
+	
+	SYS_DEVICE_ASSIGN_DEVNO,
+	SYS_PHYSMEM_MAP,
+	SYS_IOSPACE_ENABLE,
+	SYS_REGISTER_IRQ,
+	SYS_UNREGISTER_IRQ,
+	
+	SYS_SYSINFO_GET_TAG,
+	SYS_SYSINFO_GET_VALUE,
+	SYS_SYSINFO_GET_DATA_SIZE,
+	SYS_SYSINFO_GET_DATA,
+	
+	SYS_DEBUG_ACTIVATE_CONSOLE,
+	
+	SYSCALL_END
+} syscall_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/sysinfo.h
===================================================================
--- abi/include/sysinfo.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/sysinfo.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2010 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.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ * Data structures passed between kernel sysinfo and user space.
+ */
+
+#ifndef ABI_SYSINFO_H_
+#define ABI_SYSINFO_H_
+
+/** Number of load components */
+#define LOAD_STEPS  3
+
+/** Maximum name sizes */
+#define TASK_NAME_BUFLEN  20
+#define EXC_NAME_BUFLEN   20
+
+/** Thread states */
+typedef enum {
+	/** It is an error, if thread is found in this state. */
+	Invalid,
+	/** State of a thread that is currently executing on some CPU. */
+	Running,
+	/** Thread in this state is waiting for an event. */
+	Sleeping,
+	/** State of threads in a run queue. */
+	Ready,
+	/** Threads are in this state before they are first readied. */
+	Entering,
+	/** After a thread calls thread_exit(), it is put into Exiting state. */
+	Exiting,
+	/** Threads that were not detached but exited are Lingering. */
+	Lingering
+} state_t;
+
+/** Statistics about a single CPU
+ *
+ */
+typedef struct {
+	unsigned int id;         /**< CPU ID as stored by kernel */
+	bool active;             /**< CPU is activate */
+	uint16_t frequency_mhz;  /**< Frequency in MHz */
+	uint64_t idle_cycles;    /**< Number of idle cycles */
+	uint64_t busy_cycles;    /**< Number of busy cycles */
+} stats_cpu_t;
+
+/** Physical memory statistics
+ *
+ */
+typedef struct {
+	uint64_t total;    /**< Total physical memory (bytes) */
+	uint64_t unavail;  /**< Unavailable (reserved, firmware) bytes */
+	uint64_t used;     /**< Allocated physical memory (bytes) */
+	uint64_t free;     /**< Free physical memory (bytes) */
+} stats_physmem_t;
+
+/** IPC statistics
+ *
+ * Associated with a task.
+ *
+ */
+typedef struct {
+	uint64_t call_sent;           /**< IPC calls sent */
+	uint64_t call_received;       /**< IPC calls received */
+	uint64_t answer_sent;         /**< IPC answers sent */
+	uint64_t answer_received;     /**< IPC answers received */
+	uint64_t irq_notif_received;  /**< IPC IRQ notifications */
+	uint64_t forwarded;           /**< IPC messages forwarded */
+} stats_ipc_t;
+
+/** Statistics about a single task
+ *
+ */
+typedef struct {
+	task_id_t task_id;            /**< Task ID */
+	char name[TASK_NAME_BUFLEN];  /**< Task name (in kernel) */
+	size_t virtmem;               /**< Size of VAS (bytes) */
+	size_t resmem;                /**< Size of resident (used) memory (bytes) */
+	size_t threads;               /**< Number of threads */
+	uint64_t ucycles;             /**< Number of CPU cycles in user space */
+	uint64_t kcycles;             /**< Number of CPU cycles in kernel */
+	stats_ipc_t ipc_info;         /**< IPC statistics */
+} stats_task_t;
+
+/** Statistics about a single thread
+ *
+ */
+typedef struct {
+	thread_id_t thread_id;  /**< Thread ID */
+	task_id_t task_id;      /**< Associated task ID */
+	state_t state;          /**< Thread state */
+	int priority;           /**< Thread priority */
+	uint64_t ucycles;       /**< Number of CPU cycles in user space */
+	uint64_t kcycles;       /**< Number of CPU cycles in kernel */
+	bool on_cpu;            /**< Associated with a CPU */
+	unsigned int cpu;       /**< Associated CPU ID (if on_cpu is true) */
+} stats_thread_t;
+
+/** Statistics about a single exception
+ *
+ */
+typedef struct {
+	unsigned int id;             /**< Exception ID */
+	char desc[EXC_NAME_BUFLEN];  /**< Description */
+	bool hot;                    /**< Active or inactive exception */
+	uint64_t cycles;             /**< Number of CPU cycles in the handler */
+	uint64_t count;              /**< Number of handled exceptions */
+} stats_exc_t;
+
+/** Load fixed-point value */
+typedef uint32_t load_t;
+
+#endif
+
+/** @}
+ */
Index: abi/include/udebug.h
===================================================================
--- abi/include/udebug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ abi/include/udebug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,184 @@
+/*
+ * 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 generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef ABI_UDEBUG_H_
+#define ABI_UDEBUG_H_
+
+#define UDEBUG_EVMASK(event)  (1 << ((event) - 1))
+
+typedef enum { /* udebug_method_t */
+	
+	/** Start debugging the recipient.
+	 *
+	 * Causes all threads in the receiving task to stop. When they
+	 * are all stoped, an answer with retval 0 is generated.
+	 *
+	 */
+	UDEBUG_M_BEGIN = 1,
+	
+	/** Finish debugging the recipient.
+	 *
+	 * Answers all pending GO and GUARD messages.
+	 *
+	 */
+	UDEBUG_M_END,
+	
+	/** Set which events should be captured. */
+	UDEBUG_M_SET_EVMASK,
+	
+	/** Make sure the debugged task is still there.
+	 *
+	 * This message is answered when the debugged task dies
+	 * or the debugging session ends.
+	 *
+	 */
+	UDEBUG_M_GUARD,
+	
+	/** Run a thread until a debugging event occurs.
+	 *
+	 * This message is answered when the thread stops
+	 * in a debugging event.
+	 *
+	 * - ARG2 - id of the thread to run
+	 *
+	 */
+	UDEBUG_M_GO,
+	
+	/** Stop a thread being debugged.
+	 *
+	 * Creates a special STOP event in the thread, causing
+	 * it to answer a pending GO message (if any).
+	 *
+	 */
+	UDEBUG_M_STOP,
+	
+	/** Read arguments of a syscall.
+	 *
+	 * - ARG2 - thread identification
+	 * - ARG3 - destination address in the caller's address space
+	 *
+	 */
+	UDEBUG_M_ARGS_READ,
+	
+	/** Read thread's userspace register state (istate_t).
+	 *
+	 * - ARG2 - thread identification
+	 * - ARG3 - destination address in the caller's address space
+	 *
+	 * or, on error, retval will be
+	 * - ENOENT - thread does not exist
+	 * - EBUSY - register state not available
+	 */
+	UDEBUG_M_REGS_READ,
+	
+	/** Read the list of the debugged tasks's threads.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a series of sysarg_t values
+	 * (thread ids). On answer, the kernel will set:
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_THREAD_READ,
+	
+	/** Read the name of the debugged task.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a non-terminated string.
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_NAME_READ,
+	
+	/** Read the list of the debugged task's address space areas.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - size of receiving buffer in bytes
+	 *
+	 * The kernel fills the buffer with a series of as_area_info_t structures.
+	 * Upon answer, the kernel will set:
+	 *
+	 * - ARG2 - number of bytes that were actually copied
+	 * - ARG3 - number of bytes of the complete data
+	 *
+	 */
+	UDEBUG_M_AREAS_READ,
+	
+	/** Read the debugged tasks's memory.
+	 *
+	 * - ARG2 - destination address in the caller's address space
+	 * - ARG3 - source address in the recipient's address space
+	 * - ARG4 - size of receiving buffer in bytes
+	 *
+	 */
+	UDEBUG_M_MEM_READ
+} udebug_method_t;
+
+typedef enum {
+	UDEBUG_EVENT_FINISHED = 1,  /**< Debuging session has finished */
+	UDEBUG_EVENT_STOP,          /**< Stopped on DEBUG_STOP request */
+	UDEBUG_EVENT_SYSCALL_B,     /**< Before beginning syscall execution */
+	UDEBUG_EVENT_SYSCALL_E,     /**< After finishing syscall execution */
+	UDEBUG_EVENT_THREAD_B,      /**< The task created a new thread */
+	UDEBUG_EVENT_THREAD_E       /**< A thread exited */
+} udebug_event_t;
+
+typedef enum {
+	UDEBUG_EM_FINISHED = UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED),
+	UDEBUG_EM_STOP = UDEBUG_EVMASK(UDEBUG_EVENT_STOP),
+	UDEBUG_EM_SYSCALL_B = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B),
+	UDEBUG_EM_SYSCALL_E = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E),
+	UDEBUG_EM_THREAD_B = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B),
+	UDEBUG_EM_THREAD_E = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E),
+	UDEBUG_EM_ALL =
+	    (UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_STOP) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B) |
+	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E))
+} udebug_evmask_t;
+
+#endif
+
+/** @}
+ */
Index: boot/Makefile
===================================================================
--- boot/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -50,8 +50,14 @@
 	$(MKFAT) 1048576 $(DIST_PATH) $@
 endif
+ifeq ($(RDFMT),ext2fs)
+	$(MKEXT2) 1048576 $(DIST_PATH) $@
+endif
 
 build_dist: clean_dist
 	for file in $(RD_SRVS) ; do \
 		cp "$$file" "$(DIST_PATH)/srv/" ; \
+	done
+	for file in $(RD_LIBS) ; do \
+		cp "$$file" "$(DIST_PATH)/lib/" ; \
 	done
 	for file in $(RD_APPS) ; do \
@@ -62,12 +68,16 @@
 	done
 	for drv in $(RD_DRVS) ; do \
-		mkdir -p "$(DIST_PATH)/$(DRVS_PATH)/$$drv" ; \
-		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$drv/$$drv" "$(DIST_PATH)/$(DRVS_PATH)/$$drv/$$drv" ; \
-		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$drv/$$drv.ma" "$(DIST_PATH)/$(DRVS_PATH)/$$drv/$$drv.ma" ; \
+		drv_dir="`dirname "$$drv"`" ; \
+		drv_name="`basename "$$drv"`" ; \
+		mkdir -p "$(DIST_PATH)/$(DRVS_PATH)/$$drv_name" ; \
+		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$drv_dir/$$drv_name/$$drv_name" "$(DIST_PATH)/$(DRVS_PATH)/$$drv_name/" ; \
+		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$drv_dir/$$drv_name/$$drv_name.ma" "$(DIST_PATH)/$(DRVS_PATH)/$$drv_name/" ; \
 	done
 	for file in $(RD_DRV_CFG) ; do \
-		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$file" "$(DIST_PATH)/$(DRVS_PATH)/$$file" ; \
+		file_dir="`dirname "$$file"`" ; \
+		file_name="`basename "$$file"`" ; \
+		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$file_dir/$$file_name/$$file_name.dev" "$(DIST_PATH)/$(DRVS_PATH)/$$file_name/" ; \
 	done
-	
+
 clean: clean_dist
 	$(MAKE) -f $(BUILD) clean PRECHECK=$(PRECHECK)
@@ -83,4 +93,5 @@
 	rm -f $(USPACE_PATH)/dist/srv/*
 	rm -rf $(USPACE_PATH)/dist/drv/*
+	rm -f $(USPACE_PATH)/dist/lib/*
 	rm -f $(USPACE_PATH)/dist/app/*
 	rm -f $(USPACE_PATH)/dist/cfg/net/*
Index: boot/Makefile.build
===================================================================
--- boot/Makefile.build	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/Makefile.build	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,5 +40,5 @@
 	-finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
 	-Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
-	-Werror-implicit-function-declaration -Wwrite-strings \
+	-std=gnu99 -Werror-implicit-function-declaration -Wwrite-strings \
 	-pipe
 
@@ -111,5 +111,5 @@
 
 $(RAW): $(OBJECTS) $(COMPONENT_OBJECTS) $(LINK)
-	$(LD) -N $(LFLAGS) -T $(LINK) -M -Map $(MAP) -o $@ $(COMPONENT_OBJECTS) $(OBJECTS)
+	$(LD) -n $(LFLAGS) -T $(LINK) -M -Map $(MAP) -o $@ $(COMPONENT_OBJECTS) $(OBJECTS)
 
 $(LINK): $(LINK).comp $(DEPEND)
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/Makefile.common	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -56,4 +56,5 @@
 MKTMPFS = $(TOOLS_PATH)/mktmpfs.py
 MKFAT = $(TOOLS_PATH)/mkfat.py
+MKEXT2 = $(TOOLS_PATH)/mkext2.py
 MKUIMAGE = $(TOOLS_PATH)/mkuimage.py
 
@@ -72,5 +73,5 @@
 	$(USPACE_PATH)/srv/loader/loader \
 	$(USPACE_PATH)/app/init/init \
-	$(USPACE_PATH)/srv/devmap/devmap \
+	$(USPACE_PATH)/srv/loc/loc \
 	$(USPACE_PATH)/srv/bd/rd/rd \
 	$(USPACE_PATH)/srv/vfs/vfs
@@ -84,9 +85,13 @@
 endif
 
+ifeq ($(RDFMT),ext2fs)
+	INIT_TASKS += $(USPACE_PATH)/srv/fs/ext2fs/ext2fs
+endif
+
 RD_SRVS_ESSENTIAL = \
 	$(USPACE_PATH)/srv/hid/fb/fb \
-	$(USPACE_PATH)/srv/hid/kbd/kbd \
+	$(USPACE_PATH)/srv/hid/input/input \
 	$(USPACE_PATH)/srv/hid/console/console \
-	$(USPACE_PATH)/srv/fs/devfs/devfs
+	$(USPACE_PATH)/srv/fs/locfs/locfs
 
 RD_SRVS_NON_ESSENTIAL = \
@@ -97,4 +102,5 @@
 	$(USPACE_PATH)/srv/fs/tmpfs/tmpfs \
 	$(USPACE_PATH)/srv/fs/fat/fat \
+	$(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
 	$(USPACE_PATH)/srv/taskmon/taskmon \
 	$(USPACE_PATH)/srv/hw/netif/ne2000/ne2000 \
@@ -109,12 +115,23 @@
 	$(USPACE_PATH)/srv/net/net/net \
 	$(USPACE_PATH)/srv/devman/devman
-	
+
 RD_DRVS = \
-	root \
-	rootvirt \
-	test1 \
-	test2
-
-RD_DRV_CFG = 
+	infrastructure/root \
+	infrastructure/rootvirt \
+	test/test1 \
+	test/test2 \
+	test/test3
+
+RD_DRV_CFG =
+
+RD_LIBS =
+
+ifeq ($(CONFIG_BUILD_SHARED_LIBS), y)
+	RD_LIBS += \
+		$(USPACE_PATH)/lib/c/libc.so0 \
+		$(USPACE_PATH)/lib/softint/libsofti.so0
+	RD_APPS += \
+		$(USPACE_PATH)/app/dltest/dltest
+endif
 
 RD_APPS_ESSENTIAL = \
@@ -124,12 +141,22 @@
 
 RD_APPS_NON_ESSENTIAL = \
+	$(USPACE_PATH)/app/blkdump/blkdump \
+	$(USPACE_PATH)/app/bnchmark/bnchmark \
+	$(USPACE_PATH)/app/devctl/devctl \
+	$(USPACE_PATH)/app/dltest/dltest \
+	$(USPACE_PATH)/app/dltest2/dltest2 \
+	$(USPACE_PATH)/app/dload/dload \
 	$(USPACE_PATH)/app/edit/edit \
+	$(USPACE_PATH)/app/ext2info/ext2info \
 	$(USPACE_PATH)/app/kill/kill \
 	$(USPACE_PATH)/app/killall/killall \
+	$(USPACE_PATH)/app/locinfo/locinfo \
 	$(USPACE_PATH)/app/mkfat/mkfat \
+	$(USPACE_PATH)/app/lsusb/lsusb \
 	$(USPACE_PATH)/app/sbi/sbi \
 	$(USPACE_PATH)/app/redir/redir \
 	$(USPACE_PATH)/app/taskdump/taskdump \
 	$(USPACE_PATH)/app/tester/tester \
+	$(USPACE_PATH)/app/testread/testread \
 	$(USPACE_PATH)/app/tetris/tetris \
 	$(USPACE_PATH)/app/trace/trace \
@@ -139,6 +166,9 @@
 	$(USPACE_PATH)/app/ping/ping \
 	$(USPACE_PATH)/app/stats/stats \
+	$(USPACE_PATH)/app/sysinfo/sysinfo \
 	$(USPACE_PATH)/app/top/top \
-	$(USPACE_PATH)/app/sysinfo/sysinfo \
+	$(USPACE_PATH)/app/usbinfo/usbinfo \
+	$(USPACE_PATH)/app/vuhid/vuh \
+	$(USPACE_PATH)/app/mkbd/mkbd \
 	$(USPACE_PATH)/app/websrv/websrv
 
Index: boot/Makefile.silo
===================================================================
--- boot/Makefile.silo	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/Makefile.silo	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -31,9 +31,5 @@
 include Makefile.common
 
-ifeq ($(CONFIG_AOUT_ISOFS_B),y)
-	SILO_PACKAGE = a.out
-else
-	SILO_PACKAGE = raw
-endif
+SILO_PACKAGE = a.out
 
 ISOFS_B = silo/$(SILO_PACKAGE)/isofs.b
Index: boot/Makefile.uboot
===================================================================
--- boot/Makefile.uboot	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/Makefile.uboot	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -31,6 +31,6 @@
 include Makefile.common
 
-IMAGE_NAME=HelenOS-$(RELEASE)
-BIN_OUTPUT=image.bin
+IMAGE_NAME = HelenOS-$(RELEASE)
+BIN_OUTPUT = image.bin
 
 all: $(POST_OUTPUT)
@@ -40,6 +40,5 @@
 
 $(POST_OUTPUT): $(BIN_OUTPUT)
-	$(MKUIMAGE) -name "$(IMAGE_NAME)" -laddr 0x30008000 -saddr 0x30008000 \
-    $< $@
+	$(MKUIMAGE) -name "$(IMAGE_NAME)" -laddr 0x30008000 -saddr 0x30008000 $< $@
 
 clean:
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/amd64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,15 +35,25 @@
 
 RD_SRVS_NON_ESSENTIAL += \
-	$(USPACE_PATH)/srv/bd/ata_bd/ata_bd \
-	$(USPACE_PATH)/srv/hid/char_mouse/char_ms
+	$(USPACE_PATH)/srv/bd/ata_bd/ata_bd
 
 RD_DRVS += \
-	rootpc \
-	pciintel \
-	isa \
-	ns8250
+	infrastructure/rootpc \
+	bus/pci/pciintel \
+	bus/isa \
+	char/ns8250 \
+	bus/usb/ehci\
+	bus/usb/ohci \
+	bus/usb/uhci \
+	bus/usb/uhcirh \
+	bus/usb/usbflbk \
+	bus/usb/usbhub \
+	bus/usb/usbhid \
+	bus/usb/usbmast \
+	bus/usb/usbmid \
+	bus/usb/usbmouse \
+	bus/usb/vhc
 
 RD_DRV_CFG += \
-	isa/isa.dev
+	bus/isa
 
 BOOT_OUTPUT = $(ROOT_PATH)/image.iso
Index: boot/arch/ia64/Makefile.inc
===================================================================
--- boot/arch/ia64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/ia64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,6 +45,11 @@
 	arch/$(BARCH)/src/asm.S \
 	arch/$(BARCH)/src/main.c \
+	arch/$(BARCH)/src/sal.c \
+	arch/$(BARCH)/src/sal_asm.S \
+	arch/$(BARCH)/src/pal.c \
+	arch/$(BARCH)/src/pal_asm.S \
 	arch/$(BARCH)/src/putchar.c \
 	$(COMPS_C) \
+	genarch/src/efi.c \
 	genarch/src/division.c \
 	generic/src/balloc.c \
Index: boot/arch/ia64/_link.ld.in
===================================================================
--- boot/arch/ia64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/ia64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -11,6 +11,6 @@
 		*(.rodata);
 		*(.rodata.*);
-		*(.data);               /* initialized data */
-		_got = . ;
+		*(.data .data.*);       /* initialized data */
+		__gp = . ;
 		*(.got .got.*);
 		*(.bss);                /* uninitialized static variables */
@@ -20,6 +20,5 @@
 
 	/DISCARD/ : {
-		*(.comment);
-		*(.note*);
+		*(.*);
 	}
 }
Index: boot/arch/ia64/include/pal.h
===================================================================
--- boot/arch/ia64/include/pal.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/ia64/include/pal.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#ifndef BOOT_ia64_PAL_H_
+#define BOOT_ia64_PAL_H_
+
+#include <arch/types.h>
+#include <typedefs.h>
+
+/*
+ * Essential PAL procedures' IDs
+ */
+#define PAL_FREQ_RATIOS		14	
+
+extern uint64_t pal_proc_freq_ratio(void);
+
+#define pal_static_call_0_1(id, ret1) \
+	pal_static_call((id), 0, 0, 0, (ret1), NULL, NULL)
+
+extern uint64_t pal_static_call(uint64_t, uint64_t, uint64_t, uint64_t,
+    uint64_t *, uint64_t *, uint64_t *);
+
+#endif
Index: boot/arch/ia64/include/sal.h
===================================================================
--- boot/arch/ia64/include/sal.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/ia64/include/sal.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#ifndef BOOT_ia64_SAL_H_
+#define BOOT_ia64_SAL_H_
+
+#include <arch/types.h>
+#include <typedefs.h>
+
+/*
+ * Essential SAL procedures' IDs
+ */
+#define SAL_FREQ_BASE	0x1000012
+
+typedef struct {
+	uint8_t signature[4];
+	uint32_t total_length;
+	uint16_t sal_revision;
+	uint16_t entry_count;
+	uint8_t checksum;
+	uint8_t reserved1[7];
+	uint16_t sal_a_version;
+	uint16_t sal_b_version;
+	uint8_t oem_id[32];
+	uint8_t product_id[32];
+	uint8_t reserved2[8];
+} sal_system_table_header_t;
+
+typedef enum {
+	SSTT_ENTRYPOINT_DESC,
+	SSTT_MEMORY_DESC,
+	SSTT_PLATFORM_FEATURES_DESC,
+	SSTT_TR_DESC,
+	SSTT_PTC_COHERENCE_DOMAIN_DESC,
+	SSTT_AP_WAKEUP_DESC
+} sal_sst_type_t;
+
+typedef struct {
+	uint8_t type;
+	uint8_t reserved1[7];
+	uint64_t pal_proc;
+	uint64_t sal_proc;
+	uint64_t sal_proc_gp;
+	uint8_t reserved2[16];
+} sal_entrypoint_desc_t;
+
+/* This descriptor is unused on Itanium systems. */
+typedef struct {
+	uint8_t type;
+	uint8_t unused[31];
+} sal_memory_desc_t;
+
+typedef struct {
+	uint8_t type;
+	uint8_t features;
+	uint8_t reserved[14];
+} sal_platform_features_desc_t;
+
+typedef struct {
+	uint8_t type;
+	uint8_t tr_type;
+	uint8_t tr_number;
+	uint8_t reserved1[5];
+	uint64_t va;
+	uint64_t psc;
+	uint8_t reserved2[8];
+} sal_tr_desc_t;
+
+typedef struct {
+	uint8_t type;
+	uint8_t reserved[3];
+	uint32_t coherence_domains;
+	uint64_t coherence_domain_info;
+} sal_ptc_coherence_domain_desc_t;
+
+typedef struct {
+	uint8_t type;
+	uint8_t mechanism;
+	uint8_t reserved[6];
+	uint64_t vector;
+} sal_ap_wakeup_desc_t;
+
+extern void sal_system_table_parse(sal_system_table_header_t *);
+
+extern uint64_t sal_base_clock_frequency(void);
+
+#define sal_call_1_1(id, arg1, ret1) \
+	sal_call((id), (arg1), 0, 0, 0, 0, 0, 0, (ret1), NULL, NULL)
+
+extern uint64_t sal_call(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
+    uint64_t, uint64_t, uint64_t, uint64_t *, uint64_t *, uint64_t *);
+
+#endif
Index: boot/arch/ia64/include/types.h
===================================================================
--- boot/arch/ia64/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/ia64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,7 +30,9 @@
 #define BOOT_ia64_TYPES_H_
 
+#include <arch/common.h>
+
 #define TASKMAP_MAX_RECORDS		32
 #define BOOTINFO_TASK_NAME_BUFLEN	32
-#define MEMMAP_ITEMS			128	
+#define MEMMAP_ITEMS			128
 
 typedef uint64_t size_t;
@@ -53,10 +55,10 @@
 	unsigned long base;
 	unsigned long size;
-} efi_memmap_item_t;
+} memmap_item_t;
 
 typedef struct {
 	binit_t taskmap;
 
-	efi_memmap_item_t memmap[MEMMAP_ITEMS];
+	memmap_item_t memmap[MEMMAP_ITEMS];
 	unsigned int memmap_items;
 
@@ -65,6 +67,14 @@
 	unsigned long freq_scale;
 	unsigned int wakeup_intno;
-	int hello_configured;
 } bootinfo_t;
 
+/** This is a minimal ELILO-compatible boot parameter structure. */
+typedef struct {
+	uint64_t cmd_line;
+	uint64_t efi_system_table;
+	uint64_t efi_memmap;
+	uint64_t efi_memmap_sz;
+	uint64_t efi_memdesc_sz;
+} boot_param_t;
+
 #endif
Index: boot/arch/ia64/src/boot.S
===================================================================
--- boot/arch/ia64/src/boot.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/ia64/src/boot.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,5 +34,12 @@
 .global start
 start:
-	movl gp = LOADER_ADDRESS
+	movl gp = __gp
+
+	#
+	# Save the boot parameter structure address passed from the
+	# ELILO-compatible EFI loader.
+	#
+	movl r8 = bootpar ;;
+	st8 [r8] = r28
 
 	#
@@ -62,4 +69,8 @@
 .bss
 
+.global bootpar
+bootpar:
+	.quad 0
+
 .align STACK_SIZE
 initial_stack:
Index: boot/arch/ia64/src/main.c
===================================================================
--- boot/arch/ia64/src/main.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/ia64/src/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,7 +30,11 @@
 
 #include <arch/main.h>
+#include <arch/types.h>
 #include <arch/arch.h>
 #include <arch/asm.h>
 #include <arch/_components.h>
+#include <genarch/efi.h>
+#include <arch/sal.h>
+#include <arch/pal.h>
 #include <halt.h>
 #include <printf.h>
@@ -51,9 +55,95 @@
 #define DEFAULT_SYS_FREQ		100000000ULL		/* 100MHz */
 
-#define EFI_MEMMAP_FREE_MEM		0
-#define EFI_MEMMAP_IO			1
-#define EFI_MEMMAP_IO_PORTS		2
+#define MEMMAP_FREE_MEM		0
+#define MEMMAP_IO		1
+#define MEMMAP_IO_PORTS		2
+
+extern boot_param_t *bootpar;
 
 static bootinfo_t bootinfo;
+
+static void read_efi_memmap(void)
+{
+	memmap_item_t *memmap = bootinfo.memmap;
+	size_t items = 0;
+	
+	if (!bootpar) {
+		/* Fake-up a memory map for simulators. */
+		memmap[items].base = DEFAULT_MEMORY_BASE;
+		memmap[items].size = DEFAULT_MEMORY_SIZE;
+		memmap[items].type = MEMMAP_FREE_MEM;
+		items++;
+
+		memmap[items].base = DEFAULT_LEGACY_IO_BASE;
+		memmap[items].size = DEFAULT_LEGACY_IO_SIZE;
+		memmap[items].type = MEMMAP_IO_PORTS;
+		items++;		 
+	} else {
+		char *cur, *mm_base = (char *) bootpar->efi_memmap;
+		size_t mm_size = bootpar->efi_memmap_sz;
+		size_t md_size = bootpar->efi_memdesc_sz;
+		
+		/*
+		 * Walk the EFI memory map using the V1 memory descriptor
+		 * format. The actual memory descriptor can use newer format,
+		 * but it must always be backwards compatible with the V1
+		 * format.
+		 */
+		for (cur = mm_base;
+		    (cur < mm_base + (mm_size - md_size)) &&
+		    (items < MEMMAP_ITEMS);
+		    cur += md_size) {
+			efi_v1_memdesc_t *md = (efi_v1_memdesc_t *) cur;
+
+			switch ((efi_memory_type_t) md->type) {
+			case EFI_CONVENTIONAL_MEMORY:
+				memmap[items].type = MEMMAP_FREE_MEM;
+				break;
+			case EFI_MEMORY_MAPPED_IO:
+				memmap[items].type = MEMMAP_IO;
+				break;
+			case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
+				memmap[items].type = MEMMAP_IO_PORTS;
+				break;
+			default:
+				continue;
+			}
+			
+			memmap[items].base = md->phys_start;
+			memmap[items].size = md->pages * EFI_PAGE_SIZE;
+			items++;
+		}
+	}
+	
+	bootinfo.memmap_items = items;
+}
+
+static void read_pal_configuration(void)
+{
+	if (bootpar) {
+		bootinfo.freq_scale = pal_proc_freq_ratio();
+	} else {
+		/* Configure default values for simulators. */
+		bootinfo.freq_scale = DEFAULT_FREQ_SCALE;
+	}
+}
+
+static void read_sal_configuration(void)
+{
+	if (bootpar && bootpar->efi_system_table) {
+		efi_guid_t sal_guid = SAL_SYSTEM_TABLE_GUID;
+		sal_system_table_header_t *sal_st;
+		
+		sal_st = efi_vendor_table_find(
+		    (efi_system_table_t *) bootpar->efi_system_table, sal_guid);
+
+		sal_system_table_parse(sal_st);
+		
+		bootinfo.sys_freq = sal_base_clock_frequency();
+	} else {
+		/* Configure default values for simulators. */
+		bootinfo.sys_freq = DEFAULT_SYS_FREQ;
+	}
+}
 
 void bootstrap(void)
@@ -113,31 +203,8 @@
 	
 	printf(".\n");
-	
-	if (!bootinfo.hello_configured) {	/* XXX */
-		/*
-		 * Load configuration defaults for simulators.
-		 */
-		 bootinfo.memmap_items = 0;
-		 
-		 bootinfo.memmap[bootinfo.memmap_items].base =
-		     DEFAULT_MEMORY_BASE;
-		 bootinfo.memmap[bootinfo.memmap_items].size =
-		     DEFAULT_MEMORY_SIZE;
-		 bootinfo.memmap[bootinfo.memmap_items].type =
-		     EFI_MEMMAP_FREE_MEM;
-		 bootinfo.memmap_items++;
-
-		 bootinfo.memmap[bootinfo.memmap_items].base =
-		     DEFAULT_LEGACY_IO_BASE;
-		 bootinfo.memmap[bootinfo.memmap_items].size =
-		     DEFAULT_LEGACY_IO_SIZE;
-		 bootinfo.memmap[bootinfo.memmap_items].type =
-		     EFI_MEMMAP_IO_PORTS;
-		 bootinfo.memmap_items++;
-		 
-		 bootinfo.freq_scale = DEFAULT_FREQ_SCALE;
-		 bootinfo.sys_freq = DEFAULT_SYS_FREQ;
-	}
-	
+
+	read_efi_memmap();
+	read_sal_configuration();
+	read_pal_configuration();
 	
 	printf("Booting the kernel ...\n");
Index: boot/arch/ia64/src/pal.c
===================================================================
--- boot/arch/ia64/src/pal.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/ia64/src/pal.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <arch/pal.h>
+#include <arch/types.h>
+
+uint64_t pal_proc = 0;
+
+uint64_t pal_proc_freq_ratio(void)
+{
+	uint64_t proc_ratio;
+	
+	pal_static_call_0_1(PAL_FREQ_RATIOS, &proc_ratio);
+	
+	return proc_ratio;
+}
Index: boot/arch/ia64/src/pal_asm.S
===================================================================
--- boot/arch/ia64/src/pal_asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/ia64/src/pal_asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2011 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.
+#
+
+.explicit
+
+.global pal_static_call
+
+pal_static_call:
+	alloc loc0 = ar.pfs, 7, 5, 0, 0
+	
+	mov loc1 = gp
+	mov loc2 = rp
+	
+	addl loc3 = @gprel(pal_proc), gp
+	
+	mov r28 = in0
+	mov r29 = in1
+	mov r30 = in2
+	mov r31 = in3 ;;
+	
+	ld8 loc3 = [loc3]
+	movl loc4 = 0f ;;
+
+	mov b6 = loc3
+	mov rp = loc4 ;;
+	br.cond.sptk.many b6
+
+0:
+	cmp.ne p7,p0 = 0, in4
+	cmp.ne p8,p0 = 0, in5
+	cmp.ne p9,p0 = 0, in6 ;;
+	
+(p7)	st8 [in4] = r9
+(p8)	st8 [in5] = r10
+(p9)	st8 [in6] = r11
+	
+	mov gp = loc1
+	mov rp = loc2 ;;
+	
+	mov ar.pfs = loc0
+	br.ret.sptk.many rp
+
Index: boot/arch/ia64/src/sal.c
===================================================================
--- boot/arch/ia64/src/sal.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/ia64/src/sal.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <arch/sal.h>
+#include <arch/types.h>
+
+static sal_ap_wakeup_desc_t *sal_ap_wakeup;
+
+extern uint64_t pal_proc;
+
+uint64_t sal_proc = 0;
+uint64_t sal_proc_gp = 0;
+
+void sal_system_table_parse(sal_system_table_header_t *sst)
+{
+	uint8_t *cur = (uint8_t *) &sst[1];
+	uint16_t entry;
+
+	for (entry = 0; entry < sst->entry_count; entry++) {
+		switch ((sal_sst_type_t) *cur) {
+		case SSTT_ENTRYPOINT_DESC:
+			pal_proc = ((sal_entrypoint_desc_t *) cur)->pal_proc;
+			sal_proc = ((sal_entrypoint_desc_t *) cur)->sal_proc;
+			sal_proc_gp = ((sal_entrypoint_desc_t *) cur)->sal_proc_gp;
+			cur += sizeof(sal_entrypoint_desc_t);
+			break;
+		case SSTT_MEMORY_DESC:
+			cur += sizeof(sal_memory_desc_t);
+			break;
+		case SSTT_PLATFORM_FEATURES_DESC:
+			cur += sizeof(sal_platform_features_desc_t);
+			break;
+		case SSTT_TR_DESC:
+			cur += sizeof(sal_tr_desc_t);
+			break;
+		case SSTT_PTC_COHERENCE_DOMAIN_DESC:
+			cur += sizeof(sal_ptc_coherence_domain_desc_t);
+			break;
+		case SSTT_AP_WAKEUP_DESC:
+			sal_ap_wakeup = (sal_ap_wakeup_desc_t *) cur;
+			cur += sizeof(sal_ap_wakeup_desc_t);
+			break;
+		default:
+			return;
+		}
+	}
+}
+
+uint64_t sal_base_clock_frequency(void)
+{
+	uint64_t freq;
+	
+	sal_call_1_1(SAL_FREQ_BASE, 0, &freq);
+	
+	return freq;
+}
Index: boot/arch/ia64/src/sal_asm.S
===================================================================
--- boot/arch/ia64/src/sal_asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/ia64/src/sal_asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,76 @@
+#
+# Copyright (c) 2011 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.
+#
+
+.explicit
+
+.global sal_call
+
+#
+# Assume the following PSR bits are already 0, as expected by SAL:
+#
+#  be, cpl, is, da, dd, ss, ri, ed, ia
+#
+# Assume PSR.bn is 1, as expected by SAL.
+#
+sal_call:
+	alloc loc0 = ar.pfs, 11, 5, 8, 0
+	
+	mov loc1 = gp
+	mov loc2 = rp
+	
+	addl loc3 = @gprel(sal_proc), gp
+	addl loc4 = @gprel(sal_proc_gp), gp
+	
+	mov out0 = in0
+	mov out1 = in1
+	mov out2 = in2
+	mov out3 = in3
+	mov out4 = in4
+	mov out5 = in5
+	mov out6 = in6
+	mov out7 = in7 ;;
+	
+	ld8 loc3 = [loc3]
+	ld8 gp = [loc4] ;;
+	
+	mov b6 = loc3 ;;
+	br.call.sptk.many rp = b6
+	
+	cmp.ne p7,p0 = 0, in8
+	cmp.ne p8,p0 = 0, in9
+	cmp.ne p9,p0 = 0, in10 ;;
+	
+(p7)	st8 [in8] = r9
+(p8)	st8 [in9] = r10
+(p9)	st8 [in10] = r11
+	
+	mov gp = loc1
+	mov rp = loc2 ;;
+	
+	mov ar.pfs = loc0
+	br.ret.sptk.many rp
Index: boot/arch/mips32/Makefile.inc
===================================================================
--- boot/arch/mips32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/mips32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,7 +30,5 @@
 BITS = 32
 PAGE_SIZE = 16384
-EXTRA_CFLAGS = -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3
-
-RD_SRVS_ESSENTIAL +=
+EXTRA_CFLAGS = -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=32
 
 RD_SRVS_NON_ESSENTIAL += \
Index: boot/arch/mips32/src/asm.S
===================================================================
--- boot/arch/mips32/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/mips32/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,5 +44,5 @@
 	 * Setup the CP0 configuration
 	 *  - Disable 64-bit kernel addressing mode
-	 *  - DIsable 64-bit supervisor adressing mode
+	 *  - Disable 64-bit supervisor adressing mode
 	 *  - Disable 64-bit user addressing mode
 	 */
Index: boot/arch/mips64/Makefile.inc
===================================================================
--- boot/arch/mips64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2006 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.
+#
+
+BFD_ARCH = mips:4000
+BITS = 64
+PAGE_SIZE = 16384
+EXTRA_CFLAGS = -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=64
+
+ifeq ($(MACHINE),msim)
+	BFD_NAME = elf64-tradlittlemips
+	BFD_OUTPUT = binary
+	ENDIANESS = LE
+	EXTRA_GCC_CFLAGS = -mhard-float
+endif
+
+SOURCES = \
+	arch/$(BARCH)/src/asm.S \
+	arch/$(BARCH)/src/main.c \
+	arch/$(BARCH)/src/putchar.c \
+	$(COMPS_C) \
+	genarch/src/division.c \
+	genarch/src/multiplication.c \
+	generic/src/memstr.c \
+	generic/src/printf_core.c \
+	generic/src/vprintf.c \
+	generic/src/printf.c \
+	generic/src/str.c \
+	generic/src/version.c \
+	generic/src/inflate.c
Index: boot/arch/mips64/_link.ld.in
===================================================================
--- boot/arch/mips64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,30 @@
+OUTPUT_FORMAT(elf64-tradlittlemips)
+ENTRY(start)
+
+SECTIONS {
+	. = 0xffffffffbfc00000;
+	.text : {
+		*(BOOTSTRAP);
+		*(.text);
+	}
+	.data : {
+		*(.data);       /* initialized data */
+		*(.rodata);
+		*(.rodata.*);
+		*(.sdata);
+		*(.reginfo);
+		*(.sbss);
+		*(.scommon);
+		*(.bss);        /* uninitialized static variables */
+		*(COMMON);      /* global variables */
+[[COMPONENTS]]
+	}
+	
+	/DISCARD/ : {
+		*(.gnu.*);
+		*(.mdebug*);
+		*(.pdr);
+		*(.comment);
+		*(.note);
+	}
+}
Index: boot/arch/mips64/include/arch.h
===================================================================
--- boot/arch/mips64/include/arch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/include/arch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+#ifndef BOOT_mips64_ARCH_H_
+#define BOOT_mips64_ARCH_H_
+
+#define PAGE_WIDTH  14
+#define PAGE_SIZE   (1 << PAGE_WIDTH)
+
+#define CPUMAP_OFFSET    0x00001000
+#define STACK_OFFSET     0x00002000
+#define BOOTINFO_OFFSET  0x00003000
+#define BOOT_OFFSET      0x00100000
+#define LOADER_OFFSET    0x1fc00000
+
+#define MSIM_VIDEORAM_ADDRESS  0xffffffffb0000000
+#define MSIM_DORDER_ADDRESS    0xffffffffb0000100
+
+#ifndef __ASM__
+	#define PA2KA(addr)    (((uintptr_t) (addr)) + 0xffffffff80000000)
+	#define KSEG2PA(addr)  (((uintptr_t) (addr)) - 0xffffffffa0000000)
+#else
+	#define PA2KA(addr)    ((addr) + 0xffffffff80000000)
+	#define KSEG2PA(addr)  ((addr) - 0xffffffffa0000000)
+#endif
+
+#endif
Index: boot/arch/mips64/include/asm.h
===================================================================
--- boot/arch/mips64/include/asm.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/include/asm.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/asm.h
Index: boot/arch/mips64/include/main.h
===================================================================
--- boot/arch/mips64/include/main.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/include/main.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/main.h
Index: boot/arch/mips64/include/regname.h
===================================================================
--- boot/arch/mips64/include/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/include/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/regname.h
Index: boot/arch/mips64/include/types.h
===================================================================
--- boot/arch/mips64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+#ifndef BOOT_mips64_TYPES_H_
+#define BOOT_mips64_TYPES_H_
+
+#define TASKMAP_MAX_RECORDS        32
+#define CPUMAP_MAX_RECORDS         32
+#define BOOTINFO_TASK_NAME_BUFLEN  32
+
+typedef uint64_t size_t;
+typedef uint64_t uintptr_t;
+
+typedef struct {
+	/** Address where the task was placed. */
+	void *addr;
+	/** Size of the task's binary. */
+	size_t size;
+	/** Task name. */
+	char name[BOOTINFO_TASK_NAME_BUFLEN];
+} task_t;
+
+typedef struct {
+	uint32_t cpumap;
+	size_t cnt;
+	task_t tasks[TASKMAP_MAX_RECORDS];
+} bootinfo_t;
+
+#endif
Index: boot/arch/mips64/src/asm.S
===================================================================
--- boot/arch/mips64/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,150 @@
+#
+# Copyright (c) 2006 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.
+#
+
+#include <arch/arch.h>
+#include <arch/regname.h>
+
+.set noat
+.set noreorder
+.set nomacro
+
+.global start
+.global halt
+.global jump_to_kernel
+
+.section BOOTSTRAP
+
+start:
+	/*
+	 * Setup the CP0 configuration
+	 *  - Enable 64-bit kernel addressing mode
+	 *  - Enable 64-bit supervisor adressing mode
+	 *  - Enable 64-bit user addressing mode
+	 */
+	mfc0 $a0, $status
+	ori $a0, 0x00e0
+	mtc0 $a0, $status
+	
+	/*
+	 * Setup CPU map (on msim this code
+	 * is executed in parallel on all CPUs,
+	 * but it not an issue).
+	 */
+	dla $a0, PA2KA(CPUMAP_OFFSET)
+	
+	sw $zero, 0($a0)
+	sw $zero, 4($a0)
+	sw $zero, 8($a0)
+	sw $zero, 12($a0)
+	
+	sw $zero, 16($a0)
+	sw $zero, 20($a0)
+	sw $zero, 24($a0)
+	sw $zero, 28($a0)
+	
+	sw $zero, 32($a0)
+	sw $zero, 36($a0)
+	sw $zero, 40($a0)
+	sw $zero, 44($a0)
+	
+	sw $zero, 48($a0)
+	sw $zero, 52($a0)
+	sw $zero, 56($a0)
+	sw $zero, 60($a0)
+	
+	sw $zero, 64($a0)
+	sw $zero, 68($a0)
+	sw $zero, 72($a0)
+	sw $zero, 76($a0)
+	
+	sw $zero, 80($a0)
+	sw $zero, 84($a0)
+	sw $zero, 88($a0)
+	sw $zero, 92($a0)
+	
+	sw $zero, 96($a0)
+	sw $zero, 100($a0)
+	sw $zero, 104($a0)
+	sw $zero, 108($a0)
+	
+	sw $zero, 112($a0)
+	sw $zero, 116($a0)
+	sw $zero, 120($a0)
+	sw $zero, 124($a0)
+	
+	lui $a1, 1
+	
+#ifdef MACHINE_msim
+	
+	/* Read dorder value */
+	dla $k0, MSIM_DORDER_ADDRESS
+	lw $k1, ($k0)
+	
+	/*
+	 * If we are not running on BSP
+	 * then end in an infinite loop.
+	 */
+	beq $k1, $zero, bsp
+	nop
+	
+	/* Record CPU presence */
+	sll $a2, $k1, 2
+	addu $a2, $a2, $a0
+	sw $a1, ($a2)
+	
+	loop:
+		j loop
+		nop
+	
+#endif
+	
+	bsp:
+		/* Record CPU presence */
+		sw $a1, ($a0)
+		
+		/* Setup initial stack */
+		dla $sp, PA2KA(STACK_OFFSET)
+		
+		j bootstrap
+		nop
+
+.text
+
+halt:
+	j halt
+	nop
+
+jump_to_kernel:
+	/*
+	 * TODO:
+	 *
+	 * Make sure that the I-cache, D-cache and memory are mutually
+	 * coherent before passing control to the copied code.
+	 */
+	j $a0
+	nop
Index: boot/arch/mips64/src/main.c
===================================================================
--- boot/arch/mips64/src/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/src/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch/main.h>
+#include <arch/arch.h>
+#include <arch/asm.h>
+#include <arch/_components.h>
+#include <halt.h>
+#include <printf.h>
+#include <memstr.h>
+#include <version.h>
+#include <macros.h>
+#include <align.h>
+#include <str.h>
+#include <errno.h>
+#include <inflate.h>
+
+#define TOP2ADDR(top)  (((void *) PA2KA(BOOT_OFFSET)) + (top))
+
+static bootinfo_t *bootinfo = (bootinfo_t *) PA2KA(BOOTINFO_OFFSET);
+static uint32_t *cpumap = (uint32_t *) PA2KA(CPUMAP_OFFSET);
+
+void bootstrap(void)
+{
+	version_print();
+	
+	printf("\nMemory statistics\n");
+	printf(" %p|%p: CPU map\n", (void *) PA2KA(CPUMAP_OFFSET),
+	    (void *) CPUMAP_OFFSET);
+	printf(" %p|%p: bootstrap stack\n", (void *) PA2KA(STACK_OFFSET),
+	    (void *) STACK_OFFSET);
+	printf(" %p|%p: boot info structure\n",
+	    (void *) PA2KA(BOOTINFO_OFFSET), (void *) BOOTINFO_OFFSET);
+	printf(" %p|%p: kernel entry point\n", (void *) PA2KA(BOOT_OFFSET),
+	    (void *) BOOT_OFFSET);
+	printf(" %p|%p: bootloader entry point\n",
+	    (void *) PA2KA(LOADER_OFFSET), (void *) LOADER_OFFSET);
+	
+	size_t i;
+	for (i = 0; i < COMPONENTS; i++)
+		printf(" %p|%p: %s image (%zu/%zu bytes)\n", components[i].start,
+		    (void *) KSEG2PA(components[i].start), components[i].name,
+		    components[i].inflated, components[i].size);
+	
+	void *dest[COMPONENTS];
+	size_t top = 0;
+	size_t cnt = 0;
+	bootinfo->cnt = 0;
+	for (i = 0; i < min(COMPONENTS, TASKMAP_MAX_RECORDS); i++) {
+		top = ALIGN_UP(top, PAGE_SIZE);
+		
+		if (i > 0) {
+			bootinfo->tasks[bootinfo->cnt].addr = TOP2ADDR(top);
+			bootinfo->tasks[bootinfo->cnt].size = components[i].inflated;
+			
+			str_cpy(bootinfo->tasks[bootinfo->cnt].name,
+			    BOOTINFO_TASK_NAME_BUFLEN, components[i].name);
+			
+			bootinfo->cnt++;
+		}
+		
+		dest[i] = TOP2ADDR(top);
+		top += components[i].inflated;
+		cnt++;
+	}
+	
+	printf("\nInflating components ... ");
+	
+	for (i = cnt; i > 0; i--) {
+		void *tail = dest[i - 1] + components[i].inflated;
+		if (tail >= ((void *) PA2KA(LOADER_OFFSET))) {
+			printf("\n%s: Image too large to fit (%p >= %p), halting.\n",
+			    components[i].name, tail, (void *) PA2KA(LOADER_OFFSET));
+			halt();
+		}
+		
+		printf("%s ", components[i - 1].name);
+		
+		int err = inflate(components[i - 1].start, components[i - 1].size,
+		    dest[i - 1], components[i - 1].inflated);
+		
+		if (err != EOK) {
+			printf("\n%s: Inflating error %d, halting.\n",
+			    components[i - 1].name, err);
+			halt();
+		}
+	}
+	
+	printf(".\n");
+	
+	printf("Copying CPU map ... \n");
+	
+	bootinfo->cpumap = 0;
+	for (i = 0; i < CPUMAP_MAX_RECORDS; i++) {
+		if (cpumap[i] != 0)
+			bootinfo->cpumap |= (1 << i);
+	}
+	
+	printf("Booting the kernel ... \n");
+	jump_to_kernel((void *) PA2KA(BOOT_OFFSET), bootinfo);
+}
Index: boot/arch/mips64/src/putchar.c
===================================================================
--- boot/arch/mips64/src/putchar.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/arch/mips64/src/putchar.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+#include <typedefs.h>
+#include <arch/arch.h>
+#include <putchar.h>
+#include <str.h>
+
+void putchar(const wchar_t ch)
+{
+	if (ascii_check(ch))
+		*((char *) MSIM_VIDEORAM_ADDRESS) = ch;
+	else
+		*((char *) MSIM_VIDEORAM_ADDRESS) = U_SPECIAL;
+}
Index: boot/arch/ppc32/Makefile.inc
===================================================================
--- boot/arch/ppc32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/ppc32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,6 +43,6 @@
 	$(USPACE_PATH)/srv/hw/bus/cuda_adb/cuda_adb
 
-RD_SRVS_NON_ESSENTIAL += \
-	$(USPACE_PATH)/srv/hid/adb_mouse/adb_ms
+RD_DRVS += \
+	infrastructure/rootmac
 
 SOURCES = \
Index: boot/arch/ppc32/src/asm.S
===================================================================
--- boot/arch/ppc32/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/ppc32/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -58,4 +58,50 @@
 .endm
 
+.macro BAT_COMPUTE base size mask lower upper
+	# less than 128 KB -> no BAT
+	
+	lis \upper, 0x0002
+	cmpw \size, \upper
+	blt no_bat
+	
+	# mask = total >> 18
+	
+	li \upper, 18
+	srw \mask, \size, \upper
+	
+	# create Block Length mask by replicating
+	# the leading logical one 14 times
+	
+	li \upper, 14
+	mtctr \mask
+	li \upper, 1
+	
+	0:
+		# mask = (mask >> 1) | mask
+		
+		srw \lower, \mask, \upper
+		or \mask, \mask, \lower
+		
+		bdnz 0b
+	
+	# mask = mask & 0x07ff
+	# (BAT can map up to 256 MB)
+	
+	andi. \mask, \mask, 0x07ff
+	
+	# mask = (mask << 2) | 0x0002
+	# (priviledged access only)
+	
+	li \upper, 2
+	slw \mask, \mask, \upper
+	ori \mask, \mask, 0x0002
+	
+	lis \upper, (0x8000 + \base)
+	or \upper, \upper, \mask
+	
+	lis \lower, \base
+	ori \lower, \lower, 0x0002
+.endm
+
 .global start
 .global halt
@@ -243,51 +289,110 @@
 	clear_end:
 	
-#ifdef CONFIG_BAT
-	
 	# create BAT identity mapping
 	
 	lwz r31, 4(r3)                # r31 = memory size
 	
-	lis r29, 0x0002
-	cmpw r31, r29
-	blt no_bat                    # less than 128 KB -> no BAT
-	
-	li r29, 18
-	srw r31, r31, r29             # r31 = total >> 18
-	
-	# create Block Length mask by replicating
-	# the leading logical one 14 times
-	
-	li r29, 14
-	mtctr r31
-	li r29, 1
-	
-	bat_mask:
-		srw r30, r31, r29         # r30 = mask >> 1
-		or r31, r31, r30          # mask = mask | r30
-		
-		bdnz bat_mask
-	
-	andi. r31, r31, 0x07ff        # mask = mask & 0x07ff (BAT can map up to 256 MB)
-	
-	li r29, 2
-	slw r31, r31, r29             # mask = mask << 2
-	ori r31, r31, 0x0002          # mask = mask | 0x0002 (priviledged access only)
-	
-	lis r29, 0x8000
-	or r29, r29, r31
-	
-	lis r30, 0x0000
-	ori r30, r30, 0x0002
-	
-	mtspr ibat0u, r29
-	mtspr ibat0l, r30
-	
-	mtspr dbat0u, r29
-	mtspr dbat0l, r30
+	lis r30, 268435456@h
+	ori r30, r30, 268435456@l     # r30 = 256 MB
+	
+	# BAT0
+	
+	# r29 = min(r31, r30)
+	
+	cmpw r31, r30
+	blt bat0_r31
+	
+		mr r29, r30
+		b bat0_r30
+	
+	bat0_r31:
+	
+		mr r29, r31
+	
+	bat0_r30:
+	
+	BAT_COMPUTE 0x0000 r29 r28 r27 r26
+	mtspr ibat0u, r26
+	mtspr ibat0l, r27
+	
+	mtspr dbat0u, r26
+	mtspr dbat0l, r27
+	
+	# BAT1
+	
+	sub r31, r31, r29             # r31 = r31 - r29
+	
+	# r29 = min(r31, r30)
+	
+	cmpw r31, r30
+	blt bat1_r31
+	
+		mr r29, r30
+		b bat1_r30
+	
+	bat1_r31:
+	
+		mr r29, r31
+	
+	bat1_r30:
+	
+	BAT_COMPUTE 0x1000 r29 r28 r27 r26
+	mtspr ibat1u, r26
+	mtspr ibat1l, r27
+	
+	mtspr dbat1u, r26
+	mtspr dbat1l, r27
+	
+	# BAT2
+	
+	sub r31, r31, r29             # r31 = r31 - r29
+	
+	# r29 = min(r31, r30)
+	
+	cmpw r31, r30
+	blt bat2_r31
+	
+		mr r29, r30
+		b bat2_r30
+	
+	bat2_r31:
+	
+		mr r29, r31
+	
+	bat2_r30:
+	
+	BAT_COMPUTE 0x2000 r29 r28 r27 r26
+	mtspr ibat2u, r26
+	mtspr ibat2l, r27
+	
+	mtspr dbat2u, r26
+	mtspr dbat2l, r27
+	
+	# BAT3
+	
+	sub r31, r31, r29             # r31 = r31 - r29
+	
+	# r29 = min(r31, r30)
+	
+	cmpw r31, r30
+	blt bat3_r31
+	
+		mr r29, r30
+		b bat3_r30
+	
+	bat3_r31:
+	
+		mr r29, r31
+	
+	bat3_r30:
+	
+	BAT_COMPUTE 0x3000 r29 r28 r27 r26
+	mtspr ibat3u, r26
+	mtspr ibat3l, r27
+	
+	mtspr dbat3u, r26
+	mtspr dbat3l, r27
 	
 	no_bat:
-	
-#endif
 	
 	# flush TLB
Index: boot/arch/sparc64/Makefile.inc
===================================================================
--- boot/arch/sparc64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/sparc64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,5 +43,4 @@
 
 RD_SRVS_ESSENTIAL += \
-	$(USPACE_PATH)/srv/hw/irc/fhc/fhc \
 	$(USPACE_PATH)/srv/hw/irc/obio/obio
 
Index: boot/arch/sparc64/src/main.c
===================================================================
--- boot/arch/sparc64/src/main.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/arch/sparc64/src/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -182,8 +182,5 @@
 	 * of the "/memory" node to find out which parts of memory
 	 * are used by OBP and redesign the algorithm of copying
-	 * kernel/init tasks/ramdisk from the bootable image to memory
-	 * (which we must do anyway because of issues with claiming the memory
-	 * on Serengeti).
-	 *
+	 * kernel/init tasks/ramdisk from the bootable image to memory.
 	 */
 	bootinfo.physmem_start += OBP_BIAS;
Index: boot/genarch/include/efi.h
===================================================================
--- boot/genarch/include/efi.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/genarch/include/efi.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#ifndef BOOT_EFI_H_
+#define BOOT_EFI_H_
+
+#include <arch/types.h>
+
+typedef struct {
+	uint64_t signature;
+	uint32_t revision;
+	uint32_t header_size;
+	uint32_t crc32;
+	uint32_t reserved;
+} efi_table_header_t;
+
+#define SAL_SYSTEM_TABLE_GUID \
+	{ \
+		{ \
+			0x32, 0x2d, 0x9d, 0xeb, 0x88, 0x2d, 0xd3, 0x11, \
+			0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d \
+		} \
+	}
+
+typedef union {
+	uint8_t bytes[16];
+	struct {
+		uint64_t low;
+		uint64_t high;
+	};
+} efi_guid_t;
+
+typedef struct {
+	efi_guid_t guid;
+	void *table;
+} efi_configuration_table_t;
+
+typedef struct {
+	efi_table_header_t hdr;
+	char *fw_vendor;
+	uint32_t fw_revision;
+	void *cons_in_handle;
+	void *cons_in;
+	void *cons_out_handle;
+	void *cons_out;
+	void *cons_err_handle;
+	void *cons_err;
+	void *runtime_services;
+	void *boot_services;
+	sysarg_t conf_table_entries;
+	efi_configuration_table_t *conf_table;
+} efi_system_table_t;
+
+typedef enum {
+	EFI_RESERVED,
+	EFI_LOADER_CODE,
+	EFI_LOADER_DATA,
+	EFI_BOOT_SERVICES_CODE,
+	EFI_BOOT_SERVICES_DATA,
+	EFI_RUNTIME_SERVICES_CODE,
+	EFI_RUNTIME_SERVICES_DATA,
+	EFI_CONVENTIONAL_MEMORY,
+	EFI_UNUSABLE_MEMORY,
+	EFI_ACPI_RECLAIM_MEMORY,
+	EFI_ACPI_MEMORY_NVS,
+	EFI_MEMORY_MAPPED_IO,
+	EFI_MEMORY_MAPPED_IO_PORT_SPACE,
+	EFI_PAL_CODE
+} efi_memory_type_t;
+
+typedef struct {
+	uint32_t type;
+	uint64_t phys_start;
+	uint64_t virt_start;
+	uint64_t pages;
+	uint64_t attribute;
+} efi_v1_memdesc_t;
+
+#define EFI_PAGE_SIZE	4096
+
+extern void *efi_vendor_table_find(efi_system_table_t *, efi_guid_t);
+
+#endif
Index: boot/genarch/src/efi.c
===================================================================
--- boot/genarch/src/efi.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ boot/genarch/src/efi.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <genarch/efi.h>
+#include <arch/types.h>
+#include <typedefs.h>
+
+void *efi_vendor_table_find(efi_system_table_t *st, efi_guid_t guid)
+{
+	sysarg_t i;
+
+	for (i = 0; i < st->conf_table_entries; i++)
+		if ((st->conf_table[i].guid.low == guid.low) &&
+		    (st->conf_table[i].guid.high == guid.high))
+			return st->conf_table[i].table;
+
+	return NULL;
+}
+
Index: boot/generic/src/version.c
===================================================================
--- boot/generic/src/version.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ boot/generic/src/version.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,5 +32,5 @@
 
 static const char *project = "HelenOS bootloader";
-static const char *copyright = "Copyright (c) 2001-2010 HelenOS project";
+static const char *copyright = "Copyright (c) 2001-2011 HelenOS project";
 static const char *release = STRING(RELEASE);
 static const char *name = STRING(NAME);
Index: contrib/bazaar/bzreml/__init__.py
===================================================================
--- contrib/bazaar/bzreml/__init__.py	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ contrib/bazaar/bzreml/__init__.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -134,42 +134,10 @@
 				body.write("New Revision: %s%s\n" % (revision_ac_no, merge_marker(revision_ac)))
 				body.write("New Id: %s\n" % revision_ac_id)
-				
-				body.write("\n")
-				
 				for parent_id in revision_ac.parent_ids:
 					body.write("Parent: %s\n" % parent_id)
-					
-					tree_old = branch.repository.revision_tree(parent_id)
-					tree_ac = branch.repository.revision_tree(revision_ac_id)
-					
-					delta = tree_ac.changes_from(tree_old)
-					
-					if (len(delta.added) > 0):
-						body.write("Added:\n")
-						for item in delta.added:
-							body.write("    %s\n" % item[0])
-					
-					if (len(delta.removed) > 0):
-						body.write("Removed:\n")
-						for item in delta.removed:
-							body.write("    %s\n" % item[0])
-					
-					if (len(delta.renamed) > 0):
-						body.write("Renamed:\n")
-						for item in delta.renamed:
-							body.write("    %s -> %s\n" % (item[0], item[1]))
-					
-					if (len(delta.kind_changed) > 0):
-						body.write("Changed:\n")
-						for item in delta.kind_changed:
-							body.write("    %s\n" % item[0])
-						
-					if (len(delta.modified) > 0):
-						body.write("Modified:\n")
-						for item in delta.modified:
-							body.write("    %s\n" % item[0])
-					
-					body.write("\n")
-				
+				
+				body.write("\n")
+				
+				commit_message = ""
 				body.write("Log:\n")
 				if (not revision_ac.message):
@@ -179,4 +147,9 @@
 					for line in log.split("\n"):
 						body.write("%s\n" % line)
+						if (commit_message == ""):
+							commit_message = line
+				
+				if (commit_message == ""):
+					commit_message = "(empty)"
 				
 				body.write("\n")
@@ -184,4 +157,34 @@
 			tree_old = branch.repository.revision_tree(revision_old_id)
 			tree_new = branch.repository.revision_tree(revision_new_id)
+			
+			revision_new_no = branch.revision_id_to_revno(revision_new_id)
+			delta = tree_new.changes_from(tree_old)
+			
+			if (len(delta.added) > 0):
+				body.write("Added:\n")
+				for item in delta.added:
+					body.write("    %s\n" % item[0])
+			
+			if (len(delta.removed) > 0):
+				body.write("Removed:\n")
+				for item in delta.removed:
+					body.write("    %s\n" % item[0])
+			
+			if (len(delta.renamed) > 0):
+				body.write("Renamed:\n")
+				for item in delta.renamed:
+					body.write("    %s -> %s\n" % (item[0], item[1]))
+			
+			if (len(delta.kind_changed) > 0):
+				body.write("Changed:\n")
+				for item in delta.kind_changed:
+					body.write("    %s\n" % item[0])
+			
+			if (len(delta.modified) > 0):
+				body.write("Modified:\n")
+				for item in delta.modified:
+					body.write("    %s\n" % item[0])
+			
+			body.write("\n")
 			
 			tree_old.lock_read()
@@ -196,25 +199,5 @@
 				tree_old.unlock()
 			
-			revision_new_no = branch.revision_id_to_revno(revision_new_id)
-			
-			delta = tree_new.changes_from(tree_old)
-			files = []
-			
-			for item in delta.added:
-				files.append(item[0])
-			
-			for item in delta.removed:
-				files.append(item[0])
-			
-			for item in delta.renamed:
-				files.append(item[0])
-			
-			for item in delta.kind_changed:
-				files.append(item[0])
-			
-			for item in delta.modified:
-				files.append(item[0])
-			
-			subject = "r%d - %s" % (revision_new_no, " ".join(files))
+			subject = "r%d - %s" % (revision_new_no, commit_message)
 			
 			send_smtp("localhost", config_sender(config), config_to(config), subject, body.getvalue())
Index: contrib/bazaar/bzreml/setup.py
===================================================================
--- contrib/bazaar/bzreml/setup.py	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ contrib/bazaar/bzreml/setup.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -7,5 +7,5 @@
 	description = 'Commit email plugin for Bazaar',
 	keywords = 'plugin bzr email',
-	version = '1.0',
+	version = '1.2',
 	url = 'http://www.decky.cz/',
 	license = 'BSD',
Index: contrib/conf/arm32-qe.sh
===================================================================
--- contrib/conf/arm32-qe.sh	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ contrib/conf/arm32-qe.sh	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,3 +1,3 @@
 #!/bin/sh
 
-qemu-system-arm -M integratorcp --kernel image.boot
+qemu-system-arm $@ -M integratorcp --kernel image.boot
Index: contrib/conf/ia32-qe.sh
===================================================================
--- contrib/conf/ia32-qe.sh	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ contrib/conf/ia32-qe.sh	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -8,3 +8,3 @@
 fi
 
-qemu -m 32 -hda "$DISK_IMG" -cdrom image.iso -boot d
+qemu $@ -m 32 -hda "$DISK_IMG" -cdrom image.iso -boot d
Index: ntrib/conf/net-qe.bat
===================================================================
--- contrib/conf/net-qe.bat	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,26 +1,0 @@
-REM Start qemu on windows.
-REM tested with qemu-0.10.6-windows
-
-@ECHO OFF
-
-REM SDL_VIDEODRIVER=directx is faster than windib. But keyboard cannot work well.
-SET SDL_VIDEODRIVER=windib
-
-REM SDL_AUDIODRIVER=waveout or dsound can be used. Only if QEMU_AUDIO_DRV=sdl.
-SET SDL_AUDIODRIVER=dsound
-
-REM QEMU_AUDIO_DRV=dsound or fmod or sdl or none can be used. See qemu -audio-help.
-SET QEMU_AUDIO_DRV=dsound
-
-REM QEMU_AUDIO_LOG_TO_MONITOR=1 displays log messages in QEMU monitor.
-SET QEMU_AUDIO_LOG_TO_MONITOR=0
-
-REM PCI-based PC(default): -M pc 
-REM ISA-based PC         : -M isapc
-REM -M isapc is added for NE2000 ISA card.
-
-REM the -L argument should point to the qemu libraries
-
-set arguments=-L . -vga std -no-kqemu -M isapc -net nic,model=ne2k_isa -net user -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -boot d -cdrom image.iso
-
-qemu.exe %* %arguments%
Index: contrib/conf/ppc32-qe.sh
===================================================================
--- contrib/conf/ppc32-qe.sh	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ contrib/conf/ppc32-qe.sh	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,3 +1,3 @@
 #!/bin/sh
 
-qemu-system-ppc -M mac99 -boot d -cdrom image.iso
+qemu-system-ppc $@ -M g3beige -boot d -cdrom image.iso
Index: ntrib/font/bdf2c.pl
===================================================================
--- contrib/font/bdf2c.pl	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,164 +1,0 @@
-#!/usr/bin/perl -w
-
-#
-# Copyright (c) 2000 Dmitry Bolkhovityanov
-# Copyright (c) 2009 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.
-#
-
-use strict;
-
-my $skip;
-
-my $width;
-my $height;
-my $offset_x;
-my $offset_y;
-
-my $gwidth;
-my $gheight;
-my $goffset_x;
-my $goffset_y;
-
-my $index;
-my @glyphs;
-my @chars;
-
-open(BDF, "u_vga16.bdf") or die("Unable to open source font\n");
-
-READHEADER: while (<BDF>) {
-	/^FONTBOUNDINGBOX\s/ and do {
-		($skip, $width, $height, $offset_x, $offset_y) = (split);
-		
-		die("Font width is not 8px\n") if ($width != 8);
-		die("Font height is not 16px\n") if ($height != 16);
-	};
-	/^CHARS\s/ && last READHEADER;
-}
-
-READCHARS: while (<BDF>) {
-	/^ENCODING\s+([0-9]+)\s*$/ && do {
-		$index = $1;
-	};
-	/^BBX\s/ && do {
-		($skip, $gwidth, $gheight, $goffset_x, $goffset_y) = (split);
-	};
-	/^BITMAP/ && do {
-		my @glyph = ();
-		my $y;
-		
-		# Add empty lines at top
-		my $empties = $height + $offset_y - $goffset_y - $gheight;
-		
-		for ($y = 0; $y < $empties; $y++) {
-			$glyph[$y] = 0;
-		}
-		
-		# Scan the hex bitmap
-		for ($y = $empties; $y < $empties + $gheight; $y++) {
-			$_ = <BDF>;
-			$glyph[$y] = hex(substr($_, 0, 2)) >> $goffset_x;
-		}
-		
-		# Add empty lines at bottom
-		my $fill = $height - $gheight - $empties;
-		for ($y = $empties + $gheight; $y < $empties + $gheight + $fill; $y++) {
-			$glyph[$y] = 0;
-		}
-		
-		if ($index != 0) {
-			$glyphs[$index] = (\@glyph);
-			push(@chars, $index);
-		}
-	};
-	/^ENDFONT/ && last READCHARS;
-}
-
-close(BDF);
-
-@chars = sort { $a <=> $b } (@chars);
-
-print "#define FONT_GLYPHS     " . (@chars + 1). "\n";
-print "#define FONT_SCANLINES  " . $height . "\n";
-
-print "\n";
-print "uint16_t fb_font_glyph(const wchar_t ch)\n";
-print "{\n";
-print "\tif (ch == 0x0000)\n";
-print "\t\treturn 0;\n\n";
-
-my $pos = 0;
-my $start = -1;
-my $start_pos = 0;
-my $prev = 0;
-for $index (@chars) {
-	if ($prev + 1 < $index) {
-		if ($start != -1) {
-			if ($start == $prev) {
-				printf "\tif (ch == 0x%.4x)\n", $start;
-				print "\t\treturn " . $start_pos . ";\n";
-			} else {
-				printf "\tif ((ch >= 0x%.4x) && (ch <= 0x%.4x))\n", $start, $prev;
-				print "\t\treturn (ch - " . ($start - $start_pos) . ");\n";
-			}
-			
-			print "\t\n";
-		}
-		
-		$start = $index;
-		$start_pos = $pos;
-	}
-	
-	$pos++;
-	$prev = $index;
-}
-
-print "\treturn " . @chars . ";\n";
-print "}\n";
-
-print "\n";
-print "uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES] = {";
-
-for $index (@chars) {
-	print "\n\t{";
-	
-	my $y;
-	for ($y = 0; $y < $height; $y++) {
-		print ", " if ($y > 0);
-		printf "0x%.2x", $glyphs[$index]->[$y];
-	}
-	
-	print "},";
-}
-
-print "\n\t\n\t/* Special glyph for unknown character */\n\t{";
-my $y;
-for ($y = 0; $y < $height; $y++) {
-	print ", " if ($y > 0);
-	printf "0x%.2x", $glyphs[63]->[$y];
-}
-
-print "}\n};\n";
Index: ntrib/font/u_vga16.bdf
===================================================================
--- contrib/font/u_vga16.bdf	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,66709 +1,0 @@
-STARTFONT 2.1
-FONT -Bolkhov-VGA-Medium-R-Normal--16-160-75-75-C-80-iso10646-1
-SIZE 16 75 75
-FONTBOUNDINGBOX 8 16 0 -4
-STARTPROPERTIES 24
-FOUNDRY "Bolkhov"
-FAMILY_NAME "VGA"
-WEIGHT_NAME "Medium"
-SLANT "R"
-SETWIDTH_NAME "Normal"
-ADD_STYLE_NAME ""
-PIXEL_SIZE 16
-POINT_SIZE 160
-RESOLUTION_X 75
-RESOLUTION_Y 75
-SPACING "C"
-AVERAGE_WIDTH 80
-CHARSET_REGISTRY "iso10646"
-CHARSET_ENCODING "1"
-CAP_HEIGHT 10
-X_HEIGHT 7
-FONT_ASCENT 12
-FONT_DESCENT 4
-FACE_NAME "VGA Unicode"
-COPYRIGHT "Copyright (c) 2000 Dmitry Bolkhovityanov, bolkhov@inp.nsk.su"
-HOMEPAGE "http://www.inp.nsk.su/~bolkhov/files/fonts/univga/"
-NOTICE "VGA is a trademark of IBM Corporation."
-DEFAULT_CHAR 0
-_XMBDFED_INFO "Edited with xmbdfed 4.4."
-ENDPROPERTIES
-CHARS 2899
-STARTCHAR char0
-ENCODING 0
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DA
-02
-80
-82
-02
-80
-82
-02
-80
-B6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR space
-ENCODING 32
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR exclam
-ENCODING 33
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-3C
-3C
-18
-18
-18
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR quotedbl
-ENCODING 34
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-66
-66
-66
-24
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR numbersign
-ENCODING 35
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-6C
-6C
-FE
-6C
-6C
-6C
-FE
-6C
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dollar
-ENCODING 36
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-7C
-C6
-C2
-C0
-7C
-06
-06
-86
-C6
-7C
-18
-18
-00
-00
-ENDCHAR
-STARTCHAR percent
-ENCODING 37
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C2
-C6
-0C
-18
-30
-60
-C6
-86
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ampersand
-ENCODING 38
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-6C
-38
-76
-DC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR quotesingle
-ENCODING 39
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-30
-30
-20
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR parenleft
-ENCODING 40
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-30
-30
-30
-30
-30
-30
-18
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR parenright
-ENCODING 41
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-18
-0C
-0C
-0C
-0C
-0C
-0C
-18
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR asterisk
-ENCODING 42
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-3C
-FF
-3C
-66
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR plus
-ENCODING 43
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-18
-7E
-18
-18
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR comma
-ENCODING 44
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-18
-18
-30
-00
-00
-00
-ENDCHAR
-STARTCHAR hyphen
-ENCODING 45
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR period
-ENCODING 46
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR slash
-ENCODING 47
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-02
-06
-0C
-18
-30
-60
-C0
-80
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR zero
-ENCODING 48
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-C6
-C6
-D6
-D6
-C6
-C6
-6C
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR one
-ENCODING 49
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-38
-78
-18
-18
-18
-18
-18
-18
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR two
-ENCODING 50
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-06
-0C
-18
-30
-60
-C0
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR three
-ENCODING 51
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-06
-06
-3C
-06
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR four
-ENCODING 52
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-1C
-3C
-6C
-CC
-FE
-0C
-0C
-0C
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR five
-ENCODING 53
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C0
-C0
-C0
-FC
-06
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR six
-ENCODING 54
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-60
-C0
-C0
-FC
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR seven
-ENCODING 55
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-06
-06
-0C
-18
-30
-30
-30
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR eight
-ENCODING 56
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-7C
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR nine
-ENCODING 57
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-7E
-06
-06
-06
-0C
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR colon
-ENCODING 58
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-18
-00
-00
-00
-18
-18
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR semicolon
-ENCODING 59
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-18
-00
-00
-00
-18
-18
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR less
-ENCODING 60
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-06
-0C
-18
-30
-60
-30
-18
-0C
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR equal
-ENCODING 61
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-00
-00
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR greater
-ENCODING 62
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-60
-30
-18
-0C
-06
-0C
-18
-30
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR question
-ENCODING 63
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-0C
-18
-18
-18
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR at
-ENCODING 64
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-C6
-C6
-DE
-DE
-DE
-DC
-C0
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR A
-ENCODING 65
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR B
-ENCODING 66
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-66
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR C
-ENCODING 67
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR D
-ENCODING 68
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-66
-66
-66
-66
-6C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR E
-ENCODING 69
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR F
-ENCODING 70
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR G
-ENCODING 71
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-DE
-C6
-C6
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR H
-ENCODING 72
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR I
-ENCODING 73
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR J
-ENCODING 74
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-0C
-0C
-0C
-0C
-0C
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR K
-ENCODING 75
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR L
-ENCODING 76
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-60
-60
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR M
-ENCODING 77
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR N
-ENCODING 78
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR O
-ENCODING 79
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR P
-ENCODING 80
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Q
-ENCODING 81
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-D6
-DE
-7C
-0C
-0E
-00
-00
-ENDCHAR
-STARTCHAR R
-ENCODING 82
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR S
-ENCODING 83
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-60
-38
-0C
-06
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR T
-ENCODING 84
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR U
-ENCODING 85
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR V
-ENCODING 86
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-6C
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR W
-ENCODING 87
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-D6
-D6
-D6
-FE
-EE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR X
-ENCODING 88
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-6C
-7C
-38
-38
-7C
-6C
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Y
-ENCODING 89
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Z
-ENCODING 90
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-86
-0C
-18
-30
-60
-C2
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR bracketleft
-ENCODING 91
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-30
-30
-30
-30
-30
-30
-30
-30
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR backslash
-ENCODING 92
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-80
-C0
-E0
-70
-38
-1C
-0E
-06
-02
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR bracketright
-ENCODING 93
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR asciicircum
-ENCODING 94
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-6C
-C6
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR underscore
-ENCODING 95
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-ENDCHAR
-STARTCHAR grave
-ENCODING 96
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR a
-ENCODING 97
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR b
-ENCODING 98
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-78
-6C
-66
-66
-66
-66
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR c
-ENCODING 99
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR d
-ENCODING 100
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR e
-ENCODING 101
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR f
-ENCODING 102
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-64
-60
-F0
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR g
-ENCODING 103
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR h
-ENCODING 104
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR i
-ENCODING 105
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR j
-ENCODING 106
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-06
-00
-0E
-06
-06
-06
-06
-06
-06
-66
-66
-3C
-00
-ENDCHAR
-STARTCHAR k
-ENCODING 107
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-66
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR l
-ENCODING 108
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR m
-ENCODING 109
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-EC
-FE
-D6
-D6
-D6
-D6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR n
-ENCODING 110
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR o
-ENCODING 111
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR p
-ENCODING 112
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-7C
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR q
-ENCODING 113
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-0C
-1E
-00
-ENDCHAR
-STARTCHAR r
-ENCODING 114
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR s
-ENCODING 115
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR t
-ENCODING 116
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-30
-30
-36
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR u
-ENCODING 117
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR v
-ENCODING 118
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-66
-66
-66
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR w
-ENCODING 119
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR x
-ENCODING 120
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-6C
-38
-38
-38
-6C
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR y
-ENCODING 121
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR z
-ENCODING 122
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-CC
-18
-30
-60
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR braceleft
-ENCODING 123
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0E
-18
-18
-18
-70
-18
-18
-18
-18
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR bar
-ENCODING 124
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-00
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR braceright
-ENCODING 125
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-18
-18
-18
-0E
-18
-18
-18
-18
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR asciitilde
-ENCODING 126
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR char127
-ENCODING 127
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-38
-6C
-C6
-C6
-C6
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR space
-ENCODING 160
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR exclamdown
-ENCODING 161
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-18
-18
-18
-3C
-3C
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR cent
-ENCODING 162
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-18
-3C
-66
-60
-60
-60
-66
-3C
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR sterling
-ENCODING 163
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-6C
-64
-60
-F0
-60
-60
-60
-60
-E6
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR currency
-ENCODING 164
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-66
-3C
-66
-66
-66
-3C
-66
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR yen
-ENCODING 165
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-3C
-18
-7E
-18
-7E
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR brokenbar
-ENCODING 166
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-00
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR section
-ENCODING 167
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-C6
-60
-38
-6C
-C6
-C6
-6C
-38
-0C
-C6
-7C
-00
-00
-00
-ENDCHAR
-STARTCHAR dieresis
-ENCODING 168
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR copyright
-ENCODING 169
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-99
-A5
-A1
-A1
-A5
-99
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ordfeminine
-ENCODING 170
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-3C
-6C
-6C
-3E
-00
-7E
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR guillemotleft
-ENCODING 171
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-36
-6C
-D8
-6C
-36
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR logicalnot
-ENCODING 172
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-FE
-06
-06
-06
-06
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR hyphen
-ENCODING 173
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-3C
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR registered
-ENCODING 174
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-44
-BA
-B2
-AA
-44
-38
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR macron
-ENCODING 175
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR degree
-ENCODING 176
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-6C
-6C
-38
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR plusminus
-ENCODING 177
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-18
-7E
-18
-18
-00
-7E
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR twosuperior
-ENCODING 178
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-D8
-30
-60
-C8
-F8
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR threesuperior
-ENCODING 179
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-D8
-30
-18
-D8
-70
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR acute
-ENCODING 180
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR mu
-ENCODING 181
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-F6
-C0
-C0
-C0
-00
-ENDCHAR
-STARTCHAR paragraph
-ENCODING 182
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7F
-DB
-DB
-DB
-7B
-1B
-1B
-1B
-1B
-1B
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR periodcentered
-ENCODING 183
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-18
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR cedilla
-ENCODING 184
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR onesuperior
-ENCODING 185
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-70
-30
-30
-30
-78
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ordmasculine
-ENCODING 186
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-6C
-6C
-38
-00
-7C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR guillemotright
-ENCODING 187
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-D8
-6C
-36
-6C
-D8
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR onequarter
-ENCODING 188
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-C2
-C6
-CC
-18
-30
-66
-CE
-9E
-3E
-06
-06
-00
-00
-ENDCHAR
-STARTCHAR onehalf
-ENCODING 189
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-C2
-C6
-CC
-18
-30
-60
-DC
-86
-0C
-18
-3E
-00
-00
-ENDCHAR
-STARTCHAR threequarters
-ENCODING 190
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-E0
-30
-62
-36
-EC
-18
-30
-66
-CE
-9E
-3E
-06
-06
-00
-00
-ENDCHAR
-STARTCHAR questiondown
-ENCODING 191
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-30
-30
-60
-C0
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Agrave
-ENCODING 192
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Aacute
-ENCODING 193
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Acircumflex
-ENCODING 194
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-6C
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Atilde
-ENCODING 195
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Adieresis
-ENCODING 196
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Aring
-ENCODING 197
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-38
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR AE
-ENCODING 198
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3E
-6C
-CC
-CC
-FE
-CC
-CC
-CC
-CC
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ccedilla
-ENCODING 199
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-C0
-C0
-C2
-66
-3C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR Egrave
-ENCODING 200
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-18
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Eacute
-ENCODING 201
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ecircumflex
-ENCODING 202
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Edieresis
-ENCODING 203
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Igrave
-ENCODING 204
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-18
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Iacute
-ENCODING 205
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Icircumflex
-ENCODING 206
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-3C
-42
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Idieresis
-ENCODING 207
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-66
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Eth
-ENCODING 208
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-F6
-66
-66
-66
-6C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ntilde
-ENCODING 209
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ograve
-ENCODING 210
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Oacute
-ENCODING 211
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ocircumflex
-ENCODING 212
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Otilde
-ENCODING 213
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Odieresis
-ENCODING 214
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR multiply
-ENCODING 215
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-3C
-18
-3C
-66
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Oslash
-ENCODING 216
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7A
-C4
-CE
-CE
-D6
-D6
-E6
-E6
-46
-BC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ugrave
-ENCODING 217
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Uacute
-ENCODING 218
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ucircumflex
-ENCODING 219
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Udieresis
-ENCODING 220
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Yacute
-ENCODING 221
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Thorn
-ENCODING 222
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-7C
-66
-66
-66
-66
-7C
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR germandbls
-ENCODING 223
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-6C
-66
-66
-66
-66
-EC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR agrave
-ENCODING 224
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR aacute
-ENCODING 225
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-30
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR acircumflex
-ENCODING 226
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR atilde
-ENCODING 227
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR adieresis
-ENCODING 228
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR aring
-ENCODING 229
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-6C
-38
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ae
-ENCODING 230
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-76
-36
-7E
-D8
-D8
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ccedilla
-ENCODING 231
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR egrave
-ENCODING 232
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR eacute
-ENCODING 233
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ecircumflex
-ENCODING 234
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR edieresis
-ENCODING 235
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR igrave
-ENCODING 236
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-18
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR iacute
-ENCODING 237
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR icircumflex
-ENCODING 238
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR idieresis
-ENCODING 239
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR eth
-ENCODING 240
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-1C
-3C
-06
-7E
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ntilde
-ENCODING 241
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ograve
-ENCODING 242
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR oacute
-ENCODING 243
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ocircumflex
-ENCODING 244
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR otilde
-ENCODING 245
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR odieresis
-ENCODING 246
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR divide
-ENCODING 247
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-18
-00
-7E
-00
-18
-18
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR oslash
-ENCODING 248
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7A
-C4
-CE
-D6
-E6
-46
-BC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ugrave
-ENCODING 249
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uacute
-ENCODING 250
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-30
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ucircumflex
-ENCODING 251
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR udieresis
-ENCODING 252
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-CC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR yacute
-ENCODING 253
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR thorn
-ENCODING 254
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-7C
-66
-66
-66
-66
-66
-7C
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR ydieresis
-ENCODING 255
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR Amacron
-ENCODING 256
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR amacron
-ENCODING 257
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Abreve
-ENCODING 258
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR abreve
-ENCODING 259
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Aogonek
-ENCODING 260
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-0C
-18
-0E
-00
-ENDCHAR
-STARTCHAR aogonek
-ENCODING 261
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-0C
-18
-0E
-00
-ENDCHAR
-STARTCHAR Cacute
-ENCODING 262
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-3C
-66
-C2
-C0
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR cacute
-ENCODING 263
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ccircumflex
-ENCODING 264
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-3C
-66
-C2
-C0
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ccircumflex
-ENCODING 265
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Cdotaccent
-ENCODING 266
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-3C
-66
-C2
-C0
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR cdotaccent
-ENCODING 267
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ccaron
-ENCODING 268
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-3C
-66
-C2
-C0
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ccaron
-ENCODING 269
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Dcaron
-ENCODING 270
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-F8
-6C
-66
-66
-66
-66
-66
-6C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dcaron
-ENCODING 271
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Dcroat
-ENCODING 272
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-F6
-66
-66
-66
-6C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dcroat
-ENCODING 273
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-3E
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Emacron
-ENCODING 274
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR emacron
-ENCODING 275
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ebreve
-ENCODING 276
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ebreve
-ENCODING 277
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Edotaccent
-ENCODING 278
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR edotaccent
-ENCODING 279
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Eogonek
-ENCODING 280
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-18
-30
-1C
-00
-ENDCHAR
-STARTCHAR eogonek
-ENCODING 281
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR Ecaron
-ENCODING 282
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ecaron
-ENCODING 283
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Gcircumflex
-ENCODING 284
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-3C
-66
-C2
-C0
-DE
-C6
-C6
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR gcircumflex
-ENCODING 285
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR Gbreve
-ENCODING 286
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-3C
-66
-C2
-C0
-DE
-C6
-C6
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR gbreve
-ENCODING 287
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR Gdotaccent
-ENCODING 288
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-3C
-66
-C2
-C0
-DE
-C6
-C6
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR gdotaccent
-ENCODING 289
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR Gcommaaccent
-ENCODING 290
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-DE
-C6
-C6
-66
-3A
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR gcommaaccent
-ENCODING 291
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-30
-30
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR Hcircumflex
-ENCODING 292
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR hcircumflex
-ENCODING 293
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-E0
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Hbar
-ENCODING 294
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-FF
-66
-66
-7E
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR hbar
-ENCODING 295
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-F8
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Itilde
-ENCODING 296
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR itilde
-ENCODING 297
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Imacron
-ENCODING 298
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7E
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR imacron
-ENCODING 299
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7E
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ibreve
-ENCODING 300
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-3C
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ibreve
-ENCODING 301
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-3C
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Iogonek
-ENCODING 302
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-18
-30
-1C
-00
-ENDCHAR
-STARTCHAR iogonek
-ENCODING 303
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-38
-18
-18
-18
-18
-18
-3C
-18
-30
-1C
-00
-ENDCHAR
-STARTCHAR Idotaccent
-ENCODING 304
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dotlessi
-ENCODING 305
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR IJ
-ENCODING 306
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F7
-63
-63
-63
-63
-63
-63
-7B
-7B
-EE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ij
-ENCODING 307
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-00
-EE
-66
-66
-66
-66
-66
-F6
-06
-66
-3C
-00
-ENDCHAR
-STARTCHAR Jcircumflex
-ENCODING 308
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-1C
-22
-1E
-0C
-0C
-0C
-0C
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR jcircumflex
-ENCODING 309
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-04
-0E
-1B
-00
-0E
-06
-06
-06
-06
-06
-06
-66
-66
-3C
-00
-ENDCHAR
-STARTCHAR Kcommaaccent
-ENCODING 310
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E6
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR kcommaaccent
-ENCODING 311
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-66
-6C
-78
-78
-6C
-66
-E6
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR kgreenlandic
-ENCODING 312
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-E6
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Lacute
-ENCODING 313
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-30
-00
-F0
-60
-60
-60
-60
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR lacute
-ENCODING 314
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-38
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Lcommaaccent
-ENCODING 315
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-60
-60
-60
-62
-66
-FE
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR lcommaaccent
-ENCODING 316
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR Lcaron
-ENCODING 317
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-F0
-60
-60
-60
-60
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR lcaron
-ENCODING 318
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-38
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ldot
-ENCODING 319
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-66
-66
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ldot
-ENCODING 320
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-30
-30
-30
-36
-36
-30
-30
-30
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Lslash
-ENCODING 321
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-78
-E0
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR lslash
-ENCODING 322
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-1E
-78
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Nacute
-ENCODING 323
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR nacute
-ENCODING 324
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ncommaaccent
-ENCODING 325
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-C6
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR ncommaaccent
-ENCODING 326
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR Ncaron
-ENCODING 327
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ncaron
-ENCODING 328
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR napostrophe
-ENCODING 329
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-60
-60
-C0
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Eng
-ENCODING 330
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-C6
-06
-06
-1C
-00
-ENDCHAR
-STARTCHAR eng
-ENCODING 331
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-06
-06
-1C
-00
-ENDCHAR
-STARTCHAR Omacron
-ENCODING 332
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR omacron
-ENCODING 333
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Obreve
-ENCODING 334
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR obreve
-ENCODING 335
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ohungarumlaut
-ENCODING 336
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-CC
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ohungarumlaut
-ENCODING 337
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-CC
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR OE
-ENCODING 338
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6E
-D8
-D8
-D8
-DE
-D8
-D8
-D8
-D8
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR oe
-ENCODING 339
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-D6
-D6
-DE
-D8
-D8
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Racute
-ENCODING 340
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR racute
-ENCODING 341
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Rcommaaccent
-ENCODING 342
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-66
-E6
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR rcommaaccent
-ENCODING 343
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR Rcaron
-ENCODING 344
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-FC
-66
-66
-66
-7C
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR rcaron
-ENCODING 345
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Sacute
-ENCODING 346
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-7C
-C6
-C6
-60
-38
-0C
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR sacute
-ENCODING 347
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Scircumflex
-ENCODING 348
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-7C
-C6
-C6
-60
-38
-0C
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR scircumflex
-ENCODING 349
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Scedilla
-ENCODING 350
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-C6
-C6
-60
-38
-0C
-C6
-C6
-7C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR scedilla
-ENCODING 351
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR Scaron
-ENCODING 352
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-7C
-C6
-C6
-60
-38
-0C
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR scaron
-ENCODING 353
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Tcommaaccent
-ENCODING 354
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR tcommaaccent
-ENCODING 355
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-30
-30
-36
-1C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR Tcaron
-ENCODING 356
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-7E
-7E
-5A
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR tcaron
-ENCODING 357
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-10
-30
-FC
-30
-30
-30
-30
-36
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Tbar
-ENCODING 358
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-3C
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR tbar
-ENCODING 359
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-FC
-30
-30
-36
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Utilde
-ENCODING 360
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR utilde
-ENCODING 361
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Umacron
-ENCODING 362
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR umacron
-ENCODING 363
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-78
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ubreve
-ENCODING 364
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ubreve
-ENCODING 365
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-78
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Uring
-ENCODING 366
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-38
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uring
-ENCODING 367
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-6C
-38
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Uhungarumlaut
-ENCODING 368
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-CC
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uhungarumlaut
-ENCODING 369
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-CC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Uogonek
-ENCODING 370
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR uogonek
-ENCODING 371
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR Wcircumflex
-ENCODING 372
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-C6
-C6
-C6
-D6
-D6
-D6
-FE
-EE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR wcircumflex
-ENCODING 373
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-C6
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ycircumflex
-ENCODING 374
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ycircumflex
-ENCODING 375
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR Ydieresis
-ENCODING 376
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-66
-00
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Zacute
-ENCODING 377
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-FE
-C6
-8C
-18
-30
-60
-C2
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR zacute
-ENCODING 378
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-FE
-CC
-18
-30
-60
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Zdotaccent
-ENCODING 379
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-FE
-C6
-8C
-18
-30
-60
-C2
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR zdotaccent
-ENCODING 380
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-FE
-CC
-18
-30
-60
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Zcaron
-ENCODING 381
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-FE
-C6
-8C
-18
-30
-60
-C2
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR zcaron
-ENCODING 382
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-FE
-CC
-18
-30
-60
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR longs
-ENCODING 383
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-64
-60
-60
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0180
-ENCODING 384
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-F8
-60
-78
-6C
-66
-66
-66
-66
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0181
-ENCODING 385
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-B3
-B3
-33
-3E
-33
-33
-33
-33
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0182
-ENCODING 386
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-64
-60
-60
-7C
-66
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0183
-ENCODING 387
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-62
-60
-78
-6C
-66
-66
-66
-66
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0184
-ENCODING 388
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-E6
-E6
-66
-7C
-66
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0185
-ENCODING 389
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-E0
-E0
-78
-6C
-66
-66
-66
-66
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0186
-ENCODING 390
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-86
-06
-06
-06
-06
-86
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0187
-ENCODING 391
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-03
-3E
-66
-C2
-C0
-C0
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0188
-ENCODING 392
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-03
-7E
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0189
-ENCODING 393
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-F6
-66
-66
-66
-6C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni018A
-ENCODING 394
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-B6
-B3
-33
-33
-33
-33
-33
-36
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni018B
-ENCODING 395
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-4C
-0C
-0C
-7C
-CC
-CC
-CC
-CC
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni018C
-ENCODING 396
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-4C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni018D
-ENCODING 397
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-C6
-C6
-7C
-30
-18
-CC
-78
-00
-ENDCHAR
-STARTCHAR uni018E
-ENCODING 398
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-CC
-8C
-2C
-3C
-2C
-0C
-8C
-CC
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni018F
-ENCODING 399
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-06
-06
-06
-FE
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0190
-ENCODING 400
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C2
-C0
-78
-C0
-C0
-C2
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0191
-ENCODING 401
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-60
-60
-60
-60
-60
-C0
-00
-ENDCHAR
-STARTCHAR florin
-ENCODING 402
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-36
-32
-30
-78
-30
-30
-30
-30
-30
-30
-30
-E0
-00
-ENDCHAR
-STARTCHAR uni0193
-ENCODING 403
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-03
-3E
-66
-C2
-C0
-C0
-DE
-C6
-C6
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0194
-ENCODING 404
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-6C
-6C
-6C
-38
-38
-10
-38
-6C
-38
-00
-00
-ENDCHAR
-STARTCHAR uni0195
-ENCODING 405
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-C0
-F3
-DB
-DB
-DB
-DB
-DB
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0196
-ENCODING 406
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-30
-30
-30
-30
-30
-30
-30
-36
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0197
-ENCODING 407
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0198
-ENCODING 408
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-6D
-6C
-78
-70
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0199
-ENCODING 409
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-60
-66
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni019A
-ENCODING 410
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni019B
-ENCODING 411
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C8
-38
-70
-D0
-38
-38
-6C
-64
-C6
-C2
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni019C
-ENCODING 412
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D6
-D6
-D6
-D6
-D6
-D6
-D6
-D6
-FE
-EC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni019D
-ENCODING 413
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-76
-7E
-7E
-6E
-66
-66
-66
-66
-60
-60
-C0
-00
-ENDCHAR
-STARTCHAR uni019E
-ENCODING 414
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-06
-06
-06
-00
-ENDCHAR
-STARTCHAR uni019F
-ENCODING 415
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ohorn
-ENCODING 416
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-03
-7A
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ohorn
-ENCODING 417
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-06
-78
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01A2
-ENCODING 418
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-73
-DF
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-73
-03
-03
-03
-00
-ENDCHAR
-STARTCHAR uni01A3
-ENCODING 419
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-73
-DF
-DB
-DB
-DB
-DB
-73
-03
-03
-03
-00
-ENDCHAR
-STARTCHAR uni01A4
-ENCODING 420
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-B3
-B3
-33
-3E
-30
-30
-30
-30
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01A5
-ENCODING 421
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-60
-7C
-66
-66
-66
-66
-66
-7C
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR uni01A6
-ENCODING 422
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-7C
-66
-66
-7C
-78
-6C
-6C
-E6
-06
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01A7
-ENCODING 423
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-0C
-38
-60
-C0
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01A8
-ENCODING 424
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-0C
-38
-60
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01A9
-ENCODING 425
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-62
-30
-18
-18
-30
-62
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01AA
-ENCODING 426
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-D8
-78
-18
-18
-18
-18
-18
-18
-18
-18
-1B
-0E
-00
-ENDCHAR
-STARTCHAR uni01AB
-ENCODING 427
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-30
-30
-36
-1C
-0C
-6C
-38
-00
-ENDCHAR
-STARTCHAR uni01AC
-ENCODING 428
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-FE
-9A
-58
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01AD
-ENCODING 429
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-36
-30
-FC
-30
-30
-30
-30
-36
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01AE
-ENCODING 430
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-18
-18
-18
-0E
-00
-ENDCHAR
-STARTCHAR Uhorn
-ENCODING 431
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-03
-CE
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uhorn
-ENCODING 432
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-06
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01B1
-ENCODING 433
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-EE
-6C
-6C
-6C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01B2
-ENCODING 434
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01B3
-ENCODING 435
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-63
-B3
-B3
-33
-1E
-0C
-0C
-0C
-0C
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01B4
-ENCODING 436
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-06
-0D
-CC
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-18
-F0
-00
-ENDCHAR
-STARTCHAR uni01B5
-ENCODING 437
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-86
-0C
-7E
-30
-60
-C2
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01B6
-ENCODING 438
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-CC
-18
-FC
-60
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01B7
-ENCODING 439
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-06
-0C
-18
-30
-7C
-06
-06
-06
-06
-C6
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni01B8
-ENCODING 440
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C0
-60
-30
-18
-7C
-C0
-C0
-C0
-C0
-C6
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni01B9
-ENCODING 441
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-C0
-60
-30
-78
-C0
-C0
-C0
-C6
-7C
-00
-ENDCHAR
-STARTCHAR uni01BA
-ENCODING 442
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-06
-0C
-18
-3C
-06
-7C
-C0
-C6
-7C
-00
-ENDCHAR
-STARTCHAR uni01BB
-ENCODING 443
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-06
-0C
-7E
-30
-60
-C0
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01BC
-ENCODING 444
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-60
-60
-78
-0C
-06
-06
-06
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01BD
-ENCODING 445
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-60
-78
-0C
-06
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01BE
-ENCODING 446
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-18
-4C
-6C
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01BF
-ENCODING 447
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-6C
-78
-70
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR uni01C0
-ENCODING 448
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01C1
-ENCODING 449
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01C2
-ENCODING 450
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-7E
-18
-7E
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01C3
-ENCODING 451
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-3C
-3C
-18
-18
-18
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01C4
-ENCODING 452
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1B
-0E
-04
-F7
-D9
-D9
-DA
-DA
-DA
-DC
-DC
-F7
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01C5
-ENCODING 453
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F5
-DA
-D8
-DF
-D9
-DA
-DA
-DA
-DC
-F7
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01C6
-ENCODING 454
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3D
-1A
-18
-7F
-D9
-DA
-DA
-DA
-DC
-6F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01C7
-ENCODING 455
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C7
-C3
-C3
-C3
-C3
-C3
-C3
-C3
-CB
-F6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01C8
-ENCODING 456
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F3
-63
-60
-67
-63
-63
-63
-67
-6F
-FF
-03
-1B
-0E
-00
-ENDCHAR
-STARTCHAR uni01C9
-ENCODING 457
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E3
-63
-60
-67
-63
-63
-63
-63
-63
-F3
-03
-33
-1E
-00
-ENDCHAR
-STARTCHAR uni01CA
-ENCODING 458
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-FB
-FB
-FB
-DB
-DB
-DB
-DB
-DE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01CB
-ENCODING 459
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-F8
-FF
-FB
-FB
-DB
-DB
-DB
-DB
-03
-33
-1E
-00
-ENDCHAR
-STARTCHAR uni01CC
-ENCODING 460
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-00
-B7
-DB
-DB
-DB
-DB
-DB
-DB
-03
-33
-1E
-00
-ENDCHAR
-STARTCHAR uni01CD
-ENCODING 461
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01CE
-ENCODING 462
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01CF
-ENCODING 463
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D0
-ENCODING 464
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D1
-ENCODING 465
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D2
-ENCODING 466
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D3
-ENCODING 467
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D4
-ENCODING 468
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D5
-ENCODING 469
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-00
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D6
-ENCODING 470
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-78
-00
-CC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D7
-ENCODING 471
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-10
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D8
-ENCODING 472
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-30
-00
-CC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01D9
-ENCODING 473
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-28
-10
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01DA
-ENCODING 474
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-78
-30
-00
-CC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01DB
-ENCODING 475
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-20
-10
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01DC
-ENCODING 476
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-CC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01DD
-ENCODING 477
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-06
-FE
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01DE
-ENCODING 478
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-00
-6C
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01DF
-ENCODING 479
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-6C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01E0
-ENCODING 480
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-30
-30
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01E1
-ENCODING 481
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-30
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01E2
-ENCODING 482
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-3E
-6C
-CC
-CC
-FE
-CC
-CC
-CC
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01E3
-ENCODING 483
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-CC
-76
-36
-7E
-D8
-D8
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01E4
-ENCODING 484
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-DE
-C6
-DF
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01E5
-ENCODING 485
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-CC
-CC
-CC
-CC
-7C
-0C
-3E
-CC
-78
-00
-ENDCHAR
-STARTCHAR Gcaron
-ENCODING 486
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-3C
-66
-C2
-C0
-DE
-C6
-C6
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR gcaron
-ENCODING 487
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR uni01E8
-ENCODING 488
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-E6
-66
-66
-6C
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01E9
-ENCODING 489
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-E0
-60
-66
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01EA
-ENCODING 490
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR uni01EB
-ENCODING 491
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR uni01EC
-ENCODING 492
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR uni01ED
-ENCODING 493
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR uni01EE
-ENCODING 494
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-FE
-0C
-18
-30
-7C
-06
-06
-06
-06
-C6
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni01EF
-ENCODING 495
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-FE
-06
-0C
-18
-3C
-06
-06
-06
-C6
-7C
-00
-ENDCHAR
-STARTCHAR uni01F0
-ENCODING 496
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-1B
-0E
-04
-00
-0E
-06
-06
-06
-06
-06
-06
-66
-66
-3C
-00
-ENDCHAR
-STARTCHAR uni01F1
-ENCODING 497
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F7
-D9
-D9
-DA
-DA
-DA
-DA
-DC
-DC
-F7
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01F2
-ENCODING 498
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-D8
-D8
-DF
-D9
-DA
-DA
-DA
-DC
-F7
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01F3
-ENCODING 499
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-7F
-D9
-DA
-DA
-DA
-DC
-6F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01F4
-ENCODING 500
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-3C
-66
-C2
-C0
-DE
-C6
-C6
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01F5
-ENCODING 501
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-30
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR uni01F6
-ENCODING 502
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D8
-D8
-D8
-DB
-FB
-DB
-DB
-DB
-DB
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01F7
-ENCODING 503
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-66
-6C
-78
-70
-60
-60
-60
-60
-E0
-00
-ENDCHAR
-STARTCHAR uni01F8
-ENCODING 504
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni01F9
-ENCODING 505
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-18
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Aringacute
-ENCODING 506
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-38
-6C
-38
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR aringacute
-ENCODING 507
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-38
-6C
-38
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR AEacute
-ENCODING 508
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-3E
-6C
-CC
-CC
-FE
-CC
-CC
-CC
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR aeacute
-ENCODING 509
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-CC
-76
-36
-7E
-D8
-D8
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Oslashacute
-ENCODING 510
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-7A
-C4
-CE
-CE
-D6
-E6
-E6
-46
-BC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR oslashacute
-ENCODING 511
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-7A
-C4
-CE
-D6
-E6
-46
-BC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0200
-ENCODING 512
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-CC
-66
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0201
-ENCODING 513
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-66
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0202
-ENCODING 514
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0203
-ENCODING 515
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0204
-ENCODING 516
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-CC
-66
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0205
-ENCODING 517
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-66
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0206
-ENCODING 518
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0207
-ENCODING 519
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0208
-ENCODING 520
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-CC
-66
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0209
-ENCODING 521
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-66
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni020A
-ENCODING 522
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-3C
-66
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni020B
-ENCODING 523
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni020C
-ENCODING 524
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-CC
-66
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni020D
-ENCODING 525
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-66
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni020E
-ENCODING 526
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni020F
-ENCODING 527
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0210
-ENCODING 528
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-CC
-66
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0211
-ENCODING 529
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-66
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0212
-ENCODING 530
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0213
-ENCODING 531
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0214
-ENCODING 532
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-CC
-66
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0215
-ENCODING 533
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-66
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0216
-ENCODING 534
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0217
-ENCODING 535
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Scommaaccent
-ENCODING 536
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-60
-38
-0C
-06
-C6
-C6
-7C
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR scommaaccent
-ENCODING 537
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR Tcommaaccent
-ENCODING 538
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR tcommaaccent
-ENCODING 539
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-30
-30
-36
-1C
-00
-18
-18
-30
-ENDCHAR
-STARTCHAR uni021C
-ENCODING 540
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-86
-06
-1C
-74
-06
-06
-06
-06
-1C
-F0
-00
-00
-ENDCHAR
-STARTCHAR uni021D
-ENCODING 541
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-0E
-3C
-06
-06
-1C
-F0
-00
-00
-ENDCHAR
-STARTCHAR uni021E
-ENCODING 542
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni021F
-ENCODING 543
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-E0
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0222
-ENCODING 546
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-C6
-C6
-C6
-7C
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0223
-ENCODING 547
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-66
-66
-66
-3C
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0224
-ENCODING 548
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-86
-0C
-18
-30
-60
-C0
-C0
-FC
-06
-0C
-00
-00
-ENDCHAR
-STARTCHAR uni0225
-ENCODING 549
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-CC
-18
-30
-60
-C0
-FC
-06
-0C
-00
-00
-ENDCHAR
-STARTCHAR uni0226
-ENCODING 550
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0227
-ENCODING 551
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0228
-ENCODING 552
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-62
-66
-FE
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR uni0229
-ENCODING 553
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR uni022A
-ENCODING 554
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-00
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni022B
-ENCODING 555
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni022C
-ENCODING 556
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-00
-72
-9C
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni022D
-ENCODING 557
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-00
-76
-DC
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni022E
-ENCODING 558
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni022F
-ENCODING 559
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0230
-ENCODING 560
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-00
-30
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0231
-ENCODING 561
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-30
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0232
-ENCODING 562
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-3C
-00
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0233
-ENCODING 563
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni0250
-ENCODING 592
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-7C
-60
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0251
-ENCODING 593
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-74
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0252
-ENCODING 594
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-5C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0253
-ENCODING 595
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-60
-78
-6C
-66
-66
-66
-66
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0254
-ENCODING 596
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0255
-ENCODING 597
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-DC
-E6
-7C
-80
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0256
-ENCODING 598
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-7C
-0C
-0D
-06
-00
-ENDCHAR
-STARTCHAR uni0257
-ENCODING 599
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-0D
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0258
-ENCODING 600
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-FE
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0259
-ENCODING 601
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-06
-FE
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni025A
-ENCODING 602
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3B
-6C
-8E
-16
-26
-6C
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni025B
-ENCODING 603
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-78
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni025C
-ENCODING 604
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-3C
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni025D
-ENCODING 605
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7A
-CD
-0D
-38
-0C
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni025E
-ENCODING 606
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-DC
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni025F
-ENCODING 607
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0E
-06
-06
-1F
-06
-06
-06
-66
-66
-3C
-00
-ENDCHAR
-STARTCHAR uni0260
-ENCODING 608
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-06
-0D
-7C
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR uni0261
-ENCODING 609
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR uni0262
-ENCODING 610
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-CE
-C6
-C6
-7A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0263
-ENCODING 611
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-46
-6C
-2C
-2C
-38
-18
-18
-18
-18
-00
-ENDCHAR
-STARTCHAR uni0264
-ENCODING 612
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C2
-64
-28
-38
-38
-6C
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0265
-ENCODING 613
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CE
-CC
-CC
-CC
-CC
-DC
-6C
-0C
-0C
-0E
-00
-ENDCHAR
-STARTCHAR uni0266
-ENCODING 614
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0267
-ENCODING 615
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-60
-6C
-76
-66
-66
-66
-66
-E6
-06
-06
-1C
-00
-ENDCHAR
-STARTCHAR uni0268
-ENCODING 616
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-38
-18
-18
-3C
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0269
-ENCODING 617
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-18
-18
-18
-18
-18
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni026A
-ENCODING 618
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni026B
-ENCODING 619
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-7B
-DE
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni026C
-ENCODING 620
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-78
-58
-3E
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni026D
-ENCODING 621
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-1B
-0E
-00
-ENDCHAR
-STARTCHAR uni026E
-ENCODING 622
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-7F
-63
-66
-6C
-7E
-63
-F3
-03
-33
-1E
-00
-ENDCHAR
-STARTCHAR uni026F
-ENCODING 623
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-D6
-D6
-D6
-D6
-FE
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0270
-ENCODING 624
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-D6
-D6
-D6
-D6
-FE
-6E
-06
-06
-06
-00
-ENDCHAR
-STARTCHAR uni0271
-ENCODING 625
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-EC
-FE
-D6
-D6
-D6
-D6
-C6
-06
-06
-1C
-00
-ENDCHAR
-STARTCHAR uni0272
-ENCODING 626
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-60
-60
-C0
-00
-ENDCHAR
-STARTCHAR uni0273
-ENCODING 627
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-06
-06
-03
-00
-ENDCHAR
-STARTCHAR uni0274
-ENCODING 628
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0275
-ENCODING 629
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-FE
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0276
-ENCODING 630
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6E
-D8
-D8
-DE
-D8
-D8
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0277
-ENCODING 631
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-C6
-D6
-D6
-D6
-D6
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0278
-ENCODING 632
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-10
-7C
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-10
-00
-ENDCHAR
-STARTCHAR uni0279
-ENCODING 633
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-1E
-0C
-0C
-0C
-CC
-DC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni027A
-ENCODING 634
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-0C
-0C
-0C
-0C
-0C
-0C
-CC
-DC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni027B
-ENCODING 635
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-1E
-0C
-0C
-0C
-CC
-DC
-6C
-0C
-0D
-06
-00
-ENDCHAR
-STARTCHAR uni027C
-ENCODING 636
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-76
-66
-60
-60
-60
-60
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR uni027D
-ENCODING 637
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-76
-66
-60
-60
-60
-60
-60
-6C
-38
-00
-ENDCHAR
-STARTCHAR uni027E
-ENCODING 638
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-66
-66
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni027F
-ENCODING 639
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-78
-CC
-CC
-0C
-0C
-0C
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0280
-ENCODING 640
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FC
-66
-66
-7C
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0281
-ENCODING 641
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-E6
-66
-6C
-7C
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0282
-ENCODING 642
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-60
-38
-0C
-C6
-FC
-C0
-D8
-70
-00
-ENDCHAR
-STARTCHAR uni0283
-ENCODING 643
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0E
-1B
-19
-18
-18
-18
-18
-18
-18
-18
-98
-D8
-70
-00
-ENDCHAR
-STARTCHAR uni0284
-ENCODING 644
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0E
-1B
-19
-18
-18
-18
-18
-18
-18
-3C
-98
-D8
-70
-00
-ENDCHAR
-STARTCHAR uni0285
-ENCODING 645
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-D8
-18
-18
-18
-18
-1B
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0286
-ENCODING 646
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0E
-1B
-18
-18
-18
-18
-18
-18
-7E
-D8
-70
-00
-ENDCHAR
-STARTCHAR uni0287
-ENCODING 647
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-D8
-18
-18
-18
-18
-7E
-18
-18
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0288
-ENCODING 648
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-30
-30
-30
-30
-30
-36
-1C
-00
-ENDCHAR
-STARTCHAR uni0289
-ENCODING 649
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-66
-FF
-66
-66
-3B
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni028A
-ENCODING 650
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-EE
-6C
-6C
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni028B
-ENCODING 651
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni028C
-ENCODING 652
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-3C
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni028D
-ENCODING 653
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-FE
-D6
-D6
-D6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni028E
-ENCODING 654
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3E
-60
-C0
-FC
-C6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni028F
-ENCODING 655
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-66
-3C
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0290
-ENCODING 656
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-CC
-18
-30
-60
-C6
-FE
-06
-06
-03
-00
-ENDCHAR
-STARTCHAR uni0291
-ENCODING 657
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-CC
-18
-30
-66
-CB
-FE
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0292
-ENCODING 658
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-06
-0C
-18
-3C
-06
-06
-06
-C6
-7C
-00
-ENDCHAR
-STARTCHAR uni0293
-ENCODING 659
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-06
-0C
-18
-3C
-06
-06
-7E
-C7
-7C
-00
-ENDCHAR
-STARTCHAR uni0294
-ENCODING 660
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-06
-1C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0295
-ENCODING 661
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C0
-70
-30
-30
-30
-30
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0296
-ENCODING 662
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-18
-1C
-06
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0297
-ENCODING 663
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-C0
-C0
-C0
-C6
-7C
-00
-ENDCHAR
-STARTCHAR uni0298
-ENCODING 664
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C3
-C3
-DB
-DB
-C3
-C3
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0299
-ENCODING 665
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FC
-66
-66
-7C
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni029A
-ENCODING 666
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-76
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni029B
-ENCODING 667
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-03
-7E
-C6
-C0
-CE
-C6
-C6
-7A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni029C
-ENCODING 668
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR j
-ENCODING 669
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-0C
-00
-1C
-0C
-0C
-0C
-0C
-0C
-0C
-7E
-CC
-78
-00
-ENDCHAR
-STARTCHAR uni029D
-ENCODING 670
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CE
-CC
-6C
-3C
-3C
-6C
-CC
-0C
-0C
-0E
-00
-ENDCHAR
-STARTCHAR uni029E
-ENCODING 671
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-F0
-60
-60
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni029F
-ENCODING 672
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-06
-0D
-7C
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-0C
-1E
-00
-ENDCHAR
-STARTCHAR uni02A0
-ENCODING 673
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-06
-1C
-18
-7E
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02A1
-ENCODING 674
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C0
-70
-30
-FC
-30
-30
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02A2
-ENCODING 675
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-7F
-D9
-DA
-DA
-DA
-DC
-6F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02A3
-ENCODING 676
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-7F
-DB
-DB
-DE
-DE
-DB
-6B
-03
-1B
-0E
-00
-ENDCHAR
-STARTCHAR uni02A4
-ENCODING 677
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-7F
-D9
-DA
-DA
-DB
-DD
-6F
-04
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02A5
-ENCODING 678
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-60
-60
-F6
-6D
-6C
-66
-63
-6B
-36
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02A6
-ENCODING 679
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-26
-6D
-6C
-FC
-6C
-6C
-6C
-6C
-6C
-3C
-0C
-2C
-18
-00
-ENDCHAR
-STARTCHAR uni02A7
-ENCODING 680
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-60
-60
-F6
-6D
-6C
-6C
-6E
-6D
-36
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02A8
-ENCODING 681
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-D8
-C0
-FE
-DB
-DB
-DB
-DB
-DB
-DB
-03
-03
-0E
-00
-ENDCHAR
-STARTCHAR uni02A9
-ENCODING 682
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-66
-6D
-6C
-66
-63
-6B
-F6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02AA
-ENCODING 683
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-6F
-6B
-63
-66
-6C
-6D
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02AB
-ENCODING 684
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-D6
-7C
-6C
-28
-C6
-D6
-7C
-6C
-28
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02AC
-ENCODING 685
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-C6
-C6
-00
-00
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B0
-ENCODING 688
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-F0
-D8
-D8
-D8
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B1
-ENCODING 689
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-C0
-F0
-D8
-D8
-D8
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B2
-ENCODING 690
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-00
-38
-18
-18
-D8
-70
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B3
-ENCODING 691
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-B0
-D8
-C0
-C0
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B4
-ENCODING 692
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-18
-D8
-68
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B5
-ENCODING 693
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-18
-D8
-68
-0C
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B6
-ENCODING 694
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-D8
-D8
-F0
-D8
-D8
-F0
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B7
-ENCODING 695
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C6
-D6
-7C
-6C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B8
-ENCODING 696
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-D8
-D8
-78
-18
-70
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02B9
-ENCODING 697
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-30
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02BA
-ENCODING 698
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-36
-6C
-D8
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02BB
-ENCODING 699
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-30
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57929
-ENCODING 700
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-18
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii64937
-ENCODING 701
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-30
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02BE
-ENCODING 702
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-0C
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02BF
-ENCODING 703
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-60
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02C0
-ENCODING 704
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-D8
-18
-30
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02C1
-ENCODING 705
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-D8
-C0
-60
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02C2
-ENCODING 706
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-70
-C0
-70
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02C3
-ENCODING 707
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-70
-18
-70
-C0
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02C4
-ENCODING 708
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-20
-20
-70
-70
-D8
-D8
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02C5
-ENCODING 709
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-D8
-D8
-70
-70
-20
-20
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR circumflex
-ENCODING 710
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR caron
-ENCODING 711
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02C8
-ENCODING 712
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-18
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR macron
-ENCODING 713
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02CA
-ENCODING 714
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02CB
-ENCODING 715
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02CC
-ENCODING 716
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-18
-18
-00
-ENDCHAR
-STARTCHAR uni02CD
-ENCODING 717
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni02CE
-ENCODING 718
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-0C
-00
-ENDCHAR
-STARTCHAR uni02CF
-ENCODING 719
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-30
-60
-00
-ENDCHAR
-STARTCHAR breve
-ENCODING 728
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dotaccent
-ENCODING 729
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ring
-ENCODING 730
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-6C
-38
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ogonek
-ENCODING 731
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-30
-1C
-00
-ENDCHAR
-STARTCHAR tilde
-ENCODING 732
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR hungarumlaut
-ENCODING 733
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-CC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni02EE
-ENCODING 750
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-6C
-6C
-48
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR gravecomb
-ENCODING 768
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR acutecomb
-ENCODING 769
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR tildecomb
-ENCODING 771
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-34
-58
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR hookabovecomb
-ENCODING 777
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-18
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0312
-ENCODING 786
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-30
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0313
-ENCODING 787
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-18
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0314
-ENCODING 788
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-30
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dotbelowcomb
-ENCODING 803
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni0340
-ENCODING 832
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C0
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0341
-ENCODING 833
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-06
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0374
-ENCODING 884
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-20
-40
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0375
-ENCODING 885
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-10
-20
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uni037A
-ENCODING 890
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-30
-34
-18
-00
-ENDCHAR
-STARTCHAR uni037E
-ENCODING 894
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-18
-00
-00
-00
-18
-18
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR tonos
-ENCODING 900
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dieresistonos
-ENCODING 901
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-6C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Alphatonos
-ENCODING 902
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR anoteleia
-ENCODING 903
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Epsilontonos
-ENCODING 904
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-3E
-32
-30
-34
-3C
-34
-30
-30
-32
-3E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Etatonos
-ENCODING 905
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-33
-33
-33
-33
-3F
-33
-33
-33
-33
-33
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Iotatonos
-ENCODING 906
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-3C
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Omicrontonos
-ENCODING 908
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-3C
-66
-66
-66
-66
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Upsilontonos
-ENCODING 910
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-66
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Omegatonos
-ENCODING 911
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-3E
-63
-63
-63
-63
-63
-36
-36
-36
-77
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR iotadieresistonos
-ENCODING 912
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-6C
-00
-38
-18
-18
-18
-18
-18
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Alpha
-ENCODING 913
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Beta
-ENCODING 914
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-66
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Gamma
-ENCODING 915
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-60
-60
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Delta
-ENCODING 916
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-38
-38
-6C
-6C
-C6
-C6
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Epsilon
-ENCODING 917
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Zeta
-ENCODING 918
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-86
-0C
-18
-30
-60
-C2
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Eta
-ENCODING 919
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Theta
-ENCODING 920
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Iota
-ENCODING 921
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Kappa
-ENCODING 922
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Lambda
-ENCODING 923
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-38
-38
-6C
-6C
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Mu
-ENCODING 924
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Nu
-ENCODING 925
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Xi
-ENCODING 926
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-82
-44
-7C
-44
-00
-82
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Omicron
-ENCODING 927
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Pi
-ENCODING 928
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Rho
-ENCODING 929
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Sigma
-ENCODING 931
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-62
-30
-18
-18
-30
-62
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Tau
-ENCODING 932
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Upsilon
-ENCODING 933
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Phi
-ENCODING 934
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-7C
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Chi
-ENCODING 935
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-6C
-7C
-38
-38
-7C
-6C
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Psi
-ENCODING 936
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-92
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Omega
-ENCODING 937
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-6C
-6C
-6C
-EE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Iotadieresis
-ENCODING 938
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-66
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Upsilondieresis
-ENCODING 939
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-66
-00
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR alphatonos
-ENCODING 940
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR epsilontonos
-ENCODING 941
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-7C
-C6
-C0
-78
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR etatonos
-ENCODING 942
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-DC
-66
-66
-66
-66
-66
-66
-06
-06
-06
-00
-ENDCHAR
-STARTCHAR iotatonos
-ENCODING 943
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-38
-18
-18
-18
-18
-18
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR upsilondieresistonos
-ENCODING 944
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-6C
-00
-CC
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR alpha
-ENCODING 945
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR beta
-ENCODING 946
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-6C
-66
-66
-66
-66
-6C
-60
-60
-60
-00
-ENDCHAR
-STARTCHAR gamma
-ENCODING 947
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-46
-6C
-2C
-2C
-38
-18
-18
-18
-18
-00
-ENDCHAR
-STARTCHAR delta
-ENCODING 948
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-30
-18
-7C
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR epsilon
-ENCODING 949
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-78
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR zeta
-ENCODING 950
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-46
-7C
-18
-30
-60
-60
-C0
-C0
-C0
-7C
-06
-06
-1C
-00
-ENDCHAR
-STARTCHAR eta
-ENCODING 951
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-06
-06
-06
-00
-ENDCHAR
-STARTCHAR theta
-ENCODING 952
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-7E
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR iota
-ENCODING 953
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-18
-18
-18
-18
-18
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR kappa
-ENCODING 954
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-E6
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR lambda
-ENCODING 955
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-20
-30
-10
-38
-38
-6C
-64
-C6
-C2
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR mu
-ENCODING 956
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-F6
-C0
-C0
-C0
-00
-ENDCHAR
-STARTCHAR nu
-ENCODING 957
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-66
-6C
-3C
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR xi
-ENCODING 958
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-3C
-30
-60
-3C
-60
-C0
-C0
-C0
-7C
-06
-06
-1C
-00
-ENDCHAR
-STARTCHAR omicron
-ENCODING 959
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR pi
-ENCODING 960
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-6C
-6C
-6C
-6C
-6C
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR rho
-ENCODING 961
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-66
-66
-66
-66
-66
-7C
-60
-60
-60
-00
-ENDCHAR
-STARTCHAR sigma1
-ENCODING 962
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-7C
-06
-06
-1C
-00
-00
-ENDCHAR
-STARTCHAR sigma
-ENCODING 963
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR tau
-ENCODING 964
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-18
-18
-18
-18
-18
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR upsilon
-ENCODING 965
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR phi
-ENCODING 966
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-10
-00
-ENDCHAR
-STARTCHAR chi
-ENCODING 967
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-86
-46
-2C
-2C
-18
-30
-68
-68
-C4
-C2
-00
-ENDCHAR
-STARTCHAR psi
-ENCODING 968
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-92
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-10
-00
-ENDCHAR
-STARTCHAR omega
-ENCODING 969
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-C6
-D6
-D6
-D6
-D6
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR iotadieresis
-ENCODING 970
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-00
-38
-18
-18
-18
-18
-18
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR upsilondieresis
-ENCODING 971
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-CC
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR omicrontonos
-ENCODING 972
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR upsilontonos
-ENCODING 973
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-CC
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR omegatonos
-ENCODING 974
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-6C
-C6
-D6
-D6
-D6
-D6
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03D0
-ENCODING 976
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-6C
-7C
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR theta1
-ENCODING 977
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-36
-1E
-C6
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Upsilon1
-ENCODING 978
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C2
-65
-24
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03D3
-ENCODING 979
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-C0
-21
-32
-12
-1C
-0C
-0C
-0C
-0C
-0C
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03D4
-ENCODING 980
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C2
-65
-24
-38
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR phi1
-ENCODING 981
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-10
-7C
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-10
-00
-ENDCHAR
-STARTCHAR omega1
-ENCODING 982
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-6C
-C6
-D6
-D6
-D6
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03D7
-ENCODING 983
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-46
-A6
-2C
-38
-68
-CA
-C4
-0C
-18
-00
-00
-ENDCHAR
-STARTCHAR uni03DA
-ENCODING 986
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-C0
-C0
-60
-3C
-06
-06
-1C
-00
-00
-ENDCHAR
-STARTCHAR uni03DB
-ENCODING 987
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-C0
-C0
-C0
-C0
-C0
-7C
-06
-06
-1C
-00
-ENDCHAR
-STARTCHAR uni03DC
-ENCODING 988
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-60
-78
-68
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03DD
-ENCODING 989
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-32
-30
-30
-3C
-34
-30
-30
-30
-30
-00
-ENDCHAR
-STARTCHAR uni03DE
-ENCODING 990
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-60
-30
-30
-60
-63
-FF
-C6
-06
-0C
-0C
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03DF
-ENCODING 991
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-60
-60
-FE
-FE
-0C
-0C
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03E0
-ENCODING 992
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-AC
-26
-26
-0B
-0B
-1B
-1B
-1B
-1B
-03
-02
-04
-00
-ENDCHAR
-STARTCHAR uni03E1
-ENCODING 993
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C0
-60
-30
-18
-28
-4C
-14
-24
-06
-02
-02
-00
-ENDCHAR
-STARTCHAR uni03E2
-ENCODING 994
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-6D
-03
-3E
-00
-00
-ENDCHAR
-STARTCHAR uni03E3
-ENCODING 995
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DB
-DB
-DB
-DB
-DB
-DB
-6D
-03
-7E
-00
-00
-ENDCHAR
-STARTCHAR uni03E4
-ENCODING 996
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-D6
-C6
-C6
-C6
-7E
-06
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03E5
-ENCODING 997
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-36
-66
-66
-66
-66
-3E
-06
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03E6
-ENCODING 998
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-C0
-C0
-FC
-C6
-C6
-C6
-C6
-C6
-06
-76
-9C
-00
-ENDCHAR
-STARTCHAR uni03E7
-ENCODING 999
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-7C
-D6
-66
-06
-06
-66
-BC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03E8
-ENCODING 1000
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-06
-3C
-60
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03E9
-ENCODING 1001
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-26
-1C
-70
-C0
-C2
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03EA
-ENCODING 1002
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-68
-38
-30
-38
-38
-4C
-4C
-86
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03EB
-ENCODING 1003
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-64
-BA
-30
-38
-28
-4C
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03EC
-ENCODING 1004
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-C0
-CC
-D6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03ED
-ENCODING 1005
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-C0
-DC
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03EE
-ENCODING 1006
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-7E
-99
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03EF
-ENCODING 1007
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-1C
-18
-7E
-58
-18
-18
-18
-38
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03F0
-ENCODING 1008
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-46
-A6
-2C
-38
-68
-CA
-C4
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03F1
-ENCODING 1009
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-C6
-C6
-FC
-C0
-60
-3C
-06
-00
-ENDCHAR
-STARTCHAR uni03F2
-ENCODING 1010
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni03F3
-ENCODING 1011
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-06
-00
-0E
-06
-06
-06
-06
-06
-06
-66
-66
-3C
-00
-ENDCHAR
-STARTCHAR uni0400
-ENCODING 1024
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-18
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10023
-ENCODING 1025
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10051
-ENCODING 1026
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-B2
-30
-3E
-33
-33
-33
-33
-33
-33
-03
-06
-00
-00
-ENDCHAR
-STARTCHAR afii10052
-ENCODING 1027
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-FE
-66
-62
-60
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10053
-ENCODING 1028
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-F8
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10054
-ENCODING 1029
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-60
-38
-0C
-06
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10055
-ENCODING 1030
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10056
-ENCODING 1031
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-66
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10057
-ENCODING 1032
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-0C
-0C
-0C
-0C
-0C
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10058
-ENCODING 1033
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-D8
-D8
-D8
-DE
-DB
-DB
-DB
-DB
-DE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10059
-ENCODING 1034
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D8
-D8
-D8
-D8
-FE
-DB
-DB
-DB
-DB
-DE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10060
-ENCODING 1035
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-B2
-30
-3E
-33
-33
-33
-33
-33
-33
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10061
-ENCODING 1036
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-E6
-66
-66
-6C
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni040D
-ENCODING 1037
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-18
-00
-C6
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10062
-ENCODING 1038
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-C6
-C6
-C6
-C6
-7E
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10145
-ENCODING 1039
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-FE
-38
-10
-10
-00
-ENDCHAR
-STARTCHAR afii10017
-ENCODING 1040
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10018
-ENCODING 1041
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-60
-7C
-66
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10019
-ENCODING 1042
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-66
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10020
-ENCODING 1043
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-60
-60
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10021
-ENCODING 1044
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-FE
-C6
-82
-00
-00
-ENDCHAR
-STARTCHAR afii10022
-ENCODING 1045
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10024
-ENCODING 1046
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D6
-D6
-D6
-7C
-38
-7C
-D6
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10025
-ENCODING 1047
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-86
-06
-3C
-06
-06
-86
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10026
-ENCODING 1048
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10027
-ENCODING 1049
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-C6
-C6
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10028
-ENCODING 1050
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10029
-ENCODING 1051
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3E
-66
-66
-66
-66
-66
-66
-66
-66
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10030
-ENCODING 1052
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10031
-ENCODING 1053
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10032
-ENCODING 1054
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10033
-ENCODING 1055
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10034
-ENCODING 1056
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10035
-ENCODING 1057
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10036
-ENCODING 1058
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10037
-ENCODING 1059
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-7E
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10038
-ENCODING 1060
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-7C
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10039
-ENCODING 1061
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-6C
-7C
-38
-38
-7C
-6C
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10040
-ENCODING 1062
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-FE
-06
-02
-00
-00
-ENDCHAR
-STARTCHAR afii10041
-ENCODING 1063
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-7E
-06
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10042
-ENCODING 1064
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-D6
-D6
-D6
-D6
-D6
-D6
-D6
-D6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10043
-ENCODING 1065
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-D6
-D6
-D6
-D6
-D6
-D6
-D6
-D6
-FF
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR afii10044
-ENCODING 1066
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-B0
-B0
-30
-3C
-36
-36
-36
-36
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10045
-ENCODING 1067
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C3
-C3
-C3
-C3
-F3
-DB
-DB
-DB
-DB
-F3
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10046
-ENCODING 1068
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-7C
-66
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10047
-ENCODING 1069
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-86
-06
-3E
-06
-06
-86
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10048
-ENCODING 1070
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-9C
-B6
-B6
-B6
-F6
-B6
-B6
-B6
-B6
-9C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10049
-ENCODING 1071
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-CC
-CC
-CC
-7C
-6C
-6C
-6C
-6C
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10065
-ENCODING 1072
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10066
-ENCODING 1073
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-7C
-C0
-C0
-FC
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10067
-ENCODING 1074
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FC
-66
-66
-7C
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10068
-ENCODING 1075
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-66
-62
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10069
-ENCODING 1076
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-6C
-6C
-6C
-6C
-6C
-FE
-C6
-82
-00
-00
-ENDCHAR
-STARTCHAR afii10070
-ENCODING 1077
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10072
-ENCODING 1078
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-D6
-D6
-D6
-7C
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10073
-ENCODING 1079
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-3C
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10074
-ENCODING 1080
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10075
-ENCODING 1081
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10076
-ENCODING 1082
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-E6
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10077
-ENCODING 1083
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3E
-66
-66
-66
-66
-66
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10078
-ENCODING 1084
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10079
-ENCODING 1085
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10080
-ENCODING 1086
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10081
-ENCODING 1087
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-C6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10082
-ENCODING 1088
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-7C
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR afii10083
-ENCODING 1089
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10084
-ENCODING 1090
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-5A
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10085
-ENCODING 1091
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR afii10086
-ENCODING 1092
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-7C
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-10
-00
-ENDCHAR
-STARTCHAR afii10087
-ENCODING 1093
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-6C
-38
-38
-38
-6C
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10088
-ENCODING 1094
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-FE
-06
-02
-00
-00
-ENDCHAR
-STARTCHAR afii10089
-ENCODING 1095
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-7E
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10090
-ENCODING 1096
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-D6
-D6
-D6
-D6
-D6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10091
-ENCODING 1097
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-D6
-D6
-D6
-D6
-D6
-FF
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR afii10092
-ENCODING 1098
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-F8
-B0
-30
-3C
-36
-36
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10093
-ENCODING 1099
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C3
-C3
-C3
-F3
-DB
-DB
-F3
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10094
-ENCODING 1100
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-F0
-60
-60
-7C
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10095
-ENCODING 1101
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-3E
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10096
-ENCODING 1102
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-9C
-B6
-B6
-F6
-B6
-B6
-9C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10097
-ENCODING 1103
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-CC
-CC
-7C
-6C
-6C
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0450
-ENCODING 1104
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10071
-ENCODING 1105
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10099
-ENCODING 1106
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-F8
-60
-6C
-76
-66
-66
-66
-66
-E6
-06
-06
-1C
-00
-ENDCHAR
-STARTCHAR afii10100
-ENCODING 1107
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-FE
-66
-62
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10101
-ENCODING 1108
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-F8
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10102
-ENCODING 1109
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10103
-ENCODING 1110
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10104
-ENCODING 1111
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10105
-ENCODING 1112
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-06
-00
-0E
-06
-06
-06
-06
-06
-06
-66
-66
-3C
-00
-ENDCHAR
-STARTCHAR afii10106
-ENCODING 1113
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-78
-D8
-D8
-DE
-DB
-DB
-DE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10107
-ENCODING 1114
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-D8
-D8
-D8
-FE
-DB
-DB
-DE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10108
-ENCODING 1115
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-F8
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10109
-ENCODING 1116
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-E6
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni045D
-ENCODING 1117
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10110
-ENCODING 1118
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR afii10193
-ENCODING 1119
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-FE
-38
-10
-10
-00
-ENDCHAR
-STARTCHAR uni0460
-ENCODING 1120
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-C6
-C6
-D6
-D6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0461
-ENCODING 1121
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10146
-ENCODING 1122
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-FC
-B4
-30
-3C
-36
-36
-36
-36
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10194
-ENCODING 1123
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-30
-FC
-B4
-30
-3C
-36
-36
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0464
-ENCODING 1124
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CE
-DB
-D9
-D8
-FE
-D8
-D8
-D9
-DB
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0465
-ENCODING 1125
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CE
-DB
-D8
-FE
-D8
-DB
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0466
-ENCODING 1126
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-38
-6C
-6C
-6C
-FE
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0467
-ENCODING 1127
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-38
-38
-6C
-7C
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0468
-ENCODING 1128
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-88
-8C
-9C
-96
-F6
-B6
-BF
-AB
-EB
-EB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0469
-ENCODING 1129
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-88
-8C
-9C
-F6
-BE
-AB
-EB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni046A
-ENCODING 1130
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-6C
-6C
-38
-7C
-D6
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni046B
-ENCODING 1131
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-C6
-6C
-7C
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni046C
-ENCODING 1132
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-A3
-B2
-96
-FC
-9C
-BE
-AA
-AB
-EB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni046D
-ENCODING 1133
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-BF
-A3
-96
-FE
-AB
-AB
-EB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni046E
-ENCODING 1134
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-10
-7C
-C6
-06
-06
-7C
-06
-06
-06
-7C
-C0
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni046F
-ENCODING 1135
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-6C
-38
-10
-00
-7C
-86
-06
-7C
-06
-06
-7C
-C0
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni0470
-ENCODING 1136
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-96
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0471
-ENCODING 1137
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-10
-96
-D6
-D6
-D6
-D6
-D6
-7C
-10
-10
-10
-00
-ENDCHAR
-STARTCHAR afii10147
-ENCODING 1138
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10195
-ENCODING 1139
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-FE
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10148
-ENCODING 1140
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C2
-C6
-C6
-C4
-CC
-6C
-68
-78
-38
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10196
-ENCODING 1141
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C2
-C6
-64
-6C
-38
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0476
-ENCODING 1142
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-CC
-66
-00
-C2
-C6
-C4
-C4
-6C
-68
-78
-38
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0477
-ENCODING 1143
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-66
-00
-C2
-C6
-64
-6C
-38
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0478
-ENCODING 1144
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-D8
-D8
-DB
-DB
-DB
-DB
-DB
-DB
-6F
-03
-06
-1C
-00
-ENDCHAR
-STARTCHAR uni0479
-ENCODING 1145
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-73
-DB
-DB
-DB
-DB
-DB
-6F
-03
-06
-1C
-00
-ENDCHAR
-STARTCHAR uni047A
-ENCODING 1146
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-7C
-D6
-C6
-C6
-C6
-C6
-C6
-C6
-D6
-7C
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uni047B
-ENCODING 1147
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-7C
-D6
-C6
-C6
-C6
-D6
-7C
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uni047C
-ENCODING 1148
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-7C
-40
-6C
-C6
-C6
-D6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni047D
-ENCODING 1149
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-04
-7C
-40
-00
-6C
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni047E
-ENCODING 1150
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-54
-00
-6C
-C6
-C6
-D6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni047F
-ENCODING 1151
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-54
-00
-6C
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0480
-ENCODING 1152
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-C0
-C0
-C0
-60
-3C
-0C
-0C
-0C
-00
-ENDCHAR
-STARTCHAR uni0481
-ENCODING 1153
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-C0
-78
-18
-18
-00
-00
-ENDCHAR
-STARTCHAR uni0482
-ENCODING 1154
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-06
-3C
-0F
-18
-18
-F0
-3C
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0483
-ENCODING 1155
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-04
-7C
-40
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0484
-ENCODING 1156
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-24
-44
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0485
-ENCODING 1157
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-40
-7C
-40
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0486
-ENCODING 1158
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-04
-7C
-04
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0488
-ENCODING 1160
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-66
-00
-C3
-00
-66
-18
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0489
-ENCODING 1161
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-50
-46
-00
-82
-41
-00
-62
-0A
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni048A
-ENCODING 1162
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-C6
-C6
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni048B
-ENCODING 1163
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-C6
-CE
-DE
-FE
-F6
-E6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni048C
-ENCODING 1164
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-60
-F0
-60
-60
-60
-7C
-66
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni048D
-ENCODING 1165
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-60
-F0
-60
-60
-7C
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni048E
-ENCODING 1166
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-6E
-64
-7A
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni048F
-ENCODING 1167
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-6E
-64
-7A
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR afii10050
-ENCODING 1168
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-02
-06
-FE
-60
-60
-60
-60
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10098
-ENCODING 1169
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-02
-06
-FE
-60
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0492
-ENCODING 1170
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-60
-F8
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0493
-ENCODING 1171
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-66
-62
-F8
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0494
-ENCODING 1172
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-60
-7C
-66
-66
-66
-66
-F6
-06
-16
-0C
-00
-ENDCHAR
-STARTCHAR uni0495
-ENCODING 1173
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-66
-62
-78
-6C
-66
-F6
-06
-16
-0C
-00
-ENDCHAR
-STARTCHAR uni0496
-ENCODING 1174
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D6
-D6
-D6
-7C
-38
-7C
-D6
-D6
-D6
-D7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni0497
-ENCODING 1175
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-D6
-D6
-D6
-7C
-D6
-D6
-D7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni0498
-ENCODING 1176
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-86
-06
-3C
-06
-06
-86
-C6
-7C
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR uni0499
-ENCODING 1177
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-3C
-06
-C6
-7C
-30
-60
-38
-00
-ENDCHAR
-STARTCHAR uni049A
-ENCODING 1178
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni049B
-ENCODING 1179
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-E6
-6C
-78
-78
-6C
-66
-E7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni049C
-ENCODING 1180
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-D6
-D6
-DC
-F8
-DC
-D6
-D6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni049D
-ENCODING 1181
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-D6
-DC
-F8
-DC
-D6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni049E
-ENCODING 1182
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-F6
-6C
-78
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni049F
-ENCODING 1183
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-F0
-66
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04A0
-ENCODING 1184
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F3
-B3
-B3
-36
-3C
-3C
-36
-33
-33
-73
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04A1
-ENCODING 1185
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-F3
-B6
-BC
-3C
-36
-33
-73
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04A2
-ENCODING 1186
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04A3
-ENCODING 1187
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-FE
-C6
-C6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04A4
-ENCODING 1188
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DF
-DB
-D9
-D8
-F8
-D8
-D8
-D8
-D8
-D8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04A5
-ENCODING 1189
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DF
-DB
-D9
-F8
-D8
-D8
-D8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04A6
-ENCODING 1190
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-D8
-D8
-D8
-DE
-DB
-DB
-DB
-DB
-DB
-03
-0B
-06
-00
-ENDCHAR
-STARTCHAR uni04A7
-ENCODING 1191
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-D8
-D8
-D8
-FE
-DB
-DB
-DB
-03
-0B
-06
-00
-ENDCHAR
-STARTCHAR uni04A8
-ENCODING 1192
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C2
-CC
-D6
-D6
-D6
-D6
-D6
-CC
-7A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04A9
-ENCODING 1193
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C2
-CC
-D6
-D6
-CC
-7A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04AA
-ENCODING 1194
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-C0
-C0
-C2
-66
-3C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR uni04AB
-ENCODING 1195
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR uni04AC
-ENCODING 1196
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-0C
-04
-00
-00
-ENDCHAR
-STARTCHAR uni04AD
-ENCODING 1197
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-5A
-18
-18
-18
-18
-3C
-0C
-04
-00
-00
-ENDCHAR
-STARTCHAR uni04AE
-ENCODING 1198
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04AF
-ENCODING 1199
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-66
-66
-66
-3C
-18
-18
-18
-3C
-00
-ENDCHAR
-STARTCHAR uni04B0
-ENCODING 1200
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-66
-66
-3C
-18
-7E
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04B1
-ENCODING 1201
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-66
-66
-66
-3C
-18
-7E
-18
-3C
-00
-ENDCHAR
-STARTCHAR uni04B2
-ENCODING 1202
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-6C
-7C
-38
-38
-7C
-6C
-C6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04B3
-ENCODING 1203
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-6C
-38
-38
-38
-6C
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04B4
-ENCODING 1204
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F6
-66
-66
-66
-66
-66
-66
-66
-66
-7F
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04B5
-ENCODING 1205
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-F6
-66
-66
-66
-66
-66
-7F
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04B6
-ENCODING 1206
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-7E
-06
-06
-06
-07
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04B7
-ENCODING 1207
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-7E
-06
-06
-07
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04B8
-ENCODING 1208
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-D6
-D6
-7E
-16
-16
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04B9
-ENCODING 1209
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-D6
-D6
-7E
-16
-16
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04BA
-ENCODING 1210
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-C0
-C0
-FC
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04BB
-ENCODING 1211
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C0
-C0
-C0
-FC
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04BC
-ENCODING 1212
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-33
-B3
-B3
-7F
-30
-30
-30
-33
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04BD
-ENCODING 1213
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-9E
-B3
-7F
-30
-30
-33
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04BE
-ENCODING 1214
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-33
-B3
-B3
-7F
-30
-30
-30
-33
-1E
-0C
-18
-0E
-00
-ENDCHAR
-STARTCHAR uni04BF
-ENCODING 1215
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-9E
-B3
-7F
-30
-30
-33
-1E
-0C
-18
-0E
-00
-ENDCHAR
-STARTCHAR uni04C0
-ENCODING 1216
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04C1
-ENCODING 1217
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-D6
-D6
-D6
-7C
-38
-7C
-D6
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04C2
-ENCODING 1218
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-D6
-D6
-D6
-7C
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04C3
-ENCODING 1219
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E6
-06
-16
-0C
-00
-ENDCHAR
-STARTCHAR uni04C4
-ENCODING 1220
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-E6
-6C
-78
-78
-6C
-66
-E6
-06
-16
-0C
-00
-ENDCHAR
-STARTCHAR uni04C5
-ENCODING 1221
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3E
-66
-66
-66
-66
-66
-66
-66
-66
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04C6
-ENCODING 1222
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3E
-66
-66
-66
-66
-66
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04C7
-ENCODING 1223
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C6
-06
-16
-0C
-00
-ENDCHAR
-STARTCHAR uni04C8
-ENCODING 1224
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-06
-16
-0C
-00
-ENDCHAR
-STARTCHAR uni04C9
-ENCODING 1225
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04CA
-ENCODING 1226
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-FE
-C6
-C6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04CB
-ENCODING 1227
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-7E
-06
-06
-06
-0E
-0C
-08
-00
-00
-ENDCHAR
-STARTCHAR uni04CC
-ENCODING 1228
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-7E
-06
-06
-0E
-0C
-08
-00
-00
-ENDCHAR
-STARTCHAR uni04CD
-ENCODING 1229
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-C6
-C6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04CE
-ENCODING 1230
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C7
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni04D0
-ENCODING 1232
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04D1
-ENCODING 1233
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04D2
-ENCODING 1234
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04D3
-ENCODING 1235
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04D4
-ENCODING 1236
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3E
-6C
-CC
-CC
-FE
-CC
-CC
-CC
-CC
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04D5
-ENCODING 1237
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-76
-36
-7E
-D8
-D8
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04D6
-ENCODING 1238
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04D7
-ENCODING 1239
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04D8
-ENCODING 1240
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-06
-06
-06
-FE
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii10846
-ENCODING 1241
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-06
-FE
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04DA
-ENCODING 1242
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-7C
-C6
-06
-06
-FE
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04DB
-ENCODING 1243
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-7C
-C6
-06
-06
-FE
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04DC
-ENCODING 1244
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-D6
-D6
-D6
-7C
-38
-7C
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04DD
-ENCODING 1245
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-D6
-D6
-D6
-7C
-D6
-D6
-D6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04DE
-ENCODING 1246
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-7C
-C6
-86
-06
-3C
-06
-86
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04DF
-ENCODING 1247
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-7C
-C6
-06
-3C
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E0
-ENCODING 1248
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-06
-0C
-18
-3C
-06
-06
-86
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E1
-ENCODING 1249
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-06
-0C
-18
-3C
-06
-06
-06
-C6
-7C
-00
-ENDCHAR
-STARTCHAR uni04E2
-ENCODING 1250
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-C6
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E3
-ENCODING 1251
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E4
-ENCODING 1252
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C6
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E5
-ENCODING 1253
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-C6
-CE
-DE
-FE
-F6
-E6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E6
-ENCODING 1254
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E7
-ENCODING 1255
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E8
-ENCODING 1256
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04E9
-ENCODING 1257
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-FE
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04EA
-ENCODING 1258
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-7C
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04EB
-ENCODING 1259
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-7C
-C6
-C6
-FE
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04EC
-ENCODING 1260
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-78
-CC
-86
-06
-3E
-06
-86
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04ED
-ENCODING 1261
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-7C
-C6
-06
-3E
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04EE
-ENCODING 1262
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-C6
-C6
-C6
-C6
-7E
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04EF
-ENCODING 1263
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni04F0
-ENCODING 1264
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C6
-C6
-C6
-C6
-7E
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04F1
-ENCODING 1265
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni04F2
-ENCODING 1266
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-66
-CC
-00
-C6
-C6
-C6
-C6
-7E
-06
-06
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04F3
-ENCODING 1267
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-CC
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni04F4
-ENCODING 1268
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C6
-C6
-C6
-C6
-7E
-06
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04F5
-ENCODING 1269
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-C6
-C6
-C6
-7E
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04F8
-ENCODING 1272
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C3
-C3
-C3
-F3
-DB
-DB
-DB
-DB
-F3
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni04F9
-ENCODING 1273
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-C3
-C3
-C3
-F3
-DB
-DB
-F3
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0500
-ENCODING 1280
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-0C
-0C
-0C
-7C
-CC
-CC
-CC
-CC
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0501
-ENCODING 1281
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0502
-ENCODING 1282
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-0C
-0C
-0C
-7C
-CD
-CD
-CD
-CD
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0503
-ENCODING 1283
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CD
-CD
-CD
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0504
-ENCODING 1284
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-8C
-0C
-38
-0D
-0D
-0D
-0D
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0505
-ENCODING 1285
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-78
-CC
-0C
-39
-0D
-0D
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0506
-ENCODING 1286
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-86
-06
-3C
-06
-06
-06
-06
-07
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni0507
-ENCODING 1287
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-06
-3C
-06
-06
-07
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni0508
-ENCODING 1288
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-6C
-6C
-6C
-6C
-6D
-6D
-6D
-6D
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0509
-ENCODING 1289
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-6C
-6C
-6D
-6D
-6D
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni050A
-ENCODING 1290
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-CC
-CC
-CC
-FC
-CD
-CD
-CD
-CD
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni050B
-ENCODING 1291
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-FD
-CD
-CD
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni050C
-ENCODING 1292
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-CE
-C6
-C6
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni050D
-ENCODING 1293
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-CE
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni050E
-ENCODING 1294
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-1B
-1B
-1B
-1B
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni050F
-ENCODING 1295
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7E
-5A
-18
-1B
-1B
-1B
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0530
-ENCODING 1328
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-64
-94
-BA
-52
-4C
-30
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0531
-ENCODING 1329
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CF
-7B
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0532
-ENCODING 1330
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-66
-60
-60
-7E
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0533
-ENCODING 1331
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-CC
-CC
-CC
-7F
-0C
-0C
-0C
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0534
-ENCODING 1332
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-CC
-CC
-CC
-CF
-0C
-0C
-0C
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0535
-ENCODING 1333
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-7E
-60
-60
-66
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0536
-ENCODING 1334
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-66
-3E
-06
-0C
-D8
-FE
-C3
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0537
-ENCODING 1335
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-7E
-60
-60
-60
-60
-60
-60
-7C
-06
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0538
-ENCODING 1336
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-66
-66
-60
-60
-60
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0539
-ENCODING 1337
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-CF
-D6
-D6
-D6
-D6
-CC
-C0
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni053A
-ENCODING 1338
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-0C
-0C
-0C
-7F
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni053B
-ENCODING 1339
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-7C
-66
-66
-66
-66
-66
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni053C
-ENCODING 1340
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-60
-60
-60
-60
-60
-60
-60
-7C
-06
-00
-00
-00
-ENDCHAR
-STARTCHAR uni053D
-ENCODING 1341
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-F6
-D6
-D6
-D6
-D6
-CC
-C0
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni053E
-ENCODING 1342
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-7F
-24
-66
-66
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni053F
-ENCODING 1343
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-66
-66
-66
-66
-66
-3E
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0540
-ENCODING 1344
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-30
-18
-0C
-18
-30
-60
-F0
-3C
-0E
-04
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0541
-ENCODING 1345
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-06
-06
-06
-6C
-D8
-6E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0542
-ENCODING 1346
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-CC
-CC
-CC
-CC
-0C
-0C
-0C
-0F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0543
-ENCODING 1347
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-30
-60
-F8
-6C
-66
-66
-66
-66
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0544
-ENCODING 1348
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CF
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0545
-ENCODING 1349
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-06
-06
-7C
-06
-06
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0546
-ENCODING 1350
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-60
-66
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0547
-ENCODING 1351
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-06
-3E
-66
-60
-60
-60
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0548
-ENCODING 1352
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0549
-ENCODING 1353
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-06
-06
-06
-6C
-38
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni054A
-ENCODING 1354
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-D6
-D6
-D6
-D6
-D6
-16
-16
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni054B
-ENCODING 1355
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-76
-1E
-0E
-0C
-D8
-FE
-C3
-00
-00
-00
-ENDCHAR
-STARTCHAR uni054C
-ENCODING 1356
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-CC
-CC
-CC
-CF
-CC
-CC
-CC
-CC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni054D
-ENCODING 1357
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-66
-66
-66
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni054E
-ENCODING 1358
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-0C
-CC
-CC
-CC
-CC
-7C
-0C
-0C
-0F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni054F
-ENCODING 1359
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-60
-30
-18
-0C
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0550
-ENCODING 1360
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-66
-66
-60
-60
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0551
-ENCODING 1361
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-3C
-66
-06
-06
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0552
-ENCODING 1362
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-7C
-66
-66
-66
-66
-63
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0553
-ENCODING 1363
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-7C
-D6
-D6
-D6
-D6
-D6
-D6
-7C
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0554
-ENCODING 1364
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-7C
-60
-60
-FE
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0555
-ENCODING 1365
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-66
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0556
-ENCODING 1366
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-D0
-D0
-D0
-7C
-16
-16
-16
-D6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0559
-ENCODING 1369
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-30
-30
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni055A
-ENCODING 1370
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-18
-18
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni055B
-ENCODING 1371
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-30
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni055C
-ENCODING 1372
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-06
-3C
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni055D
-ENCODING 1373
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-18
-0C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni055E
-ENCODING 1374
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-1C
-36
-6C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni055F
-ENCODING 1375
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-60
-3E
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0561
-ENCODING 1377
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-D6
-D6
-D6
-D6
-D6
-D6
-6A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0562
-ENCODING 1378
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-66
-66
-66
-60
-60
-7E
-60
-60
-60
-00
-ENDCHAR
-STARTCHAR uni0563
-ENCODING 1379
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-CC
-CC
-CC
-CC
-CC
-7F
-0C
-0C
-0C
-00
-ENDCHAR
-STARTCHAR uni0564
-ENCODING 1380
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-F8
-CC
-CC
-CC
-CC
-CC
-CF
-0C
-0C
-0C
-00
-ENDCHAR
-STARTCHAR uni0565
-ENCODING 1381
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-7E
-60
-60
-66
-66
-66
-66
-3E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0566
-ENCODING 1382
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-0C
-0F
-00
-ENDCHAR
-STARTCHAR uni0567
-ENCODING 1383
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-60
-7C
-60
-60
-60
-60
-60
-78
-0C
-18
-00
-00
-ENDCHAR
-STARTCHAR uni0568
-ENCODING 1384
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-66
-66
-66
-66
-66
-66
-60
-60
-7E
-00
-ENDCHAR
-STARTCHAR uni0569
-ENCODING 1385
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FC
-C6
-C6
-CF
-D6
-D6
-CC
-C0
-C0
-C0
-00
-ENDCHAR
-STARTCHAR uni056A
-ENCODING 1386
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-0C
-0C
-7F
-CC
-CC
-CC
-CC
-CC
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni056B
-ENCODING 1387
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-60
-7C
-66
-66
-66
-66
-66
-66
-60
-60
-60
-00
-ENDCHAR
-STARTCHAR uni056C
-ENCODING 1388
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-30
-30
-30
-30
-30
-30
-30
-30
-30
-3E
-00
-ENDCHAR
-STARTCHAR uni056D
-ENCODING 1389
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-C0
-F6
-D6
-D6
-D6
-D6
-D6
-CA
-C0
-C0
-C0
-00
-ENDCHAR
-STARTCHAR uni056E
-ENCODING 1390
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-38
-0C
-7F
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni056F
-ENCODING 1391
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-60
-66
-66
-66
-66
-66
-66
-3E
-06
-06
-06
-00
-ENDCHAR
-STARTCHAR uni0570
-ENCODING 1392
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-60
-7C
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0571
-ENCODING 1393
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-1C
-0C
-18
-3C
-64
-66
-62
-63
-3D
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0572
-ENCODING 1394
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-F8
-CC
-CC
-CC
-CC
-CC
-CC
-0C
-0C
-0F
-00
-ENDCHAR
-STARTCHAR uni0573
-ENCODING 1395
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0E
-18
-30
-F8
-6C
-66
-66
-66
-66
-3E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0574
-ENCODING 1396
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0F
-0C
-0C
-CC
-CC
-CC
-CC
-CC
-CC
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0575
-ENCODING 1397
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-6C
-38
-00
-ENDCHAR
-STARTCHAR uni0576
-ENCODING 1398
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-66
-66
-66
-66
-66
-66
-3E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0577
-ENCODING 1399
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-66
-66
-66
-06
-0C
-18
-30
-60
-3E
-00
-ENDCHAR
-STARTCHAR uni0578
-ENCODING 1400
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0579
-ENCODING 1401
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-18
-18
-0C
-06
-0C
-18
-30
-60
-3E
-00
-ENDCHAR
-STARTCHAR uni057A
-ENCODING 1402
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-D6
-D6
-D6
-D6
-D6
-D6
-7E
-06
-06
-06
-00
-ENDCHAR
-STARTCHAR uni057B
-ENCODING 1403
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-66
-66
-66
-76
-1C
-18
-30
-60
-3E
-00
-ENDCHAR
-STARTCHAR uni057C
-ENCODING 1404
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-F8
-CC
-CC
-CC
-CC
-CC
-CF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni057D
-ENCODING 1405
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-66
-66
-66
-66
-3E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni057E
-ENCODING 1406
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-0C
-0C
-CC
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-0C
-0F
-00
-ENDCHAR
-STARTCHAR uni057F
-ENCODING 1407
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-D6
-D6
-D6
-D6
-D6
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0580
-ENCODING 1408
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-66
-66
-66
-66
-66
-66
-60
-60
-60
-00
-ENDCHAR
-STARTCHAR uni0581
-ENCODING 1409
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3E
-66
-66
-66
-66
-66
-3E
-06
-66
-3C
-00
-ENDCHAR
-STARTCHAR uni0582
-ENCODING 1410
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-30
-30
-30
-30
-30
-30
-3E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0583
-ENCODING 1411
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-10
-DC
-D6
-D6
-D6
-D6
-D6
-76
-10
-10
-10
-00
-ENDCHAR
-STARTCHAR uni0584
-ENCODING 1412
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-66
-66
-66
-66
-7C
-60
-FE
-60
-60
-00
-ENDCHAR
-STARTCHAR uni0585
-ENCODING 1413
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-66
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0586
-ENCODING 1414
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-D0
-D0
-7C
-16
-16
-16
-16
-D6
-7C
-10
-10
-10
-00
-ENDCHAR
-STARTCHAR uni0587
-ENCODING 1415
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-C0
-C0
-C0
-CC
-CC
-CC
-CC
-77
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0589
-ENCODING 1417
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni058A
-ENCODING 1418
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C0
-C6
-7C
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0591
-ENCODING 1425
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-10
-10
-38
-6C
-ENDCHAR
-STARTCHAR uni0592
-ENCODING 1426
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-00
-66
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0593
-ENCODING 1427
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-38
-10
-38
-20
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0594
-ENCODING 1428
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-00
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0595
-ENCODING 1429
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-60
-6C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0596
-ENCODING 1430
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-10
-18
-0C
-00
-ENDCHAR
-STARTCHAR uni0597
-ENCODING 1431
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0598
-ENCODING 1432
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-74
-D6
-5C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0599
-ENCODING 1433
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C0
-60
-20
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni059A
-ENCODING 1434
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-03
-06
-03
-00
-ENDCHAR
-STARTCHAR uni059B
-ENCODING 1435
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-28
-18
-30
-00
-ENDCHAR
-STARTCHAR uni059C
-ENCODING 1436
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni059D
-ENCODING 1437
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-06
-04
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni059E
-ENCODING 1438
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1B
-36
-24
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni059F
-ENCODING 1439
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-44
-AA
-6C
-28
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05A0
-ENCODING 1440
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-0A
-0C
-08
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05A1
-ENCODING 1441
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-40
-50
-E0
-80
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05A3
-ENCODING 1443
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-0C
-0C
-3C
-00
-ENDCHAR
-STARTCHAR uni05A4
-ENCODING 1444
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-30
-18
-00
-ENDCHAR
-STARTCHAR uni05A5
-ENCODING 1445
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-10
-30
-60
-00
-ENDCHAR
-STARTCHAR uni05A6
-ENCODING 1446
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-24
-6C
-D8
-00
-ENDCHAR
-STARTCHAR uni05A7
-ENCODING 1447
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-30
-08
-30
-ENDCHAR
-STARTCHAR uni05A8
-ENCODING 1448
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05A9
-ENCODING 1449
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-40
-A0
-60
-20
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05AA
-ENCODING 1450
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-6C
-38
-10
-10
-ENDCHAR
-STARTCHAR uni05AB
-ENCODING 1451
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-30
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05AC
-ENCODING 1452
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0C
-3C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05AD
-ENCODING 1453
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-04
-06
-03
-00
-ENDCHAR
-STARTCHAR uni05AE
-ENCODING 1454
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-48
-A8
-90
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05AF
-ENCODING 1455
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-38
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57799
-ENCODING 1456
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-00
-18
-00
-ENDCHAR
-STARTCHAR afii57801
-ENCODING 1457
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-DB
-00
-33
-00
-ENDCHAR
-STARTCHAR afii57800
-ENCODING 1458
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-F6
-00
-06
-00
-ENDCHAR
-STARTCHAR afii57802
-ENCODING 1459
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-F6
-60
-66
-00
-ENDCHAR
-STARTCHAR afii57793
-ENCODING 1460
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57794
-ENCODING 1461
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-66
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57795
-ENCODING 1462
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-66
-00
-18
-00
-ENDCHAR
-STARTCHAR afii57798
-ENCODING 1463
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-7E
-00
-00
-ENDCHAR
-STARTCHAR afii57797
-ENCODING 1464
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-7E
-18
-18
-ENDCHAR
-STARTCHAR afii57806
-ENCODING 1465
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-60
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57796
-ENCODING 1467
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-C0
-18
-03
-00
-ENDCHAR
-STARTCHAR afii57807
-ENCODING 1468
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57839
-ENCODING 1469
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-18
-18
-ENDCHAR
-STARTCHAR afii57645
-ENCODING 1470
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7E
-FC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57841
-ENCODING 1471
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57842
-ENCODING 1472
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57804
-ENCODING 1473
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-06
-06
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57803
-ENCODING 1474
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57658
-ENCODING 1475
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-18
-00
-00
-00
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05C4
-ENCODING 1476
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57664
-ENCODING 1488
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C6
-C6
-66
-76
-DC
-CC
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57665
-ENCODING 1489
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-F8
-0C
-0C
-0C
-0C
-0C
-0C
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57666
-ENCODING 1490
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-0C
-0C
-0C
-0C
-1C
-36
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57667
-ENCODING 1491
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57668
-ENCODING 1492
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-06
-06
-06
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57669
-ENCODING 1493
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57670
-ENCODING 1494
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-7E
-18
-18
-18
-0C
-0C
-18
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57671
-ENCODING 1495
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-66
-C6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57672
-ENCODING 1496
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-CC
-D6
-D6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57673
-ENCODING 1497
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-18
-18
-18
-30
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57674
-ENCODING 1498
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-06
-06
-06
-0C
-0C
-0C
-0C
-0C
-0C
-0E
-00
-ENDCHAR
-STARTCHAR afii57675
-ENCODING 1499
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-06
-06
-06
-06
-06
-06
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57676
-ENCODING 1500
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-FC
-06
-06
-06
-06
-0C
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57677
-ENCODING 1501
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-66
-C6
-C6
-C6
-C6
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57678
-ENCODING 1502
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-DC
-76
-66
-C6
-C6
-C6
-C6
-DE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57679
-ENCODING 1503
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-0C
-0C
-18
-18
-18
-18
-18
-18
-18
-1C
-00
-ENDCHAR
-STARTCHAR afii57680
-ENCODING 1504
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-0C
-0C
-0C
-0C
-0C
-0C
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57681
-ENCODING 1505
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-66
-C6
-C6
-C6
-C6
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57682
-ENCODING 1506
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-EE
-66
-66
-66
-66
-66
-2C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57683
-ENCODING 1507
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-F8
-4C
-CC
-CC
-EC
-0C
-0C
-0C
-0C
-0C
-0E
-00
-ENDCHAR
-STARTCHAR afii57684
-ENCODING 1508
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-46
-C6
-C6
-E6
-06
-06
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57685
-ENCODING 1509
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-EE
-66
-66
-6C
-78
-60
-60
-60
-60
-60
-70
-00
-ENDCHAR
-STARTCHAR afii57686
-ENCODING 1510
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-EE
-66
-66
-34
-18
-0C
-06
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57687
-ENCODING 1511
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-06
-06
-66
-64
-6C
-6E
-60
-60
-60
-60
-00
-ENDCHAR
-STARTCHAR afii57688
-ENCODING 1512
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-06
-06
-06
-06
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57689
-ENCODING 1513
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-D6
-D6
-D6
-D6
-D6
-F6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57690
-ENCODING 1514
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-66
-66
-66
-66
-66
-E6
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57716
-ENCODING 1520
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-CC
-66
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57717
-ENCODING 1521
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-CC
-66
-66
-66
-C6
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57718
-ENCODING 1522
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-CC
-66
-66
-66
-CC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05F3
-ENCODING 1523
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni05F4
-ENCODING 1524
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-CC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57388
-ENCODING 1548
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-10
-18
-18
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57403
-ENCODING 1563
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-18
-00
-00
-00
-18
-18
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57407
-ENCODING 1567
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-22
-20
-10
-08
-08
-00
-08
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57409
-ENCODING 1569
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-24
-20
-1E
-20
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57410
-ENCODING 1570
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-02
-3C
-40
-10
-10
-10
-10
-10
-10
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57411
-ENCODING 1571
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-20
-1C
-20
-08
-08
-08
-08
-08
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57412
-ENCODING 1572
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-1C
-20
-1C
-20
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57413
-ENCODING 1573
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-08
-08
-08
-08
-08
-00
-18
-20
-1C
-20
-00
-00
-ENDCHAR
-STARTCHAR afii57414
-ENCODING 1574
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-40
-38
-40
-07
-08
-88
-86
-81
-82
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57415
-ENCODING 1575
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-08
-08
-08
-08
-08
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57416
-ENCODING 1576
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-81
-81
-7E
-00
-00
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57417
-ENCODING 1577
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-28
-00
-00
-18
-24
-22
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57418
-ENCODING 1578
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-14
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57419
-ENCODING 1579
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57420
-ENCODING 1580
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-80
-88
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57421
-ENCODING 1581
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-80
-80
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57422
-ENCODING 1582
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-20
-00
-00
-70
-8F
-30
-40
-80
-80
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57423
-ENCODING 1583
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57424
-ENCODING 1584
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57425
-ENCODING 1585
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57426
-ENCODING 1586
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57427
-ENCODING 1587
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-01
-15
-88
-84
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57428
-ENCODING 1588
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-01
-15
-88
-84
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57429
-ENCODING 1589
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-06
-09
-31
-9E
-88
-88
-70
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57430
-ENCODING 1590
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-06
-09
-31
-9E
-88
-88
-70
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57431
-ENCODING 1591
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-20
-20
-2C
-32
-A2
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57432
-ENCODING 1592
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-20
-20
-2C
-32
-A2
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57433
-ENCODING 1593
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-80
-8C
-70
-40
-80
-80
-80
-41
-3E
-00
-00
-ENDCHAR
-STARTCHAR afii57434
-ENCODING 1594
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-40
-00
-00
-70
-80
-8C
-70
-40
-80
-80
-80
-41
-3E
-00
-00
-ENDCHAR
-STARTCHAR afii57440
-ENCODING 1600
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57441
-ENCODING 1601
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-06
-49
-85
-83
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57442
-ENCODING 1602
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0A
-00
-06
-09
-09
-47
-81
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57443
-ENCODING 1603
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-19
-21
-19
-21
-01
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57444
-ENCODING 1604
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-02
-02
-02
-02
-02
-42
-82
-82
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57445
-ENCODING 1605
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0C
-12
-12
-3C
-40
-40
-40
-40
-40
-40
-00
-00
-ENDCHAR
-STARTCHAR afii57446
-ENCODING 1606
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-00
-41
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57470
-ENCODING 1607
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-40
-30
-4E
-49
-39
-E6
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57448
-ENCODING 1608
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57449
-ENCODING 1609
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57450
-ENCODING 1610
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-24
-00
-ENDCHAR
-STARTCHAR afii57451
-ENCODING 1611
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-30
-0C
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57452
-ENCODING 1612
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-12
-CA
-2C
-70
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57453
-ENCODING 1613
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-0C
-30
-0C
-30
-00
-00
-ENDCHAR
-STARTCHAR afii57454
-ENCODING 1614
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57455
-ENCODING 1615
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-14
-0C
-08
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57456
-ENCODING 1616
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-0C
-30
-00
-00
-ENDCHAR
-STARTCHAR afii57457
-ENCODING 1617
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0A
-2A
-2C
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57458
-ENCODING 1618
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-24
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0653
-ENCODING 1619
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-01
-7E
-80
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0654
-ENCODING 1620
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-10
-0C
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0655
-ENCODING 1621
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-0C
-10
-0C
-10
-ENDCHAR
-STARTCHAR afii57392
-ENCODING 1632
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-30
-78
-30
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57393
-ENCODING 1633
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-70
-70
-38
-18
-18
-08
-08
-08
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57394
-ENCODING 1634
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-44
-FC
-F8
-60
-30
-30
-10
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57395
-ENCODING 1635
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-4A
-FE
-F4
-60
-30
-30
-10
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57396
-ENCODING 1636
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-20
-40
-30
-10
-20
-42
-7C
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57397
-ENCODING 1637
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-2C
-44
-42
-82
-82
-FE
-7C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57398
-ENCODING 1638
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-80
-F8
-78
-08
-08
-08
-0C
-0E
-06
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57399
-ENCODING 1639
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-82
-C6
-C6
-6C
-28
-38
-10
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57400
-ENCODING 1640
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-10
-38
-28
-6C
-C6
-C6
-82
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57401
-ENCODING 1641
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-F8
-88
-F8
-78
-08
-0C
-0E
-06
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57381
-ENCODING 1642
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-91
-92
-64
-08
-10
-26
-49
-89
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni066B
-ENCODING 1643
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-18
-18
-30
-30
-60
-60
-00
-00
-ENDCHAR
-STARTCHAR uni066C
-ENCODING 1644
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-18
-10
-20
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii63167
-ENCODING 1645
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-38
-FE
-7C
-38
-6C
-44
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0670
-ENCODING 1648
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-10
-10
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0671
-ENCODING 1649
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-06
-29
-5E
-00
-04
-04
-04
-04
-04
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0672
-ENCODING 1650
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-06
-28
-5E
-00
-04
-04
-04
-04
-04
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0673
-ENCODING 1651
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-04
-04
-04
-04
-04
-04
-00
-06
-28
-5E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0674
-ENCODING 1652
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-07
-08
-07
-08
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0675
-ENCODING 1653
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-04
-03
-14
-10
-10
-10
-10
-10
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0676
-ENCODING 1654
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-04
-03
-04
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0677
-ENCODING 1655
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-23
-54
-33
-24
-40
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0678
-ENCODING 1656
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-04
-03
-04
-00
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57511
-ENCODING 1657
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni067A
-ENCODING 1658
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-08
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni067B
-ENCODING 1659
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-81
-81
-7E
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uni067C
-ENCODING 1660
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-14
-40
-81
-81
-7E
-08
-14
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni067D
-ENCODING 1661
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-08
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57506
-ENCODING 1662
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-81
-81
-7E
-00
-00
-14
-00
-08
-00
-00
-ENDCHAR
-STARTCHAR uni067F
-ENCODING 1663
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-14
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0680
-ENCODING 1664
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-81
-81
-7E
-00
-00
-14
-00
-14
-00
-00
-ENDCHAR
-STARTCHAR uni0681
-ENCODING 1665
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-06
-08
-06
-08
-70
-8F
-30
-40
-80
-80
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0682
-ENCODING 1666
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-08
-00
-70
-8F
-30
-40
-80
-80
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0683
-ENCODING 1667
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-80
-94
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0684
-ENCODING 1668
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-88
-80
-88
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0685
-ENCODING 1669
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-70
-8F
-30
-40
-80
-80
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57507
-ENCODING 1670
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-94
-80
-88
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0687
-ENCODING 1671
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-94
-80
-94
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57512
-ENCODING 1672
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-20
-38
-28
-70
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0689
-ENCODING 1673
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-04
-02
-42
-3C
-08
-14
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni068A
-ENCODING 1674
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-04
-02
-42
-3C
-00
-00
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni068B
-ENCODING 1675
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-20
-38
-28
-70
-08
-04
-02
-42
-3C
-00
-00
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni068C
-ENCODING 1676
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni068D
-ENCODING 1677
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-04
-02
-42
-3C
-00
-00
-14
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni068E
-ENCODING 1678
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni068F
-ENCODING 1679
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-14
-00
-08
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0690
-ENCODING 1680
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-14
-00
-14
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57513
-ENCODING 1681
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0692
-ENCODING 1682
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-08
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0693
-ENCODING 1683
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-04
-02
-02
-04
-1C
-6A
-04
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0694
-ENCODING 1684
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-04
-02
-02
-04
-18
-62
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0695
-ENCODING 1685
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-04
-02
-02
-04
-18
-60
-00
-14
-08
-00
-00
-ENDCHAR
-STARTCHAR uni0696
-ENCODING 1686
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-04
-02
-12
-04
-18
-62
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0697
-ENCODING 1687
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-14
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57508
-ENCODING 1688
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni0699
-ENCODING 1689
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-14
-00
-14
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni069A
-ENCODING 1690
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-04
-00
-01
-15
-88
-88
-8A
-70
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni069B
-ENCODING 1691
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-01
-15
-88
-88
-90
-65
-00
-02
-00
-00
-00
-ENDCHAR
-STARTCHAR uni069C
-ENCODING 1692
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-04
-00
-0A
-00
-01
-15
-88
-88
-90
-65
-00
-02
-00
-00
-00
-ENDCHAR
-STARTCHAR uni069D
-ENCODING 1693
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-06
-09
-31
-9E
-88
-90
-65
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni069E
-ENCODING 1694
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-00
-0A
-00
-06
-09
-31
-9E
-88
-88
-70
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni069F
-ENCODING 1695
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-00
-2A
-20
-20
-2C
-32
-A2
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06A0
-ENCODING 1696
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-20
-00
-50
-00
-70
-80
-8C
-70
-40
-80
-80
-80
-41
-3E
-00
-00
-ENDCHAR
-STARTCHAR uni06A1
-ENCODING 1697
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-06
-49
-85
-83
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06A2
-ENCODING 1698
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-06
-49
-85
-83
-7E
-00
-02
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06A3
-ENCODING 1699
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-06
-49
-85
-83
-7E
-00
-08
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57505
-ENCODING 1700
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-00
-0A
-00
-06
-49
-85
-83
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06A5
-ENCODING 1701
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-06
-49
-85
-83
-7E
-00
-0A
-00
-04
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06A6
-ENCODING 1702
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0A
-00
-0A
-00
-06
-49
-85
-83
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06A7
-ENCODING 1703
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-06
-09
-09
-47
-81
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06A8
-ENCODING 1704
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-00
-0A
-00
-06
-09
-09
-47
-81
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06A9
-ENCODING 1705
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-01
-02
-04
-08
-44
-82
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06AA
-ENCODING 1706
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-20
-40
-3E
-01
-81
-7E
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06AB
-ENCODING 1707
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-01
-02
-05
-0B
-48
-84
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06AC
-ENCODING 1708
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-00
-19
-21
-19
-21
-01
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06AD
-ENCODING 1709
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-00
-29
-01
-19
-21
-19
-A1
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06AE
-ENCODING 1710
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-19
-21
-19
-21
-01
-81
-7E
-00
-14
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57509
-ENCODING 1711
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-09
-12
-04
-08
-44
-82
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B0
-ENCODING 1712
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-09
-12
-05
-0B
-48
-84
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B1
-ENCODING 1713
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-A4
-09
-12
-04
-08
-44
-82
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B2
-ENCODING 1714
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-09
-12
-04
-08
-44
-82
-82
-7C
-00
-14
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B3
-ENCODING 1715
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-09
-12
-04
-08
-44
-82
-82
-7C
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B4
-ENCODING 1716
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-44
-09
-A2
-04
-08
-44
-82
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B5
-ENCODING 1717
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-14
-08
-02
-02
-02
-02
-42
-82
-82
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B6
-ENCODING 1718
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-02
-02
-02
-02
-02
-42
-82
-82
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B7
-ENCODING 1719
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-02
-2A
-02
-02
-02
-42
-82
-82
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06B8
-ENCODING 1720
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-02
-02
-02
-02
-02
-42
-82
-82
-84
-78
-00
-14
-00
-08
-00
-ENDCHAR
-STARTCHAR uni06B9
-ENCODING 1721
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-00
-00
-41
-81
-81
-81
-42
-3C
-00
-00
-04
-00
-00
-ENDCHAR
-STARTCHAR afii57514
-ENCODING 1722
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-41
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06BB
-ENCODING 1723
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-41
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06BC
-ENCODING 1724
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-00
-41
-81
-81
-81
-42
-3C
-08
-14
-08
-00
-00
-ENDCHAR
-STARTCHAR uni06BD
-ENCODING 1725
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-00
-41
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06BE
-ENCODING 1726
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-38
-4C
-52
-32
-3C
-40
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06BF
-ENCODING 1727
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-00
-70
-8F
-30
-40
-94
-80
-88
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C0
-ENCODING 1728
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-40
-38
-40
-18
-24
-22
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C1
-ENCODING 1729
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-0C
-13
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C2
-ENCODING 1730
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-40
-38
-40
-00
-0C
-13
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C3
-ENCODING 1731
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-14
-00
-00
-00
-0C
-13
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C4
-ENCODING 1732
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-12
-0E
-12
-2C
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C5
-ENCODING 1733
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-12
-0E
-02
-3C
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C6
-ENCODING 1734
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-08
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C7
-ENCODING 1735
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-28
-18
-10
-20
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C8
-ENCODING 1736
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-08
-08
-08
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06C9
-ENCODING 1737
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-14
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06CA
-ENCODING 1738
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-14
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06CB
-ENCODING 1739
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06CC
-ENCODING 1740
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06CD
-ENCODING 1741
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-20
-47
-88
-08
-86
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06CE
-ENCODING 1742
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-50
-20
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06CF
-ENCODING 1743
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06D0
-ENCODING 1744
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-82
-7C
-00
-08
-00
-08
-ENDCHAR
-STARTCHAR uni06D1
-ENCODING 1745
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-82
-7C
-00
-14
-00
-08
-ENDCHAR
-STARTCHAR afii57519
-ENCODING 1746
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-14
-60
-80
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06D3
-ENCODING 1747
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-80
-60
-80
-08
-14
-60
-80
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06D4
-ENCODING 1748
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-3C
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57534
-ENCODING 1749
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-24
-22
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06D6
-ENCODING 1750
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-40
-40
-43
-55
-7E
-80
-7C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06D7
-ENCODING 1751
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-2A
-20
-26
-2A
-7C
-80
-7C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06D8
-ENCODING 1752
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0E
-1C
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06D9
-ENCODING 1753
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-14
-14
-08
-14
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06DA
-ENCODING 1754
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-2C
-10
-28
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06DB
-ENCODING 1755
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06DC
-ENCODING 1756
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-15
-8A
-90
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06DD
-ENCODING 1757
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-5A
-A5
-66
-5B
-81
-81
-81
-81
-81
-81
-5A
-66
-A5
-5A
-00
-ENDCHAR
-STARTCHAR uni06DE
-ENCODING 1758
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-66
-42
-42
-81
-99
-99
-81
-42
-42
-66
-18
-00
-00
-ENDCHAR
-STARTCHAR uni06DF
-ENCODING 1759
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-1C
-08
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E0
-ENCODING 1760
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E1
-ENCODING 1761
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-26
-08
-70
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E2
-ENCODING 1762
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0C
-10
-10
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E3
-ENCODING 1763
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-15
-8A
-90
-60
-ENDCHAR
-STARTCHAR uni06E4
-ENCODING 1764
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-32
-2C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E5
-ENCODING 1765
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-14
-0C
-04
-08
-30
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E6
-ENCODING 1766
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-10
-30
-40
-3E
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E7
-ENCODING 1767
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-30
-40
-3E
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E8
-ENCODING 1768
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-22
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06E9
-ENCODING 1769
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-28
-54
-AA
-92
-54
-54
-54
-54
-54
-54
-54
-82
-FE
-00
-00
-ENDCHAR
-STARTCHAR uni06EA
-ENCODING 1770
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-08
-14
-22
-14
-08
-ENDCHAR
-STARTCHAR uni06EB
-ENCODING 1771
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-14
-22
-14
-08
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06EC
-ENCODING 1772
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-3C
-3C
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06ED
-ENCODING 1773
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-0C
-0C
-10
-10
-10
-ENDCHAR
-STARTCHAR uni06F0
-ENCODING 1776
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-44
-44
-38
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F1
-ENCODING 1777
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-70
-70
-38
-18
-18
-08
-08
-08
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F2
-ENCODING 1778
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-44
-FC
-F8
-60
-30
-30
-10
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F3
-ENCODING 1779
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-4A
-FE
-F4
-60
-30
-30
-10
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F4
-ENCODING 1780
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-4E
-F0
-FE
-7C
-30
-30
-10
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F5
-ENCODING 1781
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-38
-2C
-44
-42
-82
-92
-FE
-6C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F6
-ENCODING 1782
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-60
-7E
-3C
-30
-60
-40
-80
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F7
-ENCODING 1783
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-82
-C6
-C6
-6C
-28
-38
-10
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F8
-ENCODING 1784
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-10
-38
-28
-6C
-C6
-C6
-82
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06F9
-ENCODING 1785
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-F8
-88
-F8
-78
-08
-0C
-0E
-06
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06FA
-ENCODING 1786
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-01
-15
-88
-88
-88
-72
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06FB
-ENCODING 1787
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-06
-09
-31
-9E
-88
-88
-72
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni06FC
-ENCODING 1788
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-40
-00
-00
-70
-80
-8C
-70
-40
-80
-88
-80
-41
-3E
-00
-00
-ENDCHAR
-STARTCHAR uni06FD
-ENCODING 1789
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-24
-20
-1E
-20
-00
-14
-14
-14
-14
-00
-00
-ENDCHAR
-STARTCHAR uni06FE
-ENCODING 1790
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0C
-12
-12
-3C
-40
-54
-54
-54
-54
-40
-00
-00
-ENDCHAR
-STARTCHAR m
-ENCODING 4307
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-92
-92
-92
-92
-92
-4C
-30
-4C
-02
-00
-ENDCHAR
-STARTCHAR m
-ENCODING 4311
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-92
-92
-92
-92
-92
-64
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR m
-ENCODING 4314
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-54
-AA
-AA
-AA
-82
-82
-40
-30
-4C
-02
-00
-ENDCHAR
-STARTCHAR m
-ENCODING 4317
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-92
-92
-92
-82
-82
-44
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR m
-ENCODING 4326
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-92
-92
-92
-82
-82
-40
-30
-4C
-02
-00
-ENDCHAR
-STARTCHAR uni1E00
-ENCODING 7680
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-38
-6C
-38
-ENDCHAR
-STARTCHAR uni1E01
-ENCODING 7681
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-38
-6C
-38
-ENDCHAR
-STARTCHAR uni1E02
-ENCODING 7682
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-FC
-66
-66
-66
-7C
-66
-66
-66
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E03
-ENCODING 7683
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-0C
-EC
-60
-60
-78
-6C
-66
-66
-66
-66
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E04
-ENCODING 7684
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-66
-66
-66
-66
-FC
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E05
-ENCODING 7685
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-78
-6C
-66
-66
-66
-66
-7C
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E06
-ENCODING 7686
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-66
-66
-66
-66
-FC
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E07
-ENCODING 7687
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-78
-6C
-66
-66
-66
-66
-7C
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E08
-ENCODING 7688
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-3C
-66
-C2
-C0
-C0
-C0
-C2
-66
-3C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR uni1E09
-ENCODING 7689
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR uni1E0A
-ENCODING 7690
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-F8
-6C
-66
-66
-66
-66
-66
-6C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E0B
-ENCODING 7691
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-60
-0C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E0C
-ENCODING 7692
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-66
-66
-66
-66
-6C
-F8
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E0D
-ENCODING 7693
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E0E
-ENCODING 7694
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-66
-66
-66
-66
-6C
-F8
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E0F
-ENCODING 7695
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E10
-ENCODING 7696
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-66
-66
-66
-66
-6C
-F8
-30
-18
-70
-00
-ENDCHAR
-STARTCHAR uni1E11
-ENCODING 7697
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-30
-18
-70
-00
-ENDCHAR
-STARTCHAR uni1E12
-ENCODING 7698
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-66
-66
-66
-66
-6C
-F8
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E13
-ENCODING 7699
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E14
-ENCODING 7700
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-7C
-00
-FE
-62
-68
-78
-68
-62
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E15
-ENCODING 7701
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-7C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E16
-ENCODING 7702
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-7C
-00
-FE
-62
-68
-78
-68
-62
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E17
-ENCODING 7703
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-7C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E18
-ENCODING 7704
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-62
-66
-FE
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E19
-ENCODING 7705
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E1A
-ENCODING 7706
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-62
-66
-FE
-00
-76
-DC
-00
-ENDCHAR
-STARTCHAR uni1E1B
-ENCODING 7707
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-76
-DC
-00
-ENDCHAR
-STARTCHAR uni1E1C
-ENCODING 7708
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR uni1E1D
-ENCODING 7709
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-18
-0C
-38
-00
-ENDCHAR
-STARTCHAR uni1E1E
-ENCODING 7710
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-FE
-66
-62
-68
-78
-68
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E1F
-ENCODING 7711
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-38
-6C
-64
-F0
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E20
-ENCODING 7712
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-3C
-66
-C2
-C0
-DE
-C6
-C6
-66
-3A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E21
-ENCODING 7713
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-76
-CC
-CC
-CC
-CC
-CC
-7C
-0C
-CC
-78
-00
-ENDCHAR
-STARTCHAR uni1E22
-ENCODING 7714
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E23
-ENCODING 7715
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0C
-E0
-60
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E24
-ENCODING 7716
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C6
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E25
-ENCODING 7717
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E26
-ENCODING 7718
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E27
-ENCODING 7719
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-E0
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E28
-ENCODING 7720
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C6
-60
-30
-E0
-00
-ENDCHAR
-STARTCHAR uni1E29
-ENCODING 7721
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-6C
-76
-66
-66
-66
-66
-E6
-30
-18
-70
-00
-ENDCHAR
-STARTCHAR uni1E2A
-ENCODING 7722
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-C6
-00
-6C
-38
-00
-ENDCHAR
-STARTCHAR uni1E2B
-ENCODING 7723
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-6C
-38
-00
-ENDCHAR
-STARTCHAR uni1E2C
-ENCODING 7724
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-76
-DC
-00
-ENDCHAR
-STARTCHAR uni1E2D
-ENCODING 7725
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-76
-DC
-00
-ENDCHAR
-STARTCHAR uni1E2E
-ENCODING 7726
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-66
-00
-3C
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E2F
-ENCODING 7727
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-66
-66
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E30
-ENCODING 7728
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-E6
-66
-66
-6C
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E31
-ENCODING 7729
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-0C
-EC
-60
-60
-66
-6C
-78
-78
-6C
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E32
-ENCODING 7730
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E6
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E33
-ENCODING 7731
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-66
-6C
-78
-78
-6C
-66
-E6
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E34
-ENCODING 7732
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E6
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E35
-ENCODING 7733
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-66
-6C
-78
-78
-6C
-66
-E6
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E36
-ENCODING 7734
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-60
-60
-60
-62
-66
-FE
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E37
-ENCODING 7735
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E38
-ENCODING 7736
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-F0
-60
-60
-60
-60
-60
-62
-66
-FE
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E39
-ENCODING 7737
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-38
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E3A
-ENCODING 7738
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-60
-60
-60
-62
-66
-FE
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E3B
-ENCODING 7739
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-7E
-00
-00
-ENDCHAR
-STARTCHAR uni1E3C
-ENCODING 7740
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-60
-60
-60
-62
-66
-FE
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E3D
-ENCODING 7741
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E3E
-ENCODING 7742
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E3F
-ENCODING 7743
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-EC
-FE
-D6
-D6
-D6
-D6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E40
-ENCODING 7744
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E41
-ENCODING 7745
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-EC
-FE
-D6
-D6
-D6
-D6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E42
-ENCODING 7746
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-C6
-C6
-C6
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E43
-ENCODING 7747
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-EC
-FE
-D6
-D6
-D6
-D6
-C6
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E44
-ENCODING 7748
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E45
-ENCODING 7749
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E46
-ENCODING 7750
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-C6
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E47
-ENCODING 7751
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E48
-ENCODING 7752
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-C6
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E49
-ENCODING 7753
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E4A
-ENCODING 7754
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-E6
-F6
-FE
-DE
-CE
-C6
-C6
-C6
-C6
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E4B
-ENCODING 7755
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-66
-66
-66
-66
-66
-66
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E4C
-ENCODING 7756
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-72
-9C
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E4D
-ENCODING 7757
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-76
-DC
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E4E
-ENCODING 7758
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-00
-72
-9C
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E4F
-ENCODING 7759
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-00
-76
-DC
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E50
-ENCODING 7760
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-7C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E51
-ENCODING 7761
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-7C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E52
-ENCODING 7762
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-7C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E53
-ENCODING 7763
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-7C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E54
-ENCODING 7764
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-FC
-66
-66
-66
-7C
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E55
-ENCODING 7765
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-DC
-66
-66
-66
-66
-66
-7C
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR uni1E56
-ENCODING 7766
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-FC
-66
-66
-66
-7C
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E57
-ENCODING 7767
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-DC
-66
-66
-66
-66
-66
-7C
-60
-60
-F0
-00
-ENDCHAR
-STARTCHAR uni1E58
-ENCODING 7768
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E59
-ENCODING 7769
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E5A
-ENCODING 7770
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-66
-E6
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E5B
-ENCODING 7771
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E5C
-ENCODING 7772
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-E6
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E5D
-ENCODING 7773
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E5E
-ENCODING 7774
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-6C
-66
-66
-66
-E6
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E5F
-ENCODING 7775
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-76
-66
-60
-60
-60
-F0
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E60
-ENCODING 7776
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-7C
-C6
-C6
-60
-38
-0C
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E61
-ENCODING 7777
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E62
-ENCODING 7778
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-60
-38
-0C
-06
-C6
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E63
-ENCODING 7779
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E64
-ENCODING 7780
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-6C
-18
-00
-7C
-C6
-C6
-70
-1C
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E65
-ENCODING 7781
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-60
-0C
-18
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E66
-ENCODING 7782
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-44
-38
-10
-7C
-C6
-C6
-70
-1C
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E67
-ENCODING 7783
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-44
-38
-10
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E68
-ENCODING 7784
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-7C
-C6
-C6
-60
-38
-0C
-C6
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E69
-ENCODING 7785
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-7C
-C6
-60
-38
-0C
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E6A
-ENCODING 7786
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E6B
-ENCODING 7787
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-06
-16
-30
-30
-FC
-30
-30
-30
-30
-36
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E6C
-ENCODING 7788
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E6D
-ENCODING 7789
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-30
-30
-36
-1C
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1E6E
-ENCODING 7790
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-00
-7E
-00
-00
-ENDCHAR
-STARTCHAR uni1E6F
-ENCODING 7791
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-30
-30
-36
-1C
-00
-7E
-00
-00
-ENDCHAR
-STARTCHAR uni1E70
-ENCODING 7792
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-18
-18
-18
-18
-18
-3C
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E71
-ENCODING 7793
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-30
-30
-FC
-30
-30
-30
-30
-36
-1C
-08
-1C
-36
-00
-ENDCHAR
-STARTCHAR uni1E72
-ENCODING 7794
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-6C
-6C
-00
-ENDCHAR
-STARTCHAR uni1E73
-ENCODING 7795
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-6C
-6C
-00
-ENDCHAR
-STARTCHAR uni1E74
-ENCODING 7796
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-76
-DC
-00
-ENDCHAR
-STARTCHAR uni1E75
-ENCODING 7797
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-76
-DC
-00
-ENDCHAR
-STARTCHAR uni1E76
-ENCODING 7798
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E77
-ENCODING 7799
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-10
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni1E78
-ENCODING 7800
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-72
-9C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E79
-ENCODING 7801
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-76
-DC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E7A
-ENCODING 7802
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-00
-7C
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E7B
-ENCODING 7803
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-CC
-CC
-00
-FC
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E7C
-ENCODING 7804
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-00
-C6
-C6
-C6
-C6
-C6
-C6
-6C
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E7D
-ENCODING 7805
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-66
-66
-66
-66
-66
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E7E
-ENCODING 7806
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-6C
-38
-10
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E7F
-ENCODING 7807
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-66
-66
-66
-3C
-18
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR Wgrave
-ENCODING 7808
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-00
-C6
-C6
-C6
-D6
-D6
-D6
-FE
-EE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR wgrave
-ENCODING 7809
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-C6
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Wacute
-ENCODING 7810
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-00
-C6
-C6
-C6
-D6
-D6
-D6
-FE
-EE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR wacute
-ENCODING 7811
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-18
-00
-C6
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Wdieresis
-ENCODING 7812
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C6
-C6
-C6
-D6
-D6
-D6
-FE
-EE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR wdieresis
-ENCODING 7813
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-C6
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E86
-ENCODING 7814
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-C6
-C6
-C6
-D6
-D6
-D6
-FE
-EE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E87
-ENCODING 7815
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-C6
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E88
-ENCODING 7816
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-D6
-D6
-D6
-FE
-EE
-6C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E89
-ENCODING 7817
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-D6
-D6
-D6
-FE
-6C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E8A
-ENCODING 7818
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-C6
-C6
-6C
-7C
-38
-7C
-6C
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E8B
-ENCODING 7819
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-C6
-6C
-38
-38
-38
-6C
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E8C
-ENCODING 7820
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-C6
-C6
-6C
-7C
-38
-7C
-6C
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E8D
-ENCODING 7821
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-C6
-6C
-38
-38
-38
-6C
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E8E
-ENCODING 7822
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-00
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E8F
-ENCODING 7823
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni1E90
-ENCODING 7824
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-FE
-C6
-8C
-18
-30
-60
-C2
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E91
-ENCODING 7825
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-FE
-CC
-18
-30
-60
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E92
-ENCODING 7826
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-86
-0C
-18
-30
-60
-C2
-C6
-FE
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E93
-ENCODING 7827
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-CC
-18
-30
-60
-C6
-FE
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1E94
-ENCODING 7828
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-86
-0C
-18
-30
-60
-C2
-C6
-FE
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E95
-ENCODING 7829
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-CC
-18
-30
-60
-C6
-FE
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E96
-ENCODING 7830
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-60
-60
-6C
-76
-66
-66
-66
-66
-E6
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni1E97
-ENCODING 7831
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-6C
-00
-10
-30
-FC
-30
-30
-30
-30
-36
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E98
-ENCODING 7832
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-6C
-38
-00
-C6
-C6
-D6
-D6
-D6
-FE
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E99
-ENCODING 7833
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-6C
-38
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni1E9A
-ENCODING 7834
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-0C
-18
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1E9B
-ENCODING 7835
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-00
-38
-6C
-64
-60
-60
-60
-60
-60
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EA0
-ENCODING 7840
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-C6
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EA1
-ENCODING 7841
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EA2
-ENCODING 7842
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-0C
-18
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EA3
-ENCODING 7843
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-0C
-18
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EA4
-ENCODING 7844
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-16
-38
-6C
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EA5
-ENCODING 7845
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-16
-38
-6C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EA6
-ENCODING 7846
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C0
-68
-1C
-36
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EA7
-ENCODING 7847
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C0
-68
-1C
-36
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EA8
-ENCODING 7848
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0E
-13
-3A
-6C
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EA9
-ENCODING 7849
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0E
-13
-3A
-6C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EAA
-ENCODING 7850
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-10
-28
-54
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EAB
-ENCODING 7851
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-10
-38
-44
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EAC
-ENCODING 7852
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-6C
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EAD
-ENCODING 7853
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EAE
-ENCODING 7854
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-44
-38
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EAF
-ENCODING 7855
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-18
-44
-38
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EB0
-ENCODING 7856
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-44
-38
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EB1
-ENCODING 7857
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-30
-44
-38
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EB2
-ENCODING 7858
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-08
-54
-38
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EB3
-ENCODING 7859
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-08
-54
-38
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EB4
-ENCODING 7860
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-72
-9C
-44
-38
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EB5
-ENCODING 7861
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-72
-9C
-44
-38
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EB6
-ENCODING 7862
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-6C
-38
-00
-10
-38
-6C
-C6
-C6
-FE
-C6
-C6
-C6
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EB7
-ENCODING 7863
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-38
-00
-78
-0C
-7C
-CC
-CC
-CC
-76
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EB8
-ENCODING 7864
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-66
-62
-68
-78
-68
-60
-62
-66
-FE
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1EB9
-ENCODING 7865
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EBA
-ENCODING 7866
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-0C
-18
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EBB
-ENCODING 7867
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-0C
-18
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EBC
-ENCODING 7868
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-00
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EBD
-ENCODING 7869
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EBE
-ENCODING 7870
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-23
-76
-88
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EBF
-ENCODING 7871
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-26
-70
-D8
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EC0
-ENCODING 7872
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C4
-6E
-11
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EC1
-ENCODING 7873
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C0
-64
-0E
-1B
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EC2
-ENCODING 7874
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0E
-13
-3A
-6C
-00
-FE
-62
-68
-78
-68
-62
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EC3
-ENCODING 7875
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0E
-13
-3A
-6C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EC4
-ENCODING 7876
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-10
-38
-44
-FE
-62
-68
-78
-68
-62
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EC5
-ENCODING 7877
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-10
-38
-44
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EC6
-ENCODING 7878
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-FE
-66
-62
-68
-78
-68
-62
-66
-FE
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1EC7
-ENCODING 7879
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-7C
-C6
-FE
-C0
-C0
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EC8
-ENCODING 7880
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-0C
-18
-3C
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EC9
-ENCODING 7881
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-0C
-18
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ECA
-ENCODING 7882
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1ECB
-ENCODING 7883
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-38
-18
-18
-18
-18
-18
-3C
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1ECC
-ENCODING 7884
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1ECD
-ENCODING 7885
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1ECE
-ENCODING 7886
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-0C
-18
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ECF
-ENCODING 7887
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-0C
-18
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED0
-ENCODING 7888
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-23
-76
-88
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED1
-ENCODING 7889
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-26
-70
-D8
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED2
-ENCODING 7890
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C4
-6E
-11
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED3
-ENCODING 7891
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C0
-64
-0E
-1B
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED4
-ENCODING 7892
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0E
-13
-3A
-44
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED5
-ENCODING 7893
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0E
-13
-3A
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED6
-ENCODING 7894
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-10
-28
-44
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED7
-ENCODING 7895
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-76
-DC
-10
-38
-44
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1ED8
-ENCODING 7896
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-38
-44
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1ED9
-ENCODING 7897
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-38
-6C
-00
-7C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EDA
-ENCODING 7898
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-33
-03
-7A
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EDB
-ENCODING 7899
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1B
-33
-06
-78
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EDC
-ENCODING 7900
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-33
-03
-7A
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EDD
-ENCODING 7901
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-63
-33
-06
-78
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EDE
-ENCODING 7902
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-70
-1B
-33
-7A
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EDF
-ENCODING 7903
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-1B
-33
-06
-78
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EE0
-ENCODING 7904
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-68
-B3
-03
-7A
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EE1
-ENCODING 7905
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-68
-B3
-03
-06
-78
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EE2
-ENCODING 7906
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-03
-7A
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EE3
-ENCODING 7907
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-06
-78
-CC
-CC
-CC
-CC
-CC
-78
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EE4
-ENCODING 7908
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EE5
-ENCODING 7909
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EE6
-ENCODING 7910
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-0C
-18
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EE7
-ENCODING 7911
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-18
-30
-00
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EE8
-ENCODING 7912
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-33
-03
-CE
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EE9
-ENCODING 7913
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1B
-33
-06
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EEA
-ENCODING 7914
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-33
-03
-CE
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EEB
-ENCODING 7915
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-63
-33
-06
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EEC
-ENCODING 7916
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-70
-1B
-33
-CE
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EED
-ENCODING 7917
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-1B
-33
-06
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EEE
-ENCODING 7918
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-68
-B3
-03
-CE
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EEF
-ENCODING 7919
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-68
-B3
-03
-06
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EF0
-ENCODING 7920
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-03
-CE
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-CC
-78
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR uni1EF1
-ENCODING 7921
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-06
-CC
-CC
-CC
-CC
-CC
-CC
-76
-00
-30
-30
-00
-ENDCHAR
-STARTCHAR Ygrave
-ENCODING 7922
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-18
-00
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ygrave
-ENCODING 7923
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-30
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni1EF4
-ENCODING 7924
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-18
-18
-00
-ENDCHAR
-STARTCHAR uni1EF5
-ENCODING 7925
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-C6
-C6
-C6
-C6
-7E
-0C
-18
-F6
-06
-00
-ENDCHAR
-STARTCHAR uni1EF6
-ENCODING 7926
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-0C
-18
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EF7
-ENCODING 7927
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-0C
-18
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni1EF8
-ENCODING 7928
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-3A
-5C
-00
-66
-66
-66
-3C
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1EF9
-ENCODING 7929
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-76
-DC
-00
-C6
-C6
-C6
-C6
-C6
-C6
-7E
-06
-0C
-F8
-00
-ENDCHAR
-STARTCHAR uni1F00
-ENCODING 7936
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-18
-30
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1F01
-ENCODING 7937
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-30
-18
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1F02
-ENCODING 7938
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-60
-6C
-C6
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1F03
-ENCODING 7939
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-CC
-66
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1F04
-ENCODING 7940
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-60
-66
-CC
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1F05
-ENCODING 7941
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C6
-6C
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1F06
-ENCODING 7942
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-34
-58
-0C
-18
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni1F07
-ENCODING 7943
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-34
-58
-30
-18
-00
-76
-CC
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8192
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-A4
-AA
-EA
-EA
-A6
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8193
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-A4
-EA
-AA
-AA
-A6
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8194
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-EA
-8A
-CE
-8E
-EA
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8195
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-EA
-8E
-CA
-8A
-EA
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8196
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-CA
-2E
-4A
-2A
-CA
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8197
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-AA
-AE
-EA
-2A
-2A
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8198
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-6A
-8E
-CA
-AA
-4A
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8199
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-38
-20
-30
-20
-20
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8200
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-30
-28
-30
-20
-20
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8201
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-EA
-4A
-4E
-4A
-4A
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8202
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-28
-28
-38
-28
-28
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8203
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-EA
-2A
-4E
-8E
-EE
-00
-6C
-8A
-4C
-28
-C8
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8204
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-EA
-2A
-4E
-8E
-EE
-00
-A2
-A2
-E2
-EA
-A4
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8205
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-EA
-2A
-4E
-8E
-EE
-00
-08
-08
-08
-28
-10
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8206
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-80
-80
-80
-F0
-28
-30
-28
-0A
-0E
-0E
-0A
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 8207
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-00
-C0
-A0
-C0
-A0
-20
-20
-38
-0A
-0E
-0E
-0A
-00
-FE
-00
-ENDCHAR
-STARTCHAR uni2010
-ENCODING 8208
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-7C
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2011
-ENCODING 8209
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-9C
-D2
-BC
-92
-9C
-00
-3C
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR figuredash
-ENCODING 8210
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-7E
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR endash
-ENCODING 8211
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-7E
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR emdash
-ENCODING 8212
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii00208
-ENCODING 8213
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2016
-ENCODING 8214
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR underscoredbl
-ENCODING 8215
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-FE
-00
-FE
-00
-ENDCHAR
-STARTCHAR quoteleft
-ENCODING 8216
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-30
-30
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR quoteright
-ENCODING 8217
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-18
-18
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR quotesinglbase
-ENCODING 8218
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-18
-18
-30
-00
-00
-ENDCHAR
-STARTCHAR quotereversed
-ENCODING 8219
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-30
-30
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR quotedblleft
-ENCODING 8220
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-66
-CC
-CC
-CC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR quotedblright
-ENCODING 8221
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-66
-66
-66
-CC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR quotedblbase
-ENCODING 8222
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-66
-66
-66
-CC
-00
-00
-ENDCHAR
-STARTCHAR uni201F
-ENCODING 8223
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-CC
-CC
-CC
-66
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dagger
-ENCODING 8224
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-7E
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR daggerdbl
-ENCODING 8225
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-7E
-18
-18
-7E
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR bullet
-ENCODING 8226
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-18
-3C
-3C
-18
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2023
-ENCODING 8227
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-20
-30
-38
-3C
-38
-30
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR onedotenleader
-ENCODING 8228
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR twodotenleader
-ENCODING 8229
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ellipsis
-ENCODING 8230
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-DB
-DB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2027
-ENCODING 8231
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR perthousand
-ENCODING 8240
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C0
-C6
-0C
-18
-30
-60
-C0
-36
-36
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2031
-ENCODING 8241
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C0
-C6
-0C
-18
-30
-60
-C0
-6B
-6B
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR minute
-ENCODING 8242
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR second
-ENCODING 8243
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-48
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2034
-ENCODING 8244
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-92
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2035
-ENCODING 8245
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-08
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2036
-ENCODING 8246
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-24
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2037
-ENCODING 8247
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-49
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2038
-ENCODING 8248
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-10
-38
-6C
-C6
-00
-ENDCHAR
-STARTCHAR guilsinglleft
-ENCODING 8249
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0C
-18
-30
-60
-30
-18
-0C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR guilsinglright
-ENCODING 8250
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-60
-30
-18
-0C
-18
-30
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni203B
-ENCODING 8251
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-92
-44
-28
-92
-28
-44
-92
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR exclamdbl
-ENCODING 8252
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-66
-66
-66
-66
-66
-00
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni203D
-ENCODING 8253
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-C3
-DB
-1B
-1E
-1C
-18
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni203E
-ENCODING 8254
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni203F
-ENCODING 8255
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-82
-7C
-00
-00
-ENDCHAR
-STARTCHAR uni2040
-ENCODING 8256
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-7C
-82
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2041
-ENCODING 8257
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-06
-0C
-18
-38
-6C
-00
-ENDCHAR
-STARTCHAR uni2042
-ENCODING 8258
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-38
-28
-00
-00
-44
-EE
-AA
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2043
-ENCODING 8259
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-3C
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR fraction
-ENCODING 8260
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-06
-0C
-0C
-18
-18
-30
-30
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2045
-ENCODING 8261
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-30
-30
-30
-3C
-30
-30
-30
-30
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2046
-ENCODING 8262
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-0C
-0C
-0C
-3C
-0C
-0C
-0C
-0C
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2048
-ENCODING 8264
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7B
-CF
-CF
-1B
-33
-33
-33
-00
-33
-33
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2049
-ENCODING 8265
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DE
-F3
-F3
-C6
-CC
-CC
-CC
-00
-CC
-CC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni204A
-ENCODING 8266
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-7E
-7E
-06
-06
-0C
-0C
-00
-00
-00
-ENDCHAR
-STARTCHAR uni204B
-ENCODING 8267
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-DB
-DB
-DB
-DE
-D8
-D8
-D8
-D8
-D8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni204C
-ENCODING 8268
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-3E
-72
-F2
-F2
-F2
-72
-3E
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni204D
-ENCODING 8269
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-F8
-9C
-9E
-9E
-9E
-9C
-F8
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR zerosuperior
-ENCODING 8304
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-D8
-D8
-D8
-D8
-70
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR foursuperior
-ENCODING 8308
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-18
-38
-78
-D8
-FC
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR fivesuperior
-ENCODING 8309
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-F8
-C0
-F0
-18
-D8
-70
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR sixsuperior
-ENCODING 8310
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-78
-C0
-F0
-D8
-D8
-70
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR sevensuperior
-ENCODING 8311
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-F8
-D8
-30
-30
-60
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR eightsuperior
-ENCODING 8312
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-D8
-70
-D8
-D8
-70
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ninesuperior
-ENCODING 8313
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-D8
-D8
-78
-18
-F0
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni207A
-ENCODING 8314
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-30
-FC
-30
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni207B
-ENCODING 8315
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni207C
-ENCODING 8316
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-00
-FC
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR parenleftsuperior
-ENCODING 8317
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-60
-60
-60
-60
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR parenrightsuperior
-ENCODING 8318
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-60
-30
-30
-30
-30
-60
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR nsuperior
-ENCODING 8319
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-B0
-D8
-D8
-D8
-D8
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR zeroinferior
-ENCODING 8320
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-70
-D8
-D8
-D8
-D8
-70
-00
-00
-00
-ENDCHAR
-STARTCHAR oneinferior
-ENCODING 8321
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-30
-70
-30
-30
-30
-78
-00
-00
-00
-ENDCHAR
-STARTCHAR twoinferior
-ENCODING 8322
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-70
-D8
-30
-60
-C8
-F8
-00
-00
-00
-ENDCHAR
-STARTCHAR threeinferior
-ENCODING 8323
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-70
-D8
-30
-18
-D8
-70
-00
-00
-00
-ENDCHAR
-STARTCHAR fourinferior
-ENCODING 8324
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-18
-38
-78
-D8
-FC
-18
-00
-00
-00
-ENDCHAR
-STARTCHAR fiveinferior
-ENCODING 8325
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-F8
-C0
-F0
-18
-D8
-70
-00
-00
-00
-ENDCHAR
-STARTCHAR sixinferior
-ENCODING 8326
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-78
-C0
-F0
-D8
-D8
-70
-00
-00
-00
-ENDCHAR
-STARTCHAR seveninferior
-ENCODING 8327
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-F8
-D8
-30
-30
-60
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR eightinferior
-ENCODING 8328
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-70
-D8
-70
-D8
-D8
-70
-00
-00
-00
-ENDCHAR
-STARTCHAR nineinferior
-ENCODING 8329
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-70
-D8
-D8
-78
-18
-F0
-00
-00
-00
-ENDCHAR
-STARTCHAR uni208A
-ENCODING 8330
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-30
-30
-FC
-30
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni208B
-ENCODING 8331
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-FC
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni208C
-ENCODING 8332
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-FC
-00
-FC
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR parenleftinferior
-ENCODING 8333
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-30
-60
-60
-60
-60
-30
-00
-00
-00
-ENDCHAR
-STARTCHAR parenrightinferior
-ENCODING 8334
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-60
-30
-30
-30
-30
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uni208F
-ENCODING 8335
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-B0
-D8
-D8
-D8
-D8
-00
-00
-00
-ENDCHAR
-STARTCHAR uni20A0
-ENCODING 8352
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-C0
-CF
-CC
-CC
-7F
-0C
-0C
-0F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR colonmonetary
-ENCODING 8353
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-04
-7C
-CE
-C8
-C8
-D0
-D0
-D0
-E0
-E6
-7C
-40
-40
-00
-00
-ENDCHAR
-STARTCHAR uni20A2
-ENCODING 8354
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C0
-C0
-D6
-D8
-D8
-D8
-DE
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR franc
-ENCODING 8355
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-C0
-C0
-C0
-F0
-CD
-CE
-CC
-CC
-CC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR lira
-ENCODING 8356
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-60
-F8
-60
-F8
-60
-60
-E6
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni20A5
-ENCODING 8357
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-02
-EC
-D6
-DE
-D6
-D6
-F6
-D6
-40
-00
-00
-00
-ENDCHAR
-STARTCHAR uni20A6
-ENCODING 8358
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-66
-76
-FF
-76
-6E
-FF
-6E
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR peseta
-ENCODING 8359
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-7C
-62
-66
-6F
-66
-66
-F3
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni20A8
-ENCODING 8360
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-CC
-CC
-CC
-F8
-E0
-F3
-D6
-DB
-CE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni20A9
-ENCODING 8361
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-81
-81
-81
-5A
-FF
-5A
-FF
-24
-24
-24
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii57636
-ENCODING 8362
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-F2
-8A
-AA
-AA
-AA
-AA
-A2
-BC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dong
-ENCODING 8363
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-3E
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-7C
-00
-00
-ENDCHAR
-STARTCHAR Euro
-ENCODING 8364
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-36
-60
-FC
-60
-F8
-60
-60
-36
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni20AD
-ENCODING 8365
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-6C
-78
-FE
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni20AE
-ENCODING 8366
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-7E
-5A
-18
-1E
-78
-1E
-78
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni20AF
-ENCODING 8367
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-7C
-B6
-36
-33
-33
-33
-63
-66
-F6
-DC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2100
-ENCODING 8448
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-D0
-D2
-D6
-7C
-18
-30
-6E
-D8
-98
-18
-0E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2101
-ENCODING 8449
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-D0
-D2
-D6
-7C
-18
-30
-6E
-D8
-8C
-06
-1C
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2102
-ENCODING 8450
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-62
-A0
-A0
-A0
-A0
-A0
-A0
-62
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2103
-ENCODING 8451
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-4E
-B9
-58
-18
-18
-18
-18
-18
-19
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2104
-ENCODING 8452
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-7C
-DA
-D8
-D8
-DA
-7C
-19
-3F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii61248
-ENCODING 8453
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-C0
-C2
-C6
-7C
-18
-30
-6E
-DB
-9B
-1B
-0E
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2106
-ENCODING 8454
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-70
-C0
-C2
-C6
-7C
-18
-30
-7B
-DB
-9B
-1B
-0D
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2107
-ENCODING 8455
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C2
-C0
-78
-C0
-C0
-C2
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2108
-ENCODING 8456
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-86
-26
-3E
-26
-06
-86
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2109
-ENCODING 8457
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7F
-B9
-58
-1A
-1E
-1A
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni210A
-ENCODING 8458
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-1A
-66
-46
-87
-8C
-8C
-7C
-98
-98
-70
-00
-ENDCHAR
-STARTCHAR uni210B
-ENCODING 8459
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-52
-B5
-15
-16
-2C
-34
-68
-A9
-AA
-4C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni210C
-ENCODING 8460
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-48
-B0
-80
-48
-7C
-66
-26
-26
-A6
-46
-06
-34
-48
-00
-ENDCHAR
-STARTCHAR uni210D
-ENCODING 8461
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E2
-A2
-A2
-A2
-BE
-A2
-A2
-A2
-A2
-E2
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni210E
-ENCODING 8462
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-36
-3B
-3B
-33
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni210F
-ENCODING 8463
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-1E
-18
-76
-3B
-3B
-33
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2110
-ENCODING 8464
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-33
-4E
-06
-06
-0C
-0C
-1F
-6C
-88
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Ifraktur
-ENCODING 8465
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-71
-8E
-04
-0C
-06
-03
-63
-C3
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2112
-ENCODING 8466
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-46
-49
-39
-1E
-18
-30
-70
-B1
-BA
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii61289
-ENCODING 8467
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0E
-19
-31
-32
-64
-68
-70
-E1
-66
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2114
-ENCODING 8468
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D8
-FF
-D8
-DE
-DB
-DB
-DB
-DB
-DB
-DE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2115
-ENCODING 8469
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E2
-A2
-B2
-B2
-AA
-AA
-A6
-A6
-A2
-E2
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR afii61352
-ENCODING 8470
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-CC
-CF
-ED
-FF
-FC
-DF
-CC
-CC
-CC
-CC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2117
-ENCODING 8471
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-B9
-A5
-A5
-B9
-A1
-A1
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR weierstrass
-ENCODING 8472
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-40
-8E
-93
-A3
-63
-4B
-6A
-A4
-B0
-B0
-60
-00
-ENDCHAR
-STARTCHAR uni2119
-ENCODING 8473
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-A2
-A2
-A2
-A2
-BC
-A0
-A0
-A0
-E0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni211A
-ENCODING 8474
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-A2
-A2
-A2
-A2
-A2
-A2
-AA
-A6
-7E
-01
-00
-00
-00
-ENDCHAR
-STARTCHAR uni211B
-ENCODING 8475
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3E
-4D
-4D
-19
-1E
-1C
-34
-34
-B5
-62
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Rfraktur
-ENCODING 8476
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-58
-A6
-A3
-6C
-B8
-26
-26
-26
-A7
-C2
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni211D
-ENCODING 8477
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-A2
-A2
-A2
-A2
-BC
-B0
-A8
-A4
-E2
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR prescription
-ENCODING 8478
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FC
-66
-66
-66
-7C
-6C
-6D
-67
-66
-EE
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uni211F
-ENCODING 8479
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-0C
-FC
-C6
-C6
-C6
-FC
-D8
-DC
-DC
-E6
-E6
-20
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2120
-ENCODING 8480
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-71
-DB
-35
-D1
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2121
-ENCODING 8481
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FE
-52
-5A
-52
-5F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR trademark
-ENCODING 8482
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F1
-5B
-55
-51
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2123
-ENCODING 8483
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-18
-CE
-D6
-D6
-D6
-D6
-D6
-E6
-6C
-38
-50
-40
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2124
-ENCODING 8484
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-0A
-14
-14
-28
-28
-50
-50
-A0
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2125
-ENCODING 8485
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-9C
-30
-FE
-0C
-18
-38
-0C
-06
-06
-C6
-C6
-7C
-00
-ENDCHAR
-STARTCHAR Omega
-ENCODING 8486
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-6C
-6C
-6C
-EE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2127
-ENCODING 8487
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-EE
-6C
-6C
-6C
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2128
-ENCODING 8488
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-26
-03
-13
-0C
-13
-03
-03
-66
-98
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2129
-ENCODING 8489
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-18
-18
-18
-18
-1C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni212A
-ENCODING 8490
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E6
-66
-66
-6C
-78
-78
-6C
-66
-66
-E6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni212B
-ENCODING 8491
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-6C
-38
-10
-38
-38
-6C
-6C
-C6
-FE
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni212C
-ENCODING 8492
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-2D
-2D
-1A
-1E
-1B
-31
-31
-B2
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni212D
-ENCODING 8493
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-14
-6B
-C8
-CC
-C6
-C6
-CC
-C0
-63
-1C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR estimated
-ENCODING 8494
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-66
-E7
-FF
-E0
-67
-3E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni212F
-ENCODING 8495
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-1C
-26
-44
-F8
-C0
-C8
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2130
-ENCODING 8496
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-4C
-52
-3C
-10
-3C
-60
-C0
-C3
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2131
-ENCODING 8497
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-73
-CE
-18
-3A
-5C
-18
-30
-30
-B0
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2132
-ENCODING 8498
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-0C
-0C
-0C
-2C
-3C
-2C
-8C
-CC
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2133
-ENCODING 8499
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-12
-12
-12
-16
-36
-3E
-3A
-5A
-52
-91
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2134
-ENCODING 8500
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-1C
-26
-46
-C6
-C4
-C8
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR aleph
-ENCODING 8501
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-42
-C6
-E7
-7A
-38
-5C
-CE
-E7
-63
-E2
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2136
-ENCODING 8502
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-80
-FC
-7E
-06
-06
-06
-06
-0C
-7E
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2137
-ENCODING 8503
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-40
-78
-3C
-0C
-0C
-0C
-0C
-1E
-7E
-F2
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2138
-ENCODING 8504
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-80
-FE
-7E
-0C
-0C
-0C
-0C
-0C
-1C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2139
-ENCODING 8505
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-38
-00
-78
-38
-38
-38
-38
-38
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni213A
-ENCODING 8506
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7D
-FF
-83
-86
-82
-FE
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR onethird
-ENCODING 8531
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-C2
-C6
-CC
-18
-30
-60
-DC
-86
-1C
-06
-1C
-00
-00
-ENDCHAR
-STARTCHAR twothirds
-ENCODING 8532
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-E0
-30
-62
-C6
-FC
-18
-30
-60
-DC
-86
-1C
-06
-1C
-00
-00
-ENDCHAR
-STARTCHAR uni2155
-ENCODING 8533
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-C2
-C6
-CC
-18
-30
-60
-DE
-98
-1C
-06
-1C
-00
-00
-ENDCHAR
-STARTCHAR uni2156
-ENCODING 8534
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-E0
-30
-62
-C6
-FC
-18
-30
-60
-DE
-98
-1C
-06
-1C
-00
-00
-ENDCHAR
-STARTCHAR uni2157
-ENCODING 8535
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-E0
-30
-62
-36
-EC
-18
-30
-60
-DE
-98
-1C
-06
-1C
-00
-00
-ENDCHAR
-STARTCHAR uni2158
-ENCODING 8536
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-70
-B2
-F6
-3C
-18
-30
-60
-DE
-98
-1C
-06
-1C
-00
-00
-ENDCHAR
-STARTCHAR uni2159
-ENCODING 8537
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-C2
-C6
-CC
-18
-30
-60
-DC
-B0
-3C
-36
-1C
-00
-00
-ENDCHAR
-STARTCHAR uni215A
-ENCODING 8538
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-F0
-C0
-E2
-36
-EC
-18
-30
-60
-DC
-B0
-3C
-36
-1C
-00
-00
-ENDCHAR
-STARTCHAR oneeighth
-ENCODING 8539
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-C2
-C6
-CC
-18
-30
-60
-DC
-B6
-1C
-36
-1C
-00
-00
-ENDCHAR
-STARTCHAR threeeighths
-ENCODING 8540
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-E0
-30
-62
-36
-EC
-18
-30
-60
-DC
-B6
-1C
-36
-1C
-00
-00
-ENDCHAR
-STARTCHAR fiveeighths
-ENCODING 8541
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-F0
-80
-E2
-36
-EC
-18
-30
-60
-DC
-B6
-1C
-36
-1C
-00
-00
-ENDCHAR
-STARTCHAR seveneighths
-ENCODING 8542
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-F0
-30
-62
-66
-6C
-18
-30
-60
-DC
-B6
-1C
-36
-1C
-00
-00
-ENDCHAR
-STARTCHAR uni215F
-ENCODING 8543
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-C2
-C6
-CC
-18
-30
-60
-C0
-80
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2160
-ENCODING 8544
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2161
-ENCODING 8545
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2162
-ENCODING 8546
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2163
-ENCODING 8547
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-CE
-CE
-C4
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2164
-ENCODING 8548
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-6C
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2165
-ENCODING 8549
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-73
-73
-23
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2166
-ENCODING 8550
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-95
-95
-95
-95
-95
-95
-95
-65
-65
-65
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2167
-ENCODING 8551
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-B5
-B5
-B5
-B5
-B5
-B5
-55
-55
-55
-55
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2168
-ENCODING 8552
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-DB
-CE
-CE
-CE
-DB
-DB
-DB
-DB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2169
-ENCODING 8553
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-6C
-7C
-38
-38
-7C
-6C
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni216A
-ENCODING 8554
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-DB
-73
-73
-73
-DB
-DB
-DB
-DB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni216B
-ENCODING 8555
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-95
-95
-95
-65
-65
-65
-95
-95
-95
-95
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni216C
-ENCODING 8556
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-60
-60
-60
-60
-60
-60
-62
-66
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni216D
-ENCODING 8557
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-C2
-C0
-C0
-C0
-C0
-C2
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni216E
-ENCODING 8558
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-6C
-66
-66
-66
-66
-66
-66
-6C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni216F
-ENCODING 8559
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-EE
-FE
-FE
-D6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2170
-ENCODING 8560
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2171
-ENCODING 8561
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-00
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2172
-ENCODING 8562
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-DB
-DB
-00
-DB
-DB
-DB
-DB
-DB
-DB
-DB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2173
-ENCODING 8563
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-00
-DB
-DB
-DB
-DB
-DB
-CE
-C4
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2174
-ENCODING 8564
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-66
-66
-66
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2175
-ENCODING 8565
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-00
-DB
-DB
-DB
-DB
-DB
-73
-23
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2176
-ENCODING 8566
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-05
-05
-00
-95
-95
-95
-95
-95
-65
-65
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2177
-ENCODING 8567
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-15
-15
-00
-B5
-B5
-B5
-B5
-55
-55
-55
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2178
-ENCODING 8568
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-00
-DB
-DB
-CE
-CE
-CE
-DB
-DB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2179
-ENCODING 8569
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-6C
-38
-38
-38
-6C
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni217A
-ENCODING 8570
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-00
-DB
-DB
-73
-73
-73
-DB
-DB
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni217B
-ENCODING 8571
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-05
-05
-00
-95
-95
-65
-65
-95
-95
-95
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni217C
-ENCODING 8572
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-18
-18
-18
-18
-18
-18
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni217D
-ENCODING 8573
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-7C
-C6
-C0
-C0
-C0
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni217E
-ENCODING 8574
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-0C
-0C
-3C
-6C
-CC
-CC
-CC
-CC
-76
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni217F
-ENCODING 8575
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-EC
-FE
-D6
-D6
-D6
-D6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2180
-ENCODING 8576
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-5A
-DB
-DB
-DB
-DB
-DB
-DB
-5A
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2181
-ENCODING 8577
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-CC
-E6
-D6
-D6
-D6
-D6
-E6
-CC
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2182
-ENCODING 8578
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-5A
-99
-BD
-DB
-DB
-BD
-99
-5A
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2183
-ENCODING 8579
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-CC
-86
-06
-06
-06
-06
-86
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowleft
-ENCODING 8592
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-30
-60
-FF
-60
-30
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowup
-ENCODING 8593
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-7E
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowright
-ENCODING 8594
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-06
-FF
-06
-0C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowdown
-ENCODING 8595
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-18
-18
-18
-7E
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowboth
-ENCODING 8596
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-24
-66
-FF
-66
-24
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowupdn
-ENCODING 8597
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-7E
-18
-18
-18
-7E
-3C
-18
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2196
-ENCODING 8598
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-F0
-E0
-B0
-18
-0C
-06
-03
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2197
-ENCODING 8599
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-0F
-07
-0D
-18
-30
-60
-C0
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2198
-ENCODING 8600
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C0
-60
-30
-18
-0D
-07
-0F
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2199
-ENCODING 8601
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-03
-06
-0C
-18
-B0
-E0
-F0
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni219A
-ENCODING 8602
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-32
-62
-FF
-64
-34
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni219B
-ENCODING 8603
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-2C
-26
-FF
-46
-4C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni219C
-ENCODING 8604
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-E0
-CE
-BB
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni219D
-ENCODING 8605
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-07
-73
-DD
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni219E
-ENCODING 8606
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-36
-6C
-FF
-6C
-36
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni219F
-ENCODING 8607
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-7E
-18
-3C
-7E
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A0
-ENCODING 8608
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-6C
-36
-FF
-36
-6C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A1
-ENCODING 8609
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-7E
-3C
-18
-7E
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A2
-ENCODING 8610
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-33
-66
-FC
-66
-33
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A3
-ENCODING 8611
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-66
-3F
-66
-CC
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A4
-ENCODING 8612
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-33
-63
-FF
-63
-33
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A5
-ENCODING 8613
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-7E
-18
-18
-18
-18
-18
-18
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A6
-ENCODING 8614
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-CC
-C6
-FF
-C6
-CC
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A7
-ENCODING 8615
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-18
-18
-18
-18
-18
-18
-7E
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowupdnbse
-ENCODING 8616
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-7E
-18
-18
-18
-7E
-3C
-18
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21A9
-ENCODING 8617
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-06
-33
-63
-FE
-60
-30
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21AA
-ENCODING 8618
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-60
-CC
-C6
-7F
-06
-0C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21AB
-ENCODING 8619
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-06
-3B
-6B
-FE
-68
-30
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21AC
-ENCODING 8620
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-60
-DC
-D6
-7F
-16
-0C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21AD
-ENCODING 8621
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-24
-5A
-FF
-66
-24
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21AE
-ENCODING 8622
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-2C
-6E
-FF
-76
-34
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21AF
-ENCODING 8623
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-30
-60
-63
-FF
-C6
-16
-1C
-1C
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B0
-ENCODING 8624
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-30
-60
-FE
-66
-36
-06
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B1
-ENCODING 8625
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-0C
-FE
-CC
-D8
-C0
-C0
-C0
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B2
-ENCODING 8626
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-06
-06
-06
-06
-36
-66
-FE
-60
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B3
-ENCODING 8627
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C0
-C0
-C0
-C0
-D8
-CC
-FE
-0C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B4
-ENCODING 8628
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FC
-0C
-0C
-3F
-1E
-0C
-00
-00
-00
-ENDCHAR
-STARTCHAR carriagereturn
-ENCODING 8629
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-06
-36
-66
-FE
-60
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B6
-ENCODING 8630
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-1E
-33
-33
-33
-30
-FC
-78
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B7
-ENCODING 8631
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-78
-CC
-CC
-CC
-0C
-3F
-1E
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B8
-ENCODING 8632
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-00
-F0
-E0
-B0
-18
-0C
-06
-03
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21B9
-ENCODING 8633
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-98
-B0
-FF
-B0
-98
-19
-0D
-FF
-0D
-19
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21BA
-ENCODING 8634
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-1E
-1C
-16
-03
-C3
-C3
-C3
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21BB
-ENCODING 8635
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-78
-38
-68
-C0
-C3
-C3
-C3
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21BC
-ENCODING 8636
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-30
-60
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21BD
-ENCODING 8637
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-60
-30
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21BE
-ENCODING 8638
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-1C
-1E
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21BF
-ENCODING 8639
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-38
-78
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C0
-ENCODING 8640
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-06
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C1
-ENCODING 8641
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-06
-0C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C2
-ENCODING 8642
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-18
-18
-18
-1E
-1C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C3
-ENCODING 8643
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-18
-18
-18
-78
-38
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C4
-ENCODING 8644
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-06
-FF
-06
-0C
-30
-60
-FF
-60
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C5
-ENCODING 8645
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-2E
-3F
-24
-24
-24
-24
-FC
-74
-24
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C6
-ENCODING 8646
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-60
-FF
-60
-30
-0C
-06
-FF
-06
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C7
-ENCODING 8647
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-60
-FE
-60
-30
-00
-30
-60
-FE
-60
-30
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C8
-ENCODING 8648
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-7E
-FF
-24
-24
-24
-24
-24
-24
-24
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21C9
-ENCODING 8649
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-0C
-FE
-0C
-18
-00
-18
-0C
-FE
-0C
-18
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21CA
-ENCODING 8650
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-24
-24
-24
-24
-24
-24
-FF
-7E
-24
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21CB
-ENCODING 8651
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-30
-60
-FF
-00
-FF
-06
-0C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21CC
-ENCODING 8652
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0C
-06
-FF
-00
-FF
-60
-30
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21CD
-ENCODING 8653
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-22
-7F
-C4
-7F
-24
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21CE
-ENCODING 8654
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-2C
-7E
-CB
-7E
-34
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21CF
-ENCODING 8655
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-24
-FE
-23
-FE
-44
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowdblleft
-ENCODING 8656
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-20
-7F
-C0
-7F
-20
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowdblup
-ENCODING 8657
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-7C
-EE
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowdblright
-ENCODING 8658
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-04
-FE
-03
-FE
-04
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowdbldown
-ENCODING 8659
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-EE
-7C
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR arrowdblboth
-ENCODING 8660
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-24
-7E
-C3
-7E
-24
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21D5
-ENCODING 8661
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-7C
-EE
-6C
-6C
-6C
-6C
-EE
-7C
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21D6
-ENCODING 8662
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-F0
-E0
-B0
-D8
-EC
-B6
-1B
-0C
-04
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21D7
-ENCODING 8663
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-0F
-07
-0D
-1B
-37
-6D
-D8
-30
-20
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21D8
-ENCODING 8664
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-20
-30
-D8
-6D
-37
-1B
-0D
-07
-0F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21D9
-ENCODING 8665
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-04
-0C
-1B
-B6
-EC
-D8
-B0
-E0
-F0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21DA
-ENCODING 8666
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-3F
-60
-FF
-60
-3F
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21DB
-ENCODING 8667
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-FC
-06
-FF
-06
-FC
-08
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21DC
-ENCODING 8668
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-30
-6A
-FF
-65
-30
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21DD
-ENCODING 8669
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-A6
-FF
-56
-0C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21DE
-ENCODING 8670
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-7E
-18
-18
-3C
-18
-3C
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21DF
-ENCODING 8671
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-3C
-18
-3C
-18
-18
-7E
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E0
-ENCODING 8672
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-30
-60
-D5
-60
-30
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E1
-ENCODING 8673
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-66
-18
-00
-18
-00
-18
-00
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E2
-ENCODING 8674
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-06
-AB
-06
-0C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E3
-ENCODING 8675
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-00
-18
-00
-18
-00
-18
-66
-3C
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E4
-ENCODING 8676
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-98
-B0
-FF
-B0
-98
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E5
-ENCODING 8677
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-19
-0D
-FF
-0D
-19
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E6
-ENCODING 8678
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-3F
-41
-81
-41
-3F
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E7
-ENCODING 8679
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-44
-C6
-44
-44
-44
-44
-44
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E8
-ENCODING 8680
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-FC
-82
-81
-82
-FC
-08
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21E9
-ENCODING 8681
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-44
-44
-44
-44
-44
-C6
-44
-28
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21EA
-ENCODING 8682
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-44
-C6
-44
-44
-7C
-00
-7C
-44
-7C
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21EB
-ENCODING 8683
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-44
-C6
-44
-44
-44
-C6
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21EC
-ENCODING 8684
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-7C
-C6
-44
-44
-44
-C6
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21ED
-ENCODING 8685
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-54
-D6
-54
-54
-54
-D6
-92
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21EE
-ENCODING 8686
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-28
-54
-EE
-44
-C6
-44
-44
-44
-44
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21EF
-ENCODING 8687
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-28
-54
-EE
-44
-C6
-44
-44
-C6
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21F0
-ENCODING 8688
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-E8
-BC
-82
-81
-82
-BC
-E8
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21F1
-ENCODING 8689
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-80
-BC
-B8
-AC
-86
-83
-81
-80
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21F2
-ENCODING 8690
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-01
-81
-C1
-61
-35
-1D
-3D
-01
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni21F3
-ENCODING 8691
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-44
-C6
-44
-44
-44
-C6
-44
-28
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR universal
-ENCODING 8704
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-FE
-C6
-6C
-6C
-38
-38
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2201
-ENCODING 8705
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-66
-60
-60
-60
-60
-60
-66
-3C
-00
-00
-ENDCHAR
-STARTCHAR partialdiff
-ENCODING 8706
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-06
-06
-3E
-66
-C6
-C6
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR existential
-ENCODING 8707
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-06
-06
-06
-7E
-06
-06
-06
-06
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2204
-ENCODING 8708
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-FE
-16
-16
-16
-7E
-16
-26
-26
-26
-FE
-40
-00
-00
-00
-ENDCHAR
-STARTCHAR emptyset
-ENCODING 8709
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-3E
-66
-CF
-DB
-DB
-F3
-66
-7C
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR Delta
-ENCODING 8710
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-38
-38
-6C
-6C
-C6
-C6
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR gradient
-ENCODING 8711
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-C6
-C6
-6C
-6C
-38
-38
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR element
-ENCODING 8712
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-3E
-60
-C0
-C0
-FE
-C0
-C0
-60
-3E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR notelement
-ENCODING 8713
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-3E
-64
-C8
-C8
-FE
-C8
-D0
-70
-3E
-20
-00
-00
-00
-ENDCHAR
-STARTCHAR uni220A
-ENCODING 8714
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-3E
-60
-C0
-FE
-C0
-60
-3E
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR suchthat
-ENCODING 8715
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-F8
-0C
-06
-06
-FE
-06
-06
-0C
-F8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni220C
-ENCODING 8716
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-F8
-1C
-16
-26
-FE
-26
-26
-4C
-F8
-40
-00
-00
-00
-ENDCHAR
-STARTCHAR uni220D
-ENCODING 8717
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-F8
-0C
-06
-FE
-06
-0C
-F8
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni220E
-ENCODING 8718
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-7E
-7E
-7E
-7E
-7E
-7E
-7E
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR product
-ENCODING 8719
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-66
-66
-66
-66
-66
-66
-66
-66
-66
-66
-E7
-00
-00
-ENDCHAR
-STARTCHAR uni2210
-ENCODING 8720
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E7
-66
-66
-66
-66
-66
-66
-66
-66
-66
-66
-FF
-00
-00
-ENDCHAR
-STARTCHAR summation
-ENCODING 8721
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-C1
-60
-30
-18
-0C
-0C
-18
-30
-60
-C1
-FF
-00
-00
-ENDCHAR
-STARTCHAR minus
-ENCODING 8722
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-7E
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2213
-ENCODING 8723
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-7E
-00
-18
-18
-7E
-18
-18
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2214
-ENCODING 8724
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-18
-00
-18
-18
-7E
-18
-18
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR fraction
-ENCODING 8725
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-06
-06
-0C
-0C
-18
-18
-30
-30
-60
-60
-C0
-C0
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2216
-ENCODING 8726
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-C0
-60
-60
-30
-30
-18
-18
-0C
-0C
-06
-06
-00
-00
-00
-ENDCHAR
-STARTCHAR asteriskmath
-ENCODING 8727
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-24
-18
-7E
-18
-24
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2218
-ENCODING 8728
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-24
-24
-18
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR periodcentered
-ENCODING 8729
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-3C
-3C
-18
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR radical
-ENCODING 8730
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-06
-06
-06
-0C
-CC
-6C
-38
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni221B
-ENCODING 8731
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E3
-33
-66
-36
-E6
-0C
-CC
-6C
-38
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni221C
-ENCODING 8732
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-33
-73
-B6
-F6
-36
-0C
-CC
-6C
-38
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR proportional
-ENCODING 8733
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-D8
-D8
-6E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR infinity
-ENCODING 8734
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-DB
-DB
-6E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR orthogonal
-ENCODING 8735
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-C0
-C0
-C0
-C0
-C0
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR angle
-ENCODING 8736
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-02
-06
-0C
-18
-30
-60
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2221
-ENCODING 8737
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-02
-16
-0C
-1C
-34
-62
-FF
-02
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2222
-ENCODING 8738
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-0E
-38
-E8
-38
-0E
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2223
-ENCODING 8739
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2224
-ENCODING 8740
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-1A
-1C
-38
-58
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2225
-ENCODING 8741
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2226
-ENCODING 8742
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6C
-6C
-6C
-6E
-7C
-EC
-6C
-6C
-6C
-6C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR logicaland
-ENCODING 8743
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-10
-38
-38
-6C
-6C
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR logicalor
-ENCODING 8744
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C6
-C6
-6C
-6C
-38
-38
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR intersection
-ENCODING 8745
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-7C
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR union
-ENCODING 8746
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR integral
-ENCODING 8747
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-1A
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-58
-30
-00
-00
-ENDCHAR
-STARTCHAR uni222C
-ENCODING 8748
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-33
-66
-66
-66
-66
-66
-66
-66
-66
-66
-66
-66
-66
-CC
-00
-00
-ENDCHAR
-STARTCHAR uni222D
-ENCODING 8749
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-2A
-54
-54
-54
-54
-54
-54
-54
-54
-54
-54
-54
-54
-A8
-00
-00
-ENDCHAR
-STARTCHAR uni222E
-ENCODING 8750
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-1A
-18
-18
-3C
-5A
-99
-99
-5A
-3C
-18
-18
-58
-30
-00
-00
-ENDCHAR
-STARTCHAR uni222F
-ENCODING 8751
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-33
-66
-66
-66
-7E
-E7
-E7
-E7
-E7
-7E
-66
-66
-66
-CC
-00
-00
-ENDCHAR
-STARTCHAR uni2230
-ENCODING 8752
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-2A
-54
-54
-54
-7C
-D6
-D6
-D6
-D6
-7C
-54
-54
-54
-A8
-00
-00
-ENDCHAR
-STARTCHAR uni2231
-ENCODING 8753
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-34
-30
-30
-38
-35
-33
-37
-30
-30
-30
-30
-B0
-60
-00
-00
-ENDCHAR
-STARTCHAR uni2232
-ENCODING 8754
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-1A
-18
-18
-3C
-5A
-FA
-5A
-5A
-3C
-18
-18
-58
-30
-00
-00
-ENDCHAR
-STARTCHAR uni2233
-ENCODING 8755
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-1A
-18
-18
-3C
-5A
-5F
-5A
-5A
-3C
-18
-18
-58
-30
-00
-00
-ENDCHAR
-STARTCHAR therefore
-ENCODING 8756
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2235
-ENCODING 8757
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-00
-00
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2236
-ENCODING 8758
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2237
-ENCODING 8759
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-66
-66
-00
-00
-00
-66
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2238
-ENCODING 8760
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-18
-00
-7E
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2239
-ENCODING 8761
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-03
-03
-00
-FC
-00
-03
-03
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni223A
-ENCODING 8762
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-66
-66
-00
-7E
-00
-66
-66
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni223B
-ENCODING 8763
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-18
-00
-76
-DC
-00
-30
-30
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR similar
-ENCODING 8764
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-76
-DC
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni223D
-ENCODING 8765
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-DC
-76
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni223E
-ENCODING 8766
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-72
-DB
-DB
-4E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni223F
-ENCODING 8767
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-D8
-DB
-DB
-1B
-0E
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2240
-ENCODING 8768
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-1C
-30
-30
-30
-18
-0C
-0C
-0C
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2241
-ENCODING 8769
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-08
-10
-76
-DC
-10
-20
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2242
-ENCODING 8770
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FE
-00
-76
-DC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2243
-ENCODING 8771
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-DC
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2244
-ENCODING 8772
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-08
-76
-DC
-10
-FE
-20
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR congruent
-ENCODING 8773
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-76
-DC
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2246
-ENCODING 8774
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-76
-DC
-08
-FE
-10
-FE
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2247
-ENCODING 8775
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-08
-76
-DC
-10
-FE
-20
-FE
-40
-40
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR approxequal
-ENCODING 8776
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-76
-DC
-00
-76
-DC
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2249
-ENCODING 8777
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-08
-76
-DC
-10
-76
-DC
-20
-20
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni224A
-ENCODING 8778
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-76
-DC
-00
-76
-DC
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni224B
-ENCODING 8779
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-76
-DC
-00
-76
-DC
-00
-76
-DC
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni224C
-ENCODING 8780
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-DC
-76
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni224D
-ENCODING 8781
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C6
-7C
-00
-7C
-C6
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni224E
-ENCODING 8782
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-66
-00
-00
-66
-18
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni224F
-ENCODING 8783
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-66
-00
-00
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2250
-ENCODING 8784
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-7E
-00
-00
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2251
-ENCODING 8785
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-7E
-00
-00
-7E
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2252
-ENCODING 8786
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-60
-00
-7E
-00
-00
-7E
-00
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2253
-ENCODING 8787
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-06
-00
-7E
-00
-00
-7E
-00
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2254
-ENCODING 8788
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C0
-DF
-00
-00
-DF
-C0
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2255
-ENCODING 8789
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-03
-FB
-00
-00
-FB
-03
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2256
-ENCODING 8790
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-FE
-28
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2257
-ENCODING 8791
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-10
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2258
-ENCODING 8792
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-38
-44
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2259
-ENCODING 8793
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-44
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni225A
-ENCODING 8794
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-44
-28
-10
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni225B
-ENCODING 8795
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-10
-7C
-28
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni225C
-ENCODING 8796
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-10
-28
-44
-7C
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni225D
-ENCODING 8797
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-26
-7C
-B4
-6C
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni225E
-ENCODING 8798
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-68
-54
-54
-00
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni225F
-ENCODING 8799
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-08
-10
-00
-10
-FE
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR notequal
-ENCODING 8800
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-04
-08
-7E
-08
-10
-7E
-10
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR equivalence
-ENCODING 8801
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-00
-00
-FE
-00
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2262
-ENCODING 8802
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-08
-FE
-08
-10
-FE
-10
-20
-FE
-20
-40
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2263
-ENCODING 8803
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-00
-00
-FE
-00
-00
-FE
-00
-00
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR lessequal
-ENCODING 8804
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0E
-38
-E0
-38
-0E
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR greaterequal
-ENCODING 8805
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-E0
-38
-0E
-38
-E0
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2266
-ENCODING 8806
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-0E
-38
-E0
-38
-0E
-00
-FE
-00
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2267
-ENCODING 8807
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-E0
-38
-0E
-38
-E0
-00
-FE
-00
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2268
-ENCODING 8808
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-0E
-38
-E0
-38
-0E
-08
-FE
-10
-FE
-20
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2269
-ENCODING 8809
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-E0
-38
-0E
-38
-E0
-08
-FE
-10
-FE
-20
-00
-00
-00
-ENDCHAR
-STARTCHAR uni226A
-ENCODING 8810
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-1B
-36
-6C
-D8
-6C
-36
-1B
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni226B
-ENCODING 8811
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-D8
-6C
-36
-1B
-36
-6C
-D8
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni226C
-ENCODING 8812
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-66
-18
-3C
-66
-66
-66
-66
-3C
-18
-66
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni226D
-ENCODING 8813
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-CE
-7C
-10
-7C
-E6
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni226E
-ENCODING 8814
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-04
-0E
-38
-E8
-38
-0E
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni226F
-ENCODING 8815
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-E0
-38
-2E
-38
-E0
-40
-40
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2270
-ENCODING 8816
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-04
-0E
-38
-E8
-38
-0E
-10
-FE
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2271
-ENCODING 8817
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-E0
-38
-2E
-38
-E0
-40
-FE
-40
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2272
-ENCODING 8818
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0E
-38
-E0
-38
-0E
-00
-76
-DC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2273
-ENCODING 8819
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-E0
-38
-0E
-38
-E0
-00
-76
-DC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2274
-ENCODING 8820
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-04
-0E
-38
-E8
-38
-0E
-10
-76
-DC
-20
-20
-00
-00
-ENDCHAR
-STARTCHAR uni2275
-ENCODING 8821
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-E0
-38
-2E
-38
-E0
-40
-76
-DC
-80
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2276
-ENCODING 8822
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0E
-38
-E0
-38
-0E
-E0
-38
-0E
-38
-E0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2277
-ENCODING 8823
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-E0
-38
-0E
-38
-E0
-0E
-38
-E0
-38
-0E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2278
-ENCODING 8824
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-0E
-38
-E8
-38
-1E
-F0
-38
-2E
-38
-E0
-20
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2279
-ENCODING 8825
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-E8
-38
-0E
-38
-F0
-1E
-38
-E0
-38
-2E
-20
-00
-00
-00
-ENDCHAR
-STARTCHAR uni227A
-ENCODING 8826
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-02
-06
-1C
-F0
-1C
-06
-02
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni227B
-ENCODING 8827
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-80
-C0
-70
-1E
-70
-C0
-80
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni227C
-ENCODING 8828
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-02
-06
-1C
-F0
-1C
-06
-F2
-1C
-06
-02
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni227D
-ENCODING 8829
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-80
-C0
-70
-1E
-70
-C0
-9E
-70
-C0
-80
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni227E
-ENCODING 8830
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-02
-06
-1C
-F0
-1C
-06
-02
-00
-76
-DC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni227F
-ENCODING 8831
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-80
-C0
-70
-1E
-70
-C0
-80
-00
-76
-DC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2280
-ENCODING 8832
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-06
-0C
-38
-E8
-38
-1C
-16
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2281
-ENCODING 8833
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-D0
-70
-38
-2E
-38
-60
-C0
-40
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR propersubset
-ENCODING 8834
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-7E
-C0
-C0
-C0
-C0
-7E
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR propersuperset
-ENCODING 8835
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FC
-06
-06
-06
-06
-FC
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR notsubset
-ENCODING 8836
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-04
-7E
-C8
-C8
-D0
-D0
-7E
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2285
-ENCODING 8837
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-FC
-16
-16
-26
-26
-FC
-40
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR reflexsubset
-ENCODING 8838
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7E
-C0
-C0
-C0
-C0
-7E
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR reflexsuperset
-ENCODING 8839
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FC
-06
-06
-06
-06
-FC
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2288
-ENCODING 8840
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-7E
-C8
-C8
-D0
-D0
-7E
-20
-FE
-40
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2289
-ENCODING 8841
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-FC
-16
-16
-26
-26
-FC
-40
-FE
-80
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni228A
-ENCODING 8842
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7E
-C0
-C0
-C0
-C0
-7E
-08
-FE
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni228B
-ENCODING 8843
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FC
-06
-06
-06
-06
-FC
-10
-FE
-20
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni228C
-ENCODING 8844
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-82
-92
-A2
-FA
-A2
-92
-44
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni228D
-ENCODING 8845
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-82
-82
-92
-BA
-BA
-92
-44
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni228E
-ENCODING 8846
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-82
-82
-92
-BA
-92
-82
-44
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni228F
-ENCODING 8847
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-C0
-C0
-C0
-C0
-FE
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2290
-ENCODING 8848
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-06
-06
-06
-06
-FE
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2291
-ENCODING 8849
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-C0
-C0
-C0
-C0
-FE
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2292
-ENCODING 8850
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-06
-06
-06
-06
-FE
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2293
-ENCODING 8851
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2294
-ENCODING 8852
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-C6
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR circleplus
-ENCODING 8853
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-54
-92
-FE
-92
-54
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2296
-ENCODING 8854
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-44
-82
-FE
-82
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR circlemultiply
-ENCODING 8855
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-44
-AA
-92
-AA
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2298
-ENCODING 8856
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-44
-8A
-92
-A2
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2299
-ENCODING 8857
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-44
-92
-BA
-92
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni229A
-ENCODING 8858
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-44
-92
-AA
-92
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni229B
-ENCODING 8859
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-54
-D6
-BA
-D6
-54
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni229C
-ENCODING 8860
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-44
-BA
-82
-BA
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni229D
-ENCODING 8861
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-44
-82
-BA
-82
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni229E
-ENCODING 8862
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-92
-92
-FE
-92
-92
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni229F
-ENCODING 8863
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-82
-82
-FE
-82
-82
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A0
-ENCODING 8864
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-C6
-AA
-92
-AA
-C6
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A1
-ENCODING 8865
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-82
-92
-BA
-92
-82
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A2
-ENCODING 8866
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C0
-C0
-C0
-C0
-FF
-C0
-C0
-C0
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A3
-ENCODING 8867
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-03
-03
-03
-03
-FF
-03
-03
-03
-03
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A4
-ENCODING 8868
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-18
-18
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR perpendicular
-ENCODING 8869
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-18
-18
-18
-18
-18
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A6
-ENCODING 8870
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-60
-60
-60
-60
-7E
-60
-60
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A7
-ENCODING 8871
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-60
-60
-60
-7E
-60
-7E
-60
-60
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A8
-ENCODING 8872
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C0
-C0
-C0
-FF
-C0
-FF
-C0
-C0
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22A9
-ENCODING 8873
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-D8
-D8
-D8
-D8
-DF
-D8
-D8
-D8
-D8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22AA
-ENCODING 8874
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-A8
-A8
-A8
-A8
-AF
-A8
-A8
-A8
-A8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22AB
-ENCODING 8875
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-D8
-D8
-D8
-DF
-D8
-DF
-D8
-D8
-D8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22AC
-ENCODING 8876
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C0
-C2
-C4
-C4
-FF
-C8
-C8
-D0
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22AD
-ENCODING 8877
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C0
-C4
-C4
-FF
-C8
-FF
-D0
-D0
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22AE
-ENCODING 8878
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-D8
-D9
-DA
-DA
-DF
-DA
-DA
-DC
-D8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22AF
-ENCODING 8879
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-D8
-D9
-DA
-DF
-DA
-DF
-DA
-DC
-D8
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B0
-ENCODING 8880
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-0C
-06
-1C
-F0
-1C
-06
-0C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B1
-ENCODING 8881
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-60
-C0
-70
-1E
-70
-C0
-60
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B2
-ENCODING 8882
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-06
-1E
-76
-C6
-76
-1E
-06
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B3
-ENCODING 8883
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C0
-F0
-DC
-C6
-DC
-F0
-C0
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B4
-ENCODING 8884
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-1E
-76
-C6
-76
-1E
-06
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B5
-ENCODING 8885
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-F0
-DC
-C6
-DC
-F0
-C0
-00
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B6
-ENCODING 8886
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-42
-BF
-42
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B7
-ENCODING 8887
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-42
-FD
-42
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B8
-ENCODING 8888
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-02
-7D
-02
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22B9
-ENCODING 8889
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-10
-00
-C6
-00
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22BA
-ENCODING 8890
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-18
-18
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22BB
-ENCODING 8891
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C6
-C6
-6C
-6C
-38
-38
-10
-10
-00
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22BC
-ENCODING 8892
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-00
-10
-10
-38
-38
-6C
-6C
-C6
-C6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22BD
-ENCODING 8893
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-00
-C6
-C6
-6C
-6C
-38
-38
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22BE
-ENCODING 8894
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-C0
-C0
-C0
-F0
-C8
-C4
-C4
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22BF
-ENCODING 8895
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-03
-07
-0B
-13
-23
-43
-83
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C0
-ENCODING 8896
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-38
-38
-6C
-6C
-C6
-C6
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C1
-ENCODING 8897
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C6
-C6
-6C
-6C
-38
-38
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C2
-ENCODING 8898
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-38
-6C
-C6
-C6
-C6
-C6
-C6
-C6
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C3
-ENCODING 8899
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C6
-C6
-C6
-C6
-C6
-C6
-6C
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C4
-ENCODING 8900
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-38
-6C
-38
-10
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR dotmath
-ENCODING 8901
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-18
-18
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C6
-ENCODING 8902
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-10
-7C
-38
-28
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C7
-ENCODING 8903
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-92
-44
-28
-92
-28
-44
-92
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C8
-ENCODING 8904
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-82
-C6
-AA
-92
-AA
-C6
-82
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22C9
-ENCODING 8905
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-82
-C4
-A8
-90
-A8
-C4
-82
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22CA
-ENCODING 8906
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-82
-46
-2A
-12
-2A
-46
-82
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22CB
-ENCODING 8907
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-80
-40
-20
-10
-28
-44
-82
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22CC
-ENCODING 8908
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-02
-04
-08
-10
-28
-44
-82
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22CD
-ENCODING 8909
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-DC
-76
-00
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22CE
-ENCODING 8910
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-10
-38
-38
-6C
-6C
-C6
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22CF
-ENCODING 8911
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C6
-6C
-6C
-38
-38
-10
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D0
-ENCODING 8912
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-3E
-60
-CE
-D8
-D8
-CE
-60
-3E
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D1
-ENCODING 8913
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-F8
-0C
-E6
-36
-36
-E6
-0C
-F8
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D2
-ENCODING 8914
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-38
-44
-92
-AA
-AA
-AA
-AA
-AA
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D3
-ENCODING 8915
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-AA
-AA
-AA
-AA
-AA
-92
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D4
-ENCODING 8916
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-10
-38
-54
-92
-92
-92
-92
-92
-92
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D5
-ENCODING 8917
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-7E
-18
-18
-7E
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D6
-ENCODING 8918
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-30
-64
-CE
-64
-30
-18
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D7
-ENCODING 8919
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-30
-18
-4C
-E6
-4C
-18
-30
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D8
-ENCODING 8920
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-15
-2A
-54
-A8
-54
-2A
-15
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22D9
-ENCODING 8921
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-A8
-54
-2A
-15
-2A
-54
-A8
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22DA
-ENCODING 8922
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-0E
-38
-E0
-38
-0E
-00
-FE
-00
-E0
-38
-0E
-38
-E0
-00
-00
-ENDCHAR
-STARTCHAR uni22DB
-ENCODING 8923
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-E0
-38
-0E
-38
-E0
-00
-FE
-00
-0E
-38
-E0
-38
-0E
-00
-00
-ENDCHAR
-STARTCHAR uni22DC
-ENCODING 8924
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-00
-0E
-38
-E0
-38
-0E
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22DD
-ENCODING 8925
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-00
-E0
-38
-0E
-38
-E0
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22DE
-ENCODING 8926
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-02
-06
-1C
-F2
-06
-1C
-F0
-1C
-06
-02
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22DF
-ENCODING 8927
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-80
-C0
-70
-9E
-C0
-70
-1E
-70
-C0
-80
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E0
-ENCODING 8928
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0A
-0E
-1C
-F0
-1C
-16
-F2
-1C
-26
-22
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E1
-ENCODING 8929
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-88
-C8
-70
-1E
-70
-D0
-9E
-70
-E0
-A0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E2
-ENCODING 8930
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-FE
-C8
-C8
-D0
-D0
-FE
-20
-FE
-40
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E3
-ENCODING 8931
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-FE
-16
-16
-26
-26
-FE
-40
-FE
-80
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E4
-ENCODING 8932
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-C0
-C0
-C0
-C0
-FE
-08
-FE
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E5
-ENCODING 8933
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-06
-06
-06
-06
-FE
-10
-FE
-20
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E6
-ENCODING 8934
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0E
-38
-E0
-38
-0E
-10
-76
-DC
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E7
-ENCODING 8935
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-E0
-38
-0E
-38
-E0
-10
-76
-DC
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E8
-ENCODING 8936
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-02
-06
-1C
-F0
-1C
-06
-02
-10
-76
-DC
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22E9
-ENCODING 8937
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-80
-C0
-70
-1E
-70
-C0
-80
-10
-76
-DC
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22EA
-ENCODING 8938
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-0E
-1E
-76
-D6
-76
-1E
-26
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22EB
-ENCODING 8939
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-C8
-F0
-DC
-D6
-DC
-F0
-E0
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22EC
-ENCODING 8940
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-0E
-1E
-76
-D6
-76
-1E
-26
-20
-FE
-40
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22ED
-ENCODING 8941
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-C8
-F0
-DC
-D6
-DC
-F0
-E0
-20
-FE
-40
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22EE
-ENCODING 8942
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-00
-00
-18
-18
-00
-00
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22EF
-ENCODING 8943
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-DB
-DB
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22F0
-ENCODING 8944
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-03
-03
-00
-00
-18
-18
-00
-00
-C0
-C0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni22F1
-ENCODING 8945
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-00
-00
-18
-18
-00
-00
-03
-03
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR emptyset
-ENCODING 8960
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-3D
-66
-C7
-CB
-D3
-E3
-66
-BC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR house
-ENCODING 8962
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-38
-6C
-C6
-C6
-C6
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2308
-ENCODING 8968
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2309
-ENCODING 8969
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni230A
-ENCODING 8970
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni230B
-ENCODING 8971
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR revlogicalnot
-ENCODING 8976
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-FE
-C0
-C0
-C0
-C0
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2318
-ENCODING 8984
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-42
-A5
-7E
-24
-24
-7E
-A5
-42
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR circleplus
-ENCODING 8986
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-38
-38
-54
-8A
-F6
-82
-54
-38
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR H
-ENCODING 8987
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-FE
-FE
-44
-44
-28
-10
-28
-44
-44
-FE
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR integraltp
-ENCODING 8992
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0E
-1B
-1B
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR integralbt
-ENCODING 8993
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-D8
-D8
-D8
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR angleleft
-ENCODING 9001
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0C
-18
-18
-30
-30
-60
-60
-30
-30
-18
-18
-0C
-0C
-00
-00
-ENDCHAR
-STARTCHAR angleright
-ENCODING 9002
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-60
-30
-30
-18
-18
-0C
-0C
-18
-18
-30
-30
-60
-60
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9115
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-03
-06
-0C
-0C
-18
-18
-18
-30
-30
-30
-30
-30
-30
-30
-30
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9116
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9117
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-30
-30
-30
-30
-30
-18
-18
-18
-0C
-0C
-06
-03
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9118
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-C0
-60
-30
-30
-18
-18
-18
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9119
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9120
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-18
-18
-18
-30
-30
-60
-C0
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9121
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-3F
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9122
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9123
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-30
-3F
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9124
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-FC
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9125
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9126
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-0C
-FC
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9127
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-07
-0C
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9128
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-30
-E0
-30
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9129
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-0C
-07
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9130
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9131
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-E0
-30
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9132
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-0C
-07
-0C
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9133
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-30
-E0
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9134
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF100000
-ENCODING 9135
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9136
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-07
-0C
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-30
-E0
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9137
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-E0
-30
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-0C
-07
-ENDCHAR
-STARTCHAR summation
-ENCODING 9138
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-C1
-C0
-60
-60
-60
-60
-30
-30
-30
-30
-18
-18
-18
-ENDCHAR
-STARTCHAR summation
-ENCODING 9139
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-30
-30
-30
-30
-60
-60
-60
-60
-C0
-C1
-FF
-00
-00
-ENDCHAR
-STARTCHAR uni2423
-ENCODING 9140
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-C3
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2423
-ENCODING 9141
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-C3
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2423
-ENCODING 9142
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-C3
-FF
-00
-FF
-C3
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9143
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-D8
-D8
-78
-78
-38
-38
-18
-18
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9144
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9145
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-03
-03
-03
-03
-03
-03
-03
-03
-03
-03
-03
-03
-03
-03
-03
-03
-ENDCHAR
-STARTCHAR SF100000
-ENCODING 9146
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF100000
-ENCODING 9147
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF100000
-ENCODING 9148
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF100000
-ENCODING 9149
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR carriagereturn
-ENCODING 9166
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-07
-05
-05
-05
-05
-25
-79
-C2
-7C
-20
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2409
-ENCODING 9225
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D8
-D8
-F8
-D8
-D8
-0F
-06
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni240A
-ENCODING 9226
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-C0
-C0
-F0
-0F
-0C
-0E
-0C
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni240B
-ENCODING 9227
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D8
-D8
-F8
-70
-20
-0F
-06
-06
-06
-06
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni240C
-ENCODING 9228
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F0
-C0
-E0
-C0
-C0
-0F
-0C
-0E
-0C
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni240D
-ENCODING 9229
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-C0
-C0
-C0
-70
-1E
-1B
-1E
-1B
-1B
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2423
-ENCODING 9251
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2424
-ENCODING 9252
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-98
-D8
-F8
-D8
-D8
-0C
-0C
-0C
-0C
-0F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR question
-ENCODING 9254
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7C
-FE
-C6
-C6
-60
-30
-30
-00
-30
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF100000
-ENCODING 9472
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2501
-ENCODING 9473
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF110000
-ENCODING 9474
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2503
-ENCODING 9475
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2504
-ENCODING 9476
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-6D
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2505
-ENCODING 9477
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-6D
-6D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2506
-ENCODING 9478
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-00
-18
-18
-18
-18
-18
-00
-18
-18
-18
-18
-00
-ENDCHAR
-STARTCHAR uni2507
-ENCODING 9479
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-00
-1C
-1C
-1C
-1C
-1C
-00
-1C
-1C
-1C
-1C
-00
-ENDCHAR
-STARTCHAR uni2508
-ENCODING 9480
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-AA
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2509
-ENCODING 9481
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-AA
-AA
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni250A
-ENCODING 9482
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-00
-18
-18
-18
-00
-18
-18
-18
-00
-18
-18
-18
-00
-ENDCHAR
-STARTCHAR uni250B
-ENCODING 9483
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-00
-1C
-1C
-1C
-00
-1C
-1C
-1C
-00
-1C
-1C
-1C
-00
-ENDCHAR
-STARTCHAR SF010000
-ENCODING 9484
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-1F
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni250D
-ENCODING 9485
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-1F
-1F
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni250E
-ENCODING 9486
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni250F
-ENCODING 9487
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-1F
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR SF030000
-ENCODING 9488
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-F8
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2511
-ENCODING 9489
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-F8
-F8
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2512
-ENCODING 9490
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2513
-ENCODING 9491
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FC
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR SF020000
-ENCODING 9492
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-1F
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2515
-ENCODING 9493
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-1F
-1F
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2516
-ENCODING 9494
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1F
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2517
-ENCODING 9495
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1F
-1F
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF040000
-ENCODING 9496
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-F8
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2519
-ENCODING 9497
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-F8
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni251A
-ENCODING 9498
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FC
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni251B
-ENCODING 9499
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FC
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF080000
-ENCODING 9500
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-1F
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni251D
-ENCODING 9501
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-1F
-1F
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni251E
-ENCODING 9502
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1F
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni251F
-ENCODING 9503
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2520
-ENCODING 9504
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2521
-ENCODING 9505
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1F
-1F
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2522
-ENCODING 9506
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-1F
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2523
-ENCODING 9507
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1F
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR SF090000
-ENCODING 9508
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-F8
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2525
-ENCODING 9509
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-F8
-F8
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2526
-ENCODING 9510
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FC
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2527
-ENCODING 9511
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2528
-ENCODING 9512
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2529
-ENCODING 9513
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FC
-FC
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni252A
-ENCODING 9514
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FC
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni252B
-ENCODING 9515
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FC
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR SF060000
-ENCODING 9516
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni252D
-ENCODING 9517
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-F8
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni252E
-ENCODING 9518
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-1F
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni252F
-ENCODING 9519
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-FF
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2530
-ENCODING 9520
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2531
-ENCODING 9521
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2532
-ENCODING 9522
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2533
-ENCODING 9523
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-FF
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR SF070000
-ENCODING 9524
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2535
-ENCODING 9525
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2536
-ENCODING 9526
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-1F
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2537
-ENCODING 9527
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2538
-ENCODING 9528
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2539
-ENCODING 9529
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni253A
-ENCODING 9530
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-1F
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni253B
-ENCODING 9531
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF050000
-ENCODING 9532
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni253D
-ENCODING 9533
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-F8
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni253E
-ENCODING 9534
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-1F
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni253F
-ENCODING 9535
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-FF
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2540
-ENCODING 9536
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2541
-ENCODING 9537
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2542
-ENCODING 9538
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2543
-ENCODING 9539
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-FC
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2544
-ENCODING 9540
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-1F
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2545
-ENCODING 9541
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2546
-ENCODING 9542
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2547
-ENCODING 9543
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-FF
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2548
-ENCODING 9544
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-FF
-FF
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni2549
-ENCODING 9545
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-FC
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni254A
-ENCODING 9546
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-1F
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni254B
-ENCODING 9547
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-FF
-FF
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni254C
-ENCODING 9548
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-EE
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni254D
-ENCODING 9549
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-EE
-EE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni254E
-ENCODING 9550
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-00
-18
-18
-18
-18
-18
-18
-18
-00
-ENDCHAR
-STARTCHAR uni254F
-ENCODING 9551
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-00
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-00
-ENDCHAR
-STARTCHAR SF430000
-ENCODING 9552
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-FF
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF240000
-ENCODING 9553
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-36
-36
-36
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF510000
-ENCODING 9554
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-1F
-18
-1F
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF520000
-ENCODING 9555
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-3F
-36
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF390000
-ENCODING 9556
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-3F
-30
-37
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF220000
-ENCODING 9557
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-F8
-18
-F8
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF210000
-ENCODING 9558
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FE
-36
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF250000
-ENCODING 9559
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-FE
-06
-F6
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF500000
-ENCODING 9560
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-1F
-18
-1F
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF490000
-ENCODING 9561
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-36
-3F
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF380000
-ENCODING 9562
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-37
-30
-3F
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF280000
-ENCODING 9563
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-F8
-18
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF270000
-ENCODING 9564
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-36
-FE
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF260000
-ENCODING 9565
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-F6
-06
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF360000
-ENCODING 9566
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-1F
-18
-1F
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF370000
-ENCODING 9567
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-36
-37
-36
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF420000
-ENCODING 9568
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-37
-30
-37
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF190000
-ENCODING 9569
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-F8
-18
-F8
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF200000
-ENCODING 9570
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-36
-F6
-36
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF230000
-ENCODING 9571
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-F6
-06
-F6
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF470000
-ENCODING 9572
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-FF
-00
-FF
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF480000
-ENCODING 9573
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-36
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF410000
-ENCODING 9574
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-FF
-00
-F7
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF450000
-ENCODING 9575
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-FF
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF460000
-ENCODING 9576
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-36
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF400000
-ENCODING 9577
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-F7
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR SF540000
-ENCODING 9578
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-FF
-18
-FF
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR SF530000
-ENCODING 9579
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-36
-FF
-36
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR SF440000
-ENCODING 9580
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-36
-36
-36
-36
-36
-36
-F7
-00
-F7
-36
-36
-36
-36
-36
-36
-36
-ENDCHAR
-STARTCHAR uni256D
-ENCODING 9581
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-03
-0E
-0C
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni256E
-ENCODING 9582
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-C0
-70
-30
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni256F
-ENCODING 9583
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-30
-70
-C0
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2570
-ENCODING 9584
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-0C
-0E
-03
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2571
-ENCODING 9585
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-01
-01
-02
-02
-04
-04
-08
-08
-10
-10
-20
-20
-40
-40
-80
-80
-ENDCHAR
-STARTCHAR uni2572
-ENCODING 9586
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-80
-80
-40
-40
-20
-20
-10
-10
-08
-08
-04
-04
-02
-02
-01
-01
-ENDCHAR
-STARTCHAR uni2573
-ENCODING 9587
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-81
-81
-42
-42
-24
-24
-18
-18
-18
-18
-24
-24
-42
-42
-81
-81
-ENDCHAR
-STARTCHAR uni2574
-ENCODING 9588
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-F8
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2575
-ENCODING 9589
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-18
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2576
-ENCODING 9590
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-1F
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2577
-ENCODING 9591
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-18
-18
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR uni2578
-ENCODING 9592
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FC
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2579
-ENCODING 9593
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni257A
-ENCODING 9594
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-1F
-1F
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni257B
-ENCODING 9595
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni257C
-ENCODING 9596
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-1F
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni257D
-ENCODING 9597
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-18
-18
-18
-18
-18
-18
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-ENDCHAR
-STARTCHAR uni257E
-ENCODING 9598
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FF
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni257F
-ENCODING 9599
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-1C
-18
-18
-18
-18
-18
-18
-18
-ENDCHAR
-STARTCHAR upblock
-ENCODING 9600
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2581
-ENCODING 9601
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-FF
-ENDCHAR
-STARTCHAR uni2582
-ENCODING 9602
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR uni2583
-ENCODING 9603
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-FF
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR dnblock
-ENCODING 9604
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR uni2585
-ENCODING 9605
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR uni2586
-ENCODING 9606
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR uni2587
-ENCODING 9607
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR block
-ENCODING 9608
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR uni2589
-ENCODING 9609
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-ENDCHAR
-STARTCHAR uni258A
-ENCODING 9610
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-FC
-ENDCHAR
-STARTCHAR uni258B
-ENCODING 9611
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-F8
-ENDCHAR
-STARTCHAR lfblock
-ENCODING 9612
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-F0
-ENDCHAR
-STARTCHAR uni258D
-ENCODING 9613
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-E0
-ENDCHAR
-STARTCHAR uni258E
-ENCODING 9614
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-C0
-ENDCHAR
-STARTCHAR uni258F
-ENCODING 9615
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-80
-80
-80
-80
-80
-80
-80
-80
-80
-80
-80
-80
-80
-80
-80
-80
-ENDCHAR
-STARTCHAR rtblock
-ENCODING 9616
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-0F
-ENDCHAR
-STARTCHAR ltshade
-ENCODING 9617
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-11
-44
-11
-44
-11
-44
-11
-44
-11
-44
-11
-44
-11
-44
-11
-44
-ENDCHAR
-STARTCHAR shade
-ENCODING 9618
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-55
-AA
-55
-AA
-55
-AA
-55
-AA
-55
-AA
-55
-AA
-55
-AA
-55
-AA
-ENDCHAR
-STARTCHAR dkshade
-ENCODING 9619
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-DD
-77
-DD
-77
-DD
-77
-DD
-77
-DD
-77
-DD
-77
-DD
-77
-DD
-77
-ENDCHAR
-STARTCHAR uni2594
-ENCODING 9620
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FF
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2595
-ENCODING 9621
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-01
-01
-01
-01
-01
-01
-01
-01
-01
-01
-01
-01
-01
-01
-01
-01
-ENDCHAR
-STARTCHAR filledbox
-ENCODING 9632
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR H22073
-ENCODING 9633
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-82
-82
-82
-82
-82
-82
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25A2
-ENCODING 9634
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-7C
-82
-82
-82
-82
-82
-82
-82
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25A3
-ENCODING 9635
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-82
-BA
-BA
-BA
-BA
-BA
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25A4
-ENCODING 9636
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-82
-FE
-82
-FE
-82
-FE
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25A5
-ENCODING 9637
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-AA
-AA
-AA
-AA
-AA
-AA
-AA
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25A6
-ENCODING 9638
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-AA
-FE
-AA
-FE
-AA
-FE
-AA
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25A7
-ENCODING 9639
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-8A
-C6
-A2
-92
-8A
-C6
-A2
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25A8
-ENCODING 9640
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-A2
-C6
-8A
-92
-A2
-C6
-8A
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25A9
-ENCODING 9641
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-AA
-C6
-AA
-92
-AA
-C6
-AA
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR H18543
-ENCODING 9642
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-7C
-7C
-7C
-7C
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR H18551
-ENCODING 9643
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-7C
-44
-44
-44
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR filledrect
-ENCODING 9644
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FE
-FE
-FE
-FE
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25AD
-ENCODING 9645
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-FE
-82
-82
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25AE
-ENCODING 9646
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-FE
-00
-00
-ENDCHAR
-STARTCHAR uni25AF
-ENCODING 9647
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-82
-82
-82
-82
-82
-82
-82
-82
-82
-82
-FE
-00
-00
-ENDCHAR
-STARTCHAR uni25B0
-ENCODING 9648
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-7E
-7E
-7E
-FC
-FC
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25B1
-ENCODING 9649
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-7E
-42
-42
-84
-84
-FC
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR triagup
-ENCODING 9650
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-38
-38
-7C
-7C
-FE
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25B3
-ENCODING 9651
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-28
-28
-44
-44
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25B4
-ENCODING 9652
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-10
-38
-38
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25B5
-ENCODING 9653
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-10
-28
-28
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25B6
-ENCODING 9654
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-80
-C0
-E0
-F0
-F8
-FC
-F8
-F0
-E0
-C0
-80
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25B7
-ENCODING 9655
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-80
-C0
-A0
-90
-88
-84
-88
-90
-A0
-C0
-80
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25B8
-ENCODING 9656
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-40
-70
-78
-70
-40
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25B9
-ENCODING 9657
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-40
-70
-48
-70
-40
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR triagrt
-ENCODING 9658
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-80
-E0
-F8
-FE
-F8
-E0
-80
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25BB
-ENCODING 9659
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-80
-E0
-98
-86
-98
-E0
-80
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR triagdn
-ENCODING 9660
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-FE
-7C
-7C
-38
-38
-10
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25BD
-ENCODING 9661
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-82
-44
-44
-28
-28
-10
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25BE
-ENCODING 9662
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-7C
-38
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25BF
-ENCODING 9663
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-7C
-28
-28
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C0
-ENCODING 9664
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-02
-06
-0E
-1E
-3E
-7E
-3E
-1E
-0E
-06
-02
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C1
-ENCODING 9665
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-02
-06
-0A
-12
-22
-42
-22
-12
-0A
-06
-02
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C2
-ENCODING 9666
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-08
-38
-78
-38
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C3
-ENCODING 9667
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-08
-38
-48
-38
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR triaglf
-ENCODING 9668
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-02
-0E
-3E
-FE
-3E
-0E
-02
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C5
-ENCODING 9669
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-02
-0E
-32
-C2
-32
-0E
-02
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C6
-ENCODING 9670
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-38
-7C
-7C
-FE
-FE
-7C
-7C
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C7
-ENCODING 9671
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-44
-44
-82
-82
-44
-44
-28
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C8
-ENCODING 9672
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-44
-54
-BA
-BA
-54
-44
-28
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25C9
-ENCODING 9673
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-99
-BD
-BD
-BD
-BD
-99
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR lozenge
-ENCODING 9674
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-28
-28
-44
-82
-82
-44
-28
-28
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR circle
-ENCODING 9675
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-81
-81
-81
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25CC
-ENCODING 9676
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-14
-40
-01
-80
-01
-80
-01
-80
-02
-28
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25CD
-ENCODING 9677
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-A5
-A5
-A5
-A5
-A5
-A5
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25CE
-ENCODING 9678
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-99
-A5
-A5
-A5
-A5
-99
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR H18533
-ENCODING 9679
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-7E
-FF
-FF
-FF
-FF
-FF
-FF
-7E
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25D0
-ENCODING 9680
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-72
-F1
-F1
-F1
-F1
-F1
-F1
-72
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25D1
-ENCODING 9681
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-4E
-8F
-8F
-8F
-8F
-8F
-8F
-4E
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25D2
-ENCODING 9682
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-81
-81
-81
-FF
-FF
-FF
-7E
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25D3
-ENCODING 9683
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-7E
-FF
-FF
-FF
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25D4
-ENCODING 9684
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-4E
-8F
-8F
-8F
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25D5
-ENCODING 9685
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-4E
-8F
-8F
-8F
-FF
-FF
-FF
-7E
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25D6
-ENCODING 9686
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-70
-F0
-F0
-F0
-F0
-F0
-F0
-70
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25D7
-ENCODING 9687
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-0E
-0F
-0F
-0F
-0F
-0F
-0F
-0E
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR invbullet
-ENCODING 9688
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FF
-FF
-FF
-FF
-FF
-FF
-E7
-C3
-C3
-E7
-FF
-FF
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR invcircle
-ENCODING 9689
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FF
-FF
-C3
-BD
-7E
-7E
-7E
-7E
-7E
-7E
-BD
-C3
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR uni25DA
-ENCODING 9690
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FF
-FF
-C3
-BD
-7E
-7E
-7E
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25DB
-ENCODING 9691
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-7E
-7E
-7E
-BD
-C3
-FF
-FF
-FF
-FF
-ENDCHAR
-STARTCHAR uni25DC
-ENCODING 9692
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-40
-80
-80
-80
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25DD
-ENCODING 9693
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0C
-02
-01
-01
-01
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25DE
-ENCODING 9694
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-01
-01
-01
-02
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25DF
-ENCODING 9695
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-80
-80
-80
-40
-30
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25E0
-ENCODING 9696
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-81
-81
-81
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25E1
-ENCODING 9697
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25E2
-ENCODING 9698
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-01
-01
-03
-03
-07
-07
-0F
-0F
-1F
-1F
-3F
-3F
-7F
-7F
-FF
-FF
-ENDCHAR
-STARTCHAR uni25E3
-ENCODING 9699
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-80
-80
-C0
-C0
-E0
-E0
-F0
-F0
-F8
-F8
-FC
-FC
-FE
-FE
-FF
-FF
-ENDCHAR
-STARTCHAR uni25E4
-ENCODING 9700
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FF
-FF
-FE
-FE
-FC
-FC
-F8
-F8
-F0
-F0
-E0
-E0
-C0
-C0
-80
-80
-ENDCHAR
-STARTCHAR uni25E5
-ENCODING 9701
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-FF
-FF
-7F
-7F
-3F
-3F
-1F
-1F
-0F
-0F
-07
-07
-03
-03
-01
-01
-ENDCHAR
-STARTCHAR openbullet
-ENCODING 9702
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-3C
-66
-42
-42
-66
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25E7
-ENCODING 9703
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-F1
-F1
-F1
-F1
-F1
-F1
-F1
-F1
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25E8
-ENCODING 9704
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-8F
-8F
-8F
-8F
-8F
-8F
-8F
-8F
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25E9
-ENCODING 9705
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-FF
-FD
-F9
-F1
-F1
-E1
-C1
-81
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25EA
-ENCODING 9706
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-81
-83
-87
-8F
-8F
-9F
-BF
-FF
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25EB
-ENCODING 9707
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FF
-99
-99
-99
-99
-99
-99
-99
-99
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25EC
-ENCODING 9708
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-28
-28
-44
-44
-92
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25ED
-ENCODING 9709
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-38
-38
-74
-74
-F2
-F2
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25EE
-ENCODING 9710
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-38
-38
-5C
-5C
-9E
-9E
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25EF
-ENCODING 9711
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-81
-81
-81
-81
-81
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25F0
-ENCODING 9712
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-92
-92
-92
-F2
-82
-82
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25F1
-ENCODING 9713
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-82
-82
-82
-F2
-92
-92
-92
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25F2
-ENCODING 9714
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-82
-82
-82
-9E
-92
-92
-92
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25F3
-ENCODING 9715
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-FE
-92
-92
-92
-9E
-82
-82
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25F4
-ENCODING 9716
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-4A
-89
-89
-89
-F9
-81
-81
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25F5
-ENCODING 9717
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-81
-81
-F9
-89
-89
-89
-4A
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25F6
-ENCODING 9718
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-81
-81
-9F
-91
-91
-91
-52
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni25F7
-ENCODING 9719
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-52
-91
-91
-91
-9F
-81
-81
-42
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2600
-ENCODING 9728
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-54
-38
-FE
-38
-54
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2602
-ENCODING 9729
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-30
-7C
-FE
-FF
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2601
-ENCODING 9730
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-38
-7C
-FE
-10
-10
-10
-10
-14
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2605
-ENCODING 9733
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-38
-FE
-7C
-38
-6C
-44
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2606
-ENCODING 9734
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-28
-EE
-44
-54
-6C
-44
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2607
-ENCODING 9735
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-18
-30
-60
-C0
-60
-34
-1C
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2608
-ENCODING 9736
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-C6
-CC
-D8
-F0
-D8
-CD
-C7
-CF
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2609
-ENCODING 9737
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-38
-44
-82
-92
-82
-44
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni260A
-ENCODING 9738
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-24
-42
-42
-42
-A5
-A5
-42
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni260B
-ENCODING 9739
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-42
-A5
-A5
-42
-42
-42
-24
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni260C
-ENCODING 9740
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-06
-0C
-78
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni260D
-ENCODING 9741
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-36
-36
-1C
-18
-30
-70
-D8
-D8
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2610
-ENCODING 9744
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-82
-82
-82
-82
-82
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2611
-ENCODING 9745
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-82
-86
-8A
-BA
-92
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2612
-ENCODING 9746
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-FE
-82
-EE
-BA
-BA
-EE
-82
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2613
-ENCODING 9747
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-82
-C6
-6C
-7C
-38
-7C
-6C
-C6
-82
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2620
-ENCODING 9760
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-7C
-82
-AA
-82
-44
-7C
-44
-38
-00
-44
-C6
-38
-C6
-44
-00
-ENDCHAR
-STARTCHAR uni2622
-ENCODING 9762
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-38
-44
-EE
-FE
-92
-BA
-7C
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2626
-ENCODING 9766
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-7E
-18
-18
-FF
-18
-1E
-78
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2628
-ENCODING 9768
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-7E
-18
-18
-FF
-18
-18
-18
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2629
-ENCODING 9769
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-38
-10
-10
-92
-FE
-92
-10
-10
-38
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni262A
-ENCODING 9770
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-72
-E0
-C4
-DF
-CE
-CA
-E0
-72
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni262B
-ENCODING 9771
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-54
-28
-54
-AA
-AA
-AA
-AA
-54
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni262E
-ENCODING 9774
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-5A
-99
-99
-99
-BD
-FF
-DB
-5A
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni262F
-ENCODING 9775
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-42
-81
-85
-B1
-F9
-FF
-DF
-7E
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2630
-ENCODING 9776
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-FE
-00
-00
-FE
-FE
-00
-00
-FE
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2631
-ENCODING 9777
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-EE
-EE
-00
-00
-FE
-FE
-00
-00
-FE
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2632
-ENCODING 9778
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-FE
-00
-00
-EE
-EE
-00
-00
-FE
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2633
-ENCODING 9779
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-EE
-EE
-00
-00
-EE
-EE
-00
-00
-FE
-FE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2634
-ENCODING 9780
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-FE
-00
-00
-FE
-FE
-00
-00
-EE
-EE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2635
-ENCODING 9781
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-EE
-EE
-00
-00
-FE
-FE
-00
-00
-EE
-EE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2636
-ENCODING 9782
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-FE
-FE
-00
-00
-EE
-EE
-00
-00
-EE
-EE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2637
-ENCODING 9783
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-EE
-EE
-00
-00
-EE
-EE
-00
-00
-EE
-EE
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2639
-ENCODING 9785
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-81
-A5
-81
-81
-81
-99
-A5
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR smileface
-ENCODING 9786
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-81
-A5
-81
-81
-A5
-99
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR invsmileface
-ENCODING 9787
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-FF
-DB
-FF
-FF
-DB
-E7
-FF
-FF
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR sun
-ENCODING 9788
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-54
-28
-C6
-28
-54
-10
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni263D
-ENCODING 9789
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-78
-14
-0A
-0A
-0A
-0A
-0A
-0A
-14
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni263E
-ENCODING 9790
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-28
-50
-50
-50
-50
-50
-50
-28
-1E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni263F
-ENCODING 9791
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-66
-66
-3C
-66
-66
-66
-66
-3C
-18
-7E
-18
-18
-00
-00
-00
-ENDCHAR
-STARTCHAR female
-ENCODING 9792
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-66
-3C
-18
-7E
-18
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2641
-ENCODING 9793
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-7E
-18
-3C
-66
-66
-66
-66
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR male
-ENCODING 9794
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-06
-0E
-1A
-78
-CC
-CC
-CC
-CC
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2643
-ENCODING 9795
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-03
-03
-7B
-CF
-CF
-CF
-0F
-1B
-33
-FF
-03
-03
-03
-00
-00
-ENDCHAR
-STARTCHAR uni2644
-ENCODING 9796
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-60
-F0
-60
-6E
-73
-63
-63
-66
-66
-63
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2645
-ENCODING 9797
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-D6
-54
-54
-7C
-54
-54
-D6
-38
-44
-44
-38
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2646
-ENCODING 9798
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-3C
-DB
-DB
-DB
-DB
-7E
-3C
-18
-3C
-18
-18
-00
-00
-ENDCHAR
-STARTCHAR uni2647
-ENCODING 9799
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-F8
-CC
-CC
-CC
-CC
-F8
-C0
-C0
-C0
-C0
-FE
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2648
-ENCODING 9800
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-42
-A5
-A5
-3C
-3C
-18
-18
-18
-18
-18
-18
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2649
-ENCODING 9801
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-C3
-66
-66
-66
-66
-3C
-66
-66
-66
-66
-3C
-00
-00
-ENDCHAR
-STARTCHAR uni264A
-ENCODING 9802
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C3
-7E
-66
-66
-66
-66
-66
-66
-7E
-C3
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni264B
-ENCODING 9803
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7E
-DB
-D8
-70
-00
-00
-0E
-1B
-DB
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni264C
-ENCODING 9804
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1E
-33
-33
-33
-33
-1B
-7B
-DB
-DB
-73
-03
-01
-00
-00
-ENDCHAR
-STARTCHAR uni264D
-ENCODING 9805
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-94
-7C
-55
-57
-55
-55
-55
-55
-55
-55
-06
-0B
-00
-00
-ENDCHAR
-STARTCHAR uni264E
-ENCODING 9806
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-66
-66
-66
-66
-24
-E7
-00
-FF
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni264F
-ENCODING 9807
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-94
-7C
-54
-54
-54
-54
-54
-54
-54
-54
-04
-03
-00
-00
-ENDCHAR
-STARTCHAR uni2650
-ENCODING 9808
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1F
-07
-8F
-DB
-73
-70
-D8
-88
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2651
-ENCODING 9809
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-90
-50
-70
-68
-48
-48
-4E
-49
-09
-0E
-10
-20
-00
-00
-ENDCHAR
-STARTCHAR uni2652
-ENCODING 9810
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-2A
-7E
-AA
-00
-00
-2A
-7E
-AA
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2653
-ENCODING 9811
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C3
-66
-66
-66
-66
-FF
-66
-66
-66
-66
-C3
-00
-00
-00
-ENDCHAR
-STARTCHAR spade
-ENCODING 9824
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-3C
-7E
-FF
-FF
-7E
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2661
-ENCODING 9825
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-6C
-92
-82
-82
-82
-44
-28
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2662
-ENCODING 9826
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-28
-44
-82
-44
-28
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR club
-ENCODING 9827
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-3C
-3C
-E7
-E7
-E7
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2664
-ENCODING 9828
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-24
-42
-81
-81
-66
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR heart
-ENCODING 9829
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-6C
-FE
-FE
-FE
-FE
-7C
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR diamond
-ENCODING 9830
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-38
-7C
-FE
-7C
-38
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2667
-ENCODING 9831
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-18
-24
-3C
-E7
-A5
-E7
-18
-18
-3C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni2669
-ENCODING 9833
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-18
-18
-18
-18
-18
-18
-18
-38
-78
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR musicalnote
-ENCODING 9834
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-30
-3C
-3E
-32
-30
-30
-30
-70
-F0
-E0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR musicalnotedbl
-ENCODING 9835
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-7F
-6F
-63
-63
-63
-63
-E3
-E7
-C7
-06
-00
-00
-00
-ENDCHAR
-STARTCHAR uni266C
-ENCODING 9836
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-7F
-63
-7F
-63
-63
-63
-63
-63
-E7
-E7
-C6
-00
-00
-00
-ENDCHAR
-STARTCHAR uni266D
-ENCODING 9837
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-C0
-C0
-C0
-C0
-CC
-DE
-E6
-C4
-D8
-E0
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uni266E
-ENCODING 9838
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-40
-40
-44
-5C
-74
-44
-44
-5C
-74
-44
-04
-04
-00
-00
-ENDCHAR
-STARTCHAR uni266F
-ENCODING 9839
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-04
-46
-5C
-74
-C4
-46
-5C
-74
-C4
-40
-40
-00
-00
-ENDCHAR
-STARTCHAR ff
-ENCODING 64256
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3B
-66
-66
-66
-FF
-66
-66
-66
-66
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR fi
-ENCODING 64257
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3C
-6E
-66
-60
-FE
-66
-66
-66
-66
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR fl
-ENCODING 64258
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-3E
-6E
-66
-66
-FE
-66
-66
-66
-66
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ffi
-ENCODING 64259
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6E
-DB
-DB
-D8
-FF
-DB
-DB
-DB
-DB
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR ffl
-ENCODING 64260
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-6F
-DB
-DB
-DB
-FF
-DB
-DB
-DB
-DB
-FF
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB05
-ENCODING 64261
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-38
-6C
-6C
-6F
-6C
-6C
-6C
-6C
-6D
-F6
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB50
-ENCODING 64336
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-06
-29
-5E
-00
-04
-04
-04
-04
-04
-04
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB51
-ENCODING 64337
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-06
-29
-5E
-00
-04
-04
-04
-04
-04
-03
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB52
-ENCODING 64338
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-81
-81
-7E
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB53
-ENCODING 64339
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-80
-81
-7E
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB54
-ENCODING 64340
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-04
-04
-F8
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB55
-ENCODING 64341
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-08
-F7
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB56
-ENCODING 64342
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-81
-81
-7E
-00
-14
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB57
-ENCODING 64343
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-80
-81
-7E
-00
-14
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB58
-ENCODING 64344
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-04
-04
-F8
-00
-14
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB59
-ENCODING 64345
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-08
-F7
-00
-14
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB5A
-ENCODING 64346
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-81
-81
-7E
-00
-14
-00
-14
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB5B
-ENCODING 64347
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-80
-81
-7E
-00
-14
-00
-14
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB5C
-ENCODING 64348
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-04
-04
-F8
-00
-14
-00
-14
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB5D
-ENCODING 64349
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-08
-F7
-00
-14
-00
-14
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB5E
-ENCODING 64350
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-08
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB5F
-ENCODING 64351
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-08
-00
-40
-80
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB60
-ENCODING 64352
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-08
-00
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB61
-ENCODING 64353
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-08
-00
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB62
-ENCODING 64354
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-14
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB63
-ENCODING 64355
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-14
-00
-40
-80
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB64
-ENCODING 64356
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-14
-00
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB65
-ENCODING 64357
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-14
-00
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB66
-ENCODING 64358
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB67
-ENCODING 64359
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-40
-80
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB68
-ENCODING 64360
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB69
-ENCODING 64361
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB6A
-ENCODING 64362
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-00
-0A
-00
-06
-49
-85
-83
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB6B
-ENCODING 64363
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-00
-0A
-00
-06
-49
-89
-86
-7D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB6C
-ENCODING 64364
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-0C
-12
-0A
-06
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB6D
-ENCODING 64365
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-0C
-12
-12
-0C
-F3
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB6E
-ENCODING 64366
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0A
-00
-0A
-00
-06
-49
-85
-83
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB6F
-ENCODING 64367
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0A
-00
-0A
-00
-06
-49
-89
-86
-7D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB70
-ENCODING 64368
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-14
-00
-14
-00
-0C
-12
-0A
-06
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB71
-ENCODING 64369
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-14
-00
-14
-00
-0C
-12
-12
-0C
-F3
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB72
-ENCODING 64370
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-88
-80
-88
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB73
-ENCODING 64371
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-41
-88
-80
-88
-40
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFB74
-ENCODING 64372
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-47
-18
-E0
-00
-04
-00
-04
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB75
-ENCODING 64373
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-C1
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB76
-ENCODING 64374
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-80
-94
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB77
-ENCODING 64375
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-41
-80
-94
-80
-40
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFB78
-ENCODING 64376
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-47
-18
-E0
-00
-00
-0A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB79
-ENCODING 64377
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-C1
-00
-00
-14
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB7A
-ENCODING 64378
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-94
-80
-88
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB7B
-ENCODING 64379
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-41
-94
-80
-88
-40
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFB7C
-ENCODING 64380
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-47
-18
-E0
-00
-0A
-00
-04
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB7D
-ENCODING 64381
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-C1
-00
-14
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB7E
-ENCODING 64382
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-94
-80
-94
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB7F
-ENCODING 64383
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-41
-94
-80
-94
-40
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFB80
-ENCODING 64384
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-47
-18
-E0
-00
-0A
-00
-0A
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB81
-ENCODING 64385
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-C1
-00
-14
-00
-14
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB82
-ENCODING 64386
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-04
-02
-42
-3C
-00
-00
-14
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB83
-ENCODING 64387
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-08
-04
-46
-39
-00
-00
-14
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB84
-ENCODING 64388
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-28
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB85
-ENCODING 64389
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-28
-00
-08
-08
-04
-46
-39
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB86
-ENCODING 64390
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-00
-28
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB87
-ENCODING 64391
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-00
-28
-00
-08
-08
-04
-46
-39
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB88
-ENCODING 64392
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-20
-38
-28
-70
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB89
-ENCODING 64393
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-20
-38
-28
-70
-08
-08
-04
-46
-39
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB8A
-ENCODING 64394
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-00
-14
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB8B
-ENCODING 64395
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-14
-00
-00
-04
-07
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB8C
-ENCODING 64396
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB8D
-ENCODING 64397
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-00
-00
-04
-07
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB8E
-ENCODING 64398
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-01
-02
-04
-08
-44
-82
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB8F
-ENCODING 64399
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-01
-02
-04
-08
-48
-84
-82
-7D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB90
-ENCODING 64400
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-18
-20
-10
-08
-08
-F0
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB91
-ENCODING 64401
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-18
-20
-20
-10
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB92
-ENCODING 64402
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-09
-12
-04
-08
-44
-82
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB93
-ENCODING 64403
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-09
-12
-04
-08
-48
-84
-82
-7D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB94
-ENCODING 64404
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-30
-46
-18
-20
-10
-08
-08
-F0
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB95
-ENCODING 64405
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-30
-46
-18
-20
-20
-10
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB96
-ENCODING 64406
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-09
-12
-04
-08
-44
-82
-82
-7C
-00
-10
-00
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB97
-ENCODING 64407
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-09
-12
-04
-08
-48
-84
-82
-7D
-00
-10
-00
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB98
-ENCODING 64408
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-30
-46
-18
-20
-10
-08
-08
-F0
-00
-10
-00
-10
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB99
-ENCODING 64409
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-30
-46
-18
-20
-20
-10
-08
-F7
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB9A
-ENCODING 64410
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-A4
-09
-12
-04
-08
-44
-82
-82
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB9B
-ENCODING 64411
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-A4
-09
-12
-04
-08
-48
-84
-82
-7D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB9C
-ENCODING 64412
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-A2
-0C
-13
-0C
-10
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB9D
-ENCODING 64413
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-A2
-0C
-13
-0C
-10
-10
-08
-04
-FB
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB9E
-ENCODING 64414
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-41
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFB9F
-ENCODING 64415
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-01
-41
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA0
-ENCODING 64416
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-41
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA1
-ENCODING 64417
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-00
-00
-01
-41
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA2
-ENCODING 64418
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA3
-ENCODING 64419
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-1C
-14
-38
-00
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA4
-ENCODING 64420
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-38
-40
-38
-40
-18
-24
-22
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA5
-ENCODING 64421
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-70
-80
-70
-80
-10
-68
-88
-74
-03
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA6
-ENCODING 64422
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-24
-22
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA7
-ENCODING 64423
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-0C
-13
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA8
-ENCODING 64424
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-10
-F0
-10
-14
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBA9
-ENCODING 64425
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-10
-F7
-08
-08
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBAA
-ENCODING 64426
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-38
-4C
-52
-32
-3D
-40
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBAB
-ENCODING 64427
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-38
-4C
-52
-32
-3D
-40
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBAC
-ENCODING 64428
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-38
-4C
-52
-32
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBAD
-ENCODING 64429
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-38
-4C
-52
-32
-FD
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBAE
-ENCODING 64430
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-14
-60
-80
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBAF
-ENCODING 64431
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-07
-18
-20
-3F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBB0
-ENCODING 64432
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-70
-80
-70
-80
-08
-14
-60
-80
-FE
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBB1
-ENCODING 64433
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-1C
-20
-1C
-20
-00
-00
-07
-18
-20
-3F
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBD3
-ENCODING 64467
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-00
-29
-01
-19
-21
-19
-A1
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBD4
-ENCODING 64468
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-00
-2A
-02
-32
-42
-32
-C6
-79
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBD5
-ENCODING 64469
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-40
-00
-A3
-0C
-10
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBD6
-ENCODING 64470
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-40
-00
-A3
-0C
-10
-10
-08
-04
-FB
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBD7
-ENCODING 64471
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-28
-18
-10
-20
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBD8
-ENCODING 64472
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-28
-18
-10
-20
-00
-0C
-12
-0F
-02
-04
-18
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBD9
-ENCODING 64473
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-08
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBDA
-ENCODING 64474
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-08
-00
-00
-00
-0C
-12
-0F
-02
-04
-18
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBDB
-ENCODING 64475
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-08
-08
-08
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBDC
-ENCODING 64476
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-08
-08
-08
-00
-00
-0C
-12
-0F
-02
-04
-18
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBDD
-ENCODING 64477
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-23
-54
-33
-24
-40
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBDE
-ENCODING 64478
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBDF
-ENCODING 64479
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-14
-00
-0C
-12
-0F
-02
-04
-18
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBE0
-ENCODING 64480
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-12
-0E
-02
-3C
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBE1
-ENCODING 64481
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-08
-00
-00
-00
-0C
-12
-0F
-02
-3C
-18
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBE2
-ENCODING 64482
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-14
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBE3
-ENCODING 64483
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-14
-00
-00
-00
-0C
-12
-0F
-02
-04
-18
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBE4
-ENCODING 64484
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-81
-7E
-00
-10
-00
-10
-ENDCHAR
-STARTCHAR uniFBE5
-ENCODING 64485
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-07
-88
-87
-81
-7E
-10
-00
-10
-ENDCHAR
-STARTCHAR uniFBE6
-ENCODING 64486
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-04
-04
-F8
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBE7
-ENCODING 64487
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-08
-F7
-00
-08
-00
-08
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBE8
-ENCODING 64488
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBE9
-ENCODING 64489
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBFC
-ENCODING 64508
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-82
-7C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBFD
-ENCODING 64509
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-07
-88
-87
-81
-7E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBFE
-ENCODING 64510
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-04
-04
-F8
-00
-00
-14
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFBFF
-ENCODING 64511
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-08
-F7
-00
-00
-14
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC5B
-ENCODING 64603
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-20
-20
-20
-20
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC5C
-ENCODING 64604
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-10
-10
-10
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC5D
-ENCODING 64605
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-10
-10
-10
-00
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC5E
-ENCODING 64606
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-24
-98
-60
-C2
-12
-92
-9C
-60
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC5F
-ENCODING 64607
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-02
-92
-9C
-60
-0E
-70
-0E
-70
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC60
-ENCODING 64608
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-60
-04
-54
-58
-20
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC61
-ENCODING 64609
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-28
-10
-60
-04
-54
-58
-20
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC62
-ENCODING 64610
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-04
-54
-58
-20
-0C
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC63
-ENCODING 64611
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-10
-04
-54
-58
-20
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFC90
-ENCODING 64656
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-10
-10
-10
-00
-00
-00
-00
-07
-88
-87
-81
-7E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFCF2
-ENCODING 64754
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0E
-F0
-02
-92
-9C
-60
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFCF3
-ENCODING 64755
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-24
-18
-60
-02
-92
-9C
-60
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFCF4
-ENCODING 64756
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-02
-12
-9C
-60
-0E
-70
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFD3C
-ENCODING 64828
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-10
-28
-50
-28
-08
-08
-08
-08
-07
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFD3D
-ENCODING 64829
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-14
-28
-14
-04
-04
-04
-04
-04
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFD3E
-ENCODING 64830
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-08
-10
-54
-38
-54
-10
-08
-04
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFD3F
-ENCODING 64831
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-10
-08
-2A
-1C
-2A
-08
-10
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFDF2
-ENCODING 65010
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-2A
-14
-00
-21
-69
-A9
-69
-16
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE50
-ENCODING 65104
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-08
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE51
-ENCODING 65105
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-10
-08
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE52
-ENCODING 65106
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-10
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE54
-ENCODING 65108
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-00
-00
-08
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE55
-ENCODING 65109
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-10
-00
-00
-10
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE56
-ENCODING 65110
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-24
-08
-10
-00
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE57
-ENCODING 65111
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-10
-10
-10
-00
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE58
-ENCODING 65112
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE59
-ENCODING 65113
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-10
-10
-10
-10
-10
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE5A
-ENCODING 65114
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-08
-08
-08
-08
-08
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE5B
-ENCODING 65115
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-10
-10
-20
-10
-10
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE5C
-ENCODING 65116
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-08
-08
-04
-08
-08
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE5D
-ENCODING 65117
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-10
-10
-10
-10
-10
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE5E
-ENCODING 65118
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-18
-08
-08
-08
-08
-08
-18
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE5F
-ENCODING 65119
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-28
-7C
-28
-7C
-28
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE60
-ENCODING 65120
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-28
-28
-10
-2A
-24
-1A
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE61
-ENCODING 65121
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-10
-10
-7C
-38
-38
-44
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE62
-ENCODING 65122
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-10
-10
-7C
-10
-10
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE63
-ENCODING 65123
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE64
-ENCODING 65124
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-10
-20
-10
-08
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE65
-ENCODING 65125
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-20
-10
-08
-10
-20
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE66
-ENCODING 65126
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-3C
-00
-3C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE68
-ENCODING 65128
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-20
-10
-10
-08
-08
-04
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE69
-ENCODING 65129
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-10
-38
-54
-30
-18
-54
-38
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE6A
-ENCODING 65130
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-24
-08
-08
-10
-10
-24
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE6B
-ENCODING 65131
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-44
-54
-58
-40
-38
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE70
-ENCODING 65136
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-30
-0C
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE71
-ENCODING 65137
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-06
-18
-60
-06
-18
-60
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE72
-ENCODING 65138
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-12
-CA
-2C
-70
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE74
-ENCODING 65140
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-0C
-30
-0C
-30
-00
-00
-ENDCHAR
-STARTCHAR uniFE76
-ENCODING 65142
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-30
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE77
-ENCODING 65143
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-06
-18
-60
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE78
-ENCODING 65144
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-08
-14
-0C
-08
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE79
-ENCODING 65145
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-24
-14
-18
-60
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE7A
-ENCODING 65146
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-0C
-30
-00
-00
-ENDCHAR
-STARTCHAR uniFE7B
-ENCODING 65147
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-FF
-00
-00
-06
-18
-60
-00
-00
-ENDCHAR
-STARTCHAR uniFE7C
-ENCODING 65148
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0A
-2A
-2C
-10
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE7D
-ENCODING 65149
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-02
-12
-92
-9C
-60
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE7E
-ENCODING 65150
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-24
-18
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE7F
-ENCODING 65151
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-24
-24
-18
-00
-00
-00
-00
-FF
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE80
-ENCODING 65152
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-24
-20
-1E
-20
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE81
-ENCODING 65153
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-02
-3C
-40
-10
-10
-10
-10
-10
-10
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE82
-ENCODING 65154
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-01
-3E
-40
-08
-08
-08
-08
-08
-07
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE83
-ENCODING 65155
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-18
-20
-1C
-20
-08
-08
-08
-08
-08
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE84
-ENCODING 65156
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-0C
-10
-0E
-10
-04
-04
-04
-04
-03
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE85
-ENCODING 65157
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-1C
-20
-1C
-20
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE86
-ENCODING 65158
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-1C
-20
-1C
-20
-00
-0C
-12
-0F
-02
-04
-18
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE87
-ENCODING 65159
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-04
-04
-04
-04
-04
-04
-00
-0C
-10
-0E
-10
-00
-00
-ENDCHAR
-STARTCHAR uniFE88
-ENCODING 65160
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-04
-04
-04
-04
-04
-03
-00
-0C
-10
-0E
-10
-00
-00
-ENDCHAR
-STARTCHAR uniFE89
-ENCODING 65161
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-40
-38
-40
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE8A
-ENCODING 65162
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-30
-40
-38
-40
-00
-00
-00
-07
-88
-87
-81
-7E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE8B
-ENCODING 65163
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-1C
-20
-1C
-20
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE8C
-ENCODING 65164
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-1C
-20
-1C
-20
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE8D
-ENCODING 65165
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-08
-08
-08
-08
-08
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE8E
-ENCODING 65166
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-08
-08
-08
-08
-07
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE8F
-ENCODING 65167
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-81
-81
-7E
-00
-00
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE90
-ENCODING 65168
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-40
-80
-81
-7E
-00
-00
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE91
-ENCODING 65169
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-04
-04
-F8
-00
-00
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE92
-ENCODING 65170
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-08
-F7
-00
-00
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE93
-ENCODING 65171
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-28
-00
-00
-18
-24
-22
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE94
-ENCODING 65172
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-50
-00
-10
-10
-68
-88
-74
-03
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE95
-ENCODING 65173
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-14
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE96
-ENCODING 65174
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-14
-00
-40
-80
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE97
-ENCODING 65175
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-14
-00
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE98
-ENCODING 65176
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-14
-00
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE99
-ENCODING 65177
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-40
-81
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE9A
-ENCODING 65178
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-40
-80
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE9B
-ENCODING 65179
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE9C
-ENCODING 65180
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE9D
-ENCODING 65181
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-80
-88
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFE9E
-ENCODING 65182
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-41
-80
-88
-80
-40
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFE9F
-ENCODING 65183
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-47
-18
-E0
-00
-00
-10
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEA0
-ENCODING 65184
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-C1
-00
-00
-08
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEA1
-ENCODING 65185
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-8F
-30
-40
-80
-80
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEA2
-ENCODING 65186
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-41
-80
-80
-80
-40
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFEA3
-ENCODING 65187
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-38
-47
-18
-E0
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEA4
-ENCODING 65188
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-70
-8F
-32
-C1
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEA5
-ENCODING 65189
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-20
-00
-00
-70
-8F
-30
-40
-80
-80
-80
-41
-3E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEA6
-ENCODING 65190
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-00
-00
-70
-8F
-32
-41
-80
-80
-80
-40
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFEA7
-ENCODING 65191
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-00
-38
-47
-18
-E0
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEA8
-ENCODING 65192
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-00
-00
-70
-8F
-32
-C1
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEA9
-ENCODING 65193
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEAA
-ENCODING 65194
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-08
-04
-46
-39
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEAB
-ENCODING 65195
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-00
-08
-04
-02
-42
-3C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEAC
-ENCODING 65196
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-00
-08
-08
-04
-46
-39
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEAD
-ENCODING 65197
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEAE
-ENCODING 65198
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-04
-07
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEAF
-ENCODING 65199
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-00
-04
-02
-02
-04
-18
-60
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB0
-ENCODING 65200
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-00
-00
-04
-07
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB1
-ENCODING 65201
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-01
-15
-88
-84
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB2
-ENCODING 65202
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-01
-15
-88
-84
-84
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB3
-ENCODING 65203
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-01
-15
-EA
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB4
-ENCODING 65204
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-2A
-D5
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB5
-ENCODING 65205
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-01
-15
-88
-84
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB6
-ENCODING 65206
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-14
-00
-01
-15
-88
-84
-84
-78
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB7
-ENCODING 65207
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-04
-00
-0A
-00
-00
-01
-15
-EA
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB8
-ENCODING 65208
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-14
-00
-00
-00
-2A
-D5
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEB9
-ENCODING 65209
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-06
-09
-31
-9E
-88
-88
-70
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEBA
-ENCODING 65210
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-06
-09
-31
-9E
-88
-88
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEBB
-ENCODING 65211
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-06
-29
-31
-DE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEBC
-ENCODING 65212
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-06
-29
-31
-DE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEBD
-ENCODING 65213
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-06
-09
-31
-9E
-88
-88
-70
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEBE
-ENCODING 65214
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-04
-00
-06
-09
-31
-9E
-88
-88
-70
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEBF
-ENCODING 65215
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-00
-06
-29
-31
-DE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC0
-ENCODING 65216
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-00
-06
-29
-31
-DE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC1
-ENCODING 65217
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-20
-20
-2C
-32
-A2
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC2
-ENCODING 65218
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-20
-20
-2C
-32
-A2
-7D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC3
-ENCODING 65219
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-20
-20
-2C
-32
-22
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC4
-ENCODING 65220
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-20
-20
-20
-2C
-32
-22
-FD
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC5
-ENCODING 65221
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-20
-20
-2C
-32
-A2
-7C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC6
-ENCODING 65222
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-20
-20
-2C
-32
-A2
-7D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC7
-ENCODING 65223
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-20
-20
-2C
-32
-22
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC8
-ENCODING 65224
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-24
-20
-20
-2C
-32
-22
-FD
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEC9
-ENCODING 65225
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-70
-80
-8C
-70
-40
-80
-80
-80
-41
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFECA
-ENCODING 65226
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-1E
-22
-1C
-22
-41
-80
-80
-80
-41
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFECB
-ENCODING 65227
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0E
-10
-10
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFECC
-ENCODING 65228
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-1E
-22
-1C
-E3
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFECD
-ENCODING 65229
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-40
-00
-00
-70
-80
-8C
-70
-40
-80
-80
-80
-41
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFECE
-ENCODING 65230
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-08
-00
-00
-1E
-22
-1C
-22
-41
-80
-80
-80
-41
-3E
-00
-00
-ENDCHAR
-STARTCHAR uniFECF
-ENCODING 65231
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-10
-00
-00
-0E
-10
-10
-FE
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED0
-ENCODING 65232
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-00
-1E
-22
-1C
-E3
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED1
-ENCODING 65233
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-06
-49
-85
-83
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED2
-ENCODING 65234
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-04
-00
-06
-49
-89
-86
-7D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED3
-ENCODING 65235
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-0C
-12
-0A
-06
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED4
-ENCODING 65236
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-0C
-12
-12
-0C
-F3
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED5
-ENCODING 65237
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0A
-00
-06
-09
-09
-47
-81
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED6
-ENCODING 65238
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-0A
-00
-00
-06
-09
-49
-87
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED7
-ENCODING 65239
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-00
-0C
-12
-0A
-06
-FC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED8
-ENCODING 65240
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-14
-00
-00
-0C
-12
-12
-0C
-F3
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFED9
-ENCODING 65241
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-19
-21
-19
-21
-01
-81
-7E
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEDA
-ENCODING 65242
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-32
-42
-32
-42
-02
-86
-79
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEDB
-ENCODING 65243
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-18
-20
-10
-08
-08
-F0
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEDC
-ENCODING 65244
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-06
-18
-20
-20
-10
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEDD
-ENCODING 65245
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-02
-02
-02
-02
-02
-42
-82
-82
-84
-78
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEDE
-ENCODING 65246
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-02
-02
-02
-02
-02
-03
-42
-82
-82
-84
-78
-00
-00
-ENDCHAR
-STARTCHAR uniFEDF
-ENCODING 65247
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-08
-08
-08
-08
-08
-F0
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEE0
-ENCODING 65248
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-08
-08
-08
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEE1
-ENCODING 65249
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-0C
-12
-12
-3C
-40
-40
-40
-40
-40
-40
-00
-00
-ENDCHAR
-STARTCHAR uniFEE2
-ENCODING 65250
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-3C
-4B
-4A
-44
-40
-40
-40
-00
-00
-ENDCHAR
-STARTCHAR uniFEE3
-ENCODING 65251
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-12
-32
-CC
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEE4
-ENCODING 65252
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-12
-32
-CD
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEE5
-ENCODING 65253
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-08
-00
-00
-41
-81
-81
-81
-42
-3C
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEE6
-ENCODING 65254
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-01
-41
-81
-81
-42
-3C
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEE7
-ENCODING 65255
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-00
-08
-04
-04
-F8
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEE8
-ENCODING 65256
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-08
-00
-00
-08
-08
-F7
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEE9
-ENCODING 65257
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-18
-24
-22
-22
-1C
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEEA
-ENCODING 65258
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-10
-10
-68
-88
-74
-03
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEEB
-ENCODING 65259
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-40
-30
-4E
-49
-39
-E6
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEEC
-ENCODING 65260
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-08
-14
-24
-28
-F3
-24
-18
-0C
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEED
-ENCODING 65261
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-0C
-12
-0E
-02
-04
-18
-60
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEEE
-ENCODING 65262
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-0C
-12
-0F
-02
-04
-18
-60
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEEF
-ENCODING 65263
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEF0
-ENCODING 65264
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-07
-88
-87
-81
-7E
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEF1
-ENCODING 65265
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-07
-08
-88
-86
-81
-81
-7E
-00
-00
-24
-00
-ENDCHAR
-STARTCHAR uniFEF2
-ENCODING 65266
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-00
-00
-07
-88
-87
-81
-7E
-00
-24
-00
-ENDCHAR
-STARTCHAR uniFEF3
-ENCODING 65267
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-08
-04
-04
-F8
-00
-00
-14
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEF4
-ENCODING 65268
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-00
-00
-00
-00
-08
-08
-F7
-00
-00
-14
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEF5
-ENCODING 65269
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-68
-90
-02
-22
-12
-0A
-04
-0C
-12
-3C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEF6
-ENCODING 65270
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-68
-90
-02
-32
-12
-0A
-0A
-0E
-3D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEF7
-ENCODING 65271
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-60
-80
-72
-A2
-12
-0A
-04
-0C
-12
-3C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEF8
-ENCODING 65272
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-30
-40
-3A
-52
-12
-0A
-0A
-0E
-3D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEF9
-ENCODING 65273
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-42
-22
-12
-0A
-04
-0C
-12
-3C
-00
-18
-20
-1C
-20
-00
-ENDCHAR
-STARTCHAR uniFEFA
-ENCODING 65274
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-22
-12
-12
-0A
-0A
-0E
-3D
-00
-00
-18
-20
-1C
-20
-00
-ENDCHAR
-STARTCHAR uniFEFB
-ENCODING 65275
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-42
-22
-12
-0A
-04
-0C
-12
-3C
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEFC
-ENCODING 65276
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-00
-22
-12
-12
-0A
-0A
-0E
-3D
-00
-00
-00
-00
-00
-00
-00
-ENDCHAR
-STARTCHAR uniFEFF
-ENCODING 65279
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-F1
-35
-55
-8A
-E0
-06
-95
-D6
-B5
-97
-00
-EE
-8A
-EE
-28
-E8
-ENDCHAR
-STARTCHAR uniFFFD
-ENCODING 65533
-SWIDTH 480 0
-DWIDTH 8 0
-BBX 8 16 0 -4
-BITMAP
-00
-38
-7C
-7C
-C6
-92
-F2
-E6
-FE
-E6
-7C
-7C
-38
-00
-00
-00
-ENDCHAR
-ENDFONT
Index: ntrib/tools/download_and_patch_silo.sh
===================================================================
--- contrib/tools/download_and_patch_silo.sh	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,74 +1,0 @@
-#!/bin/bash
-
-# Download SILO and patch it so that it can be used to create a bootable CD
-# for the Serengeti machine
-#  by Pavel Rimsky <rimskyp@seznam.cz>
-#  portions by Martin Decky <martin@decky.cz>
-#
-#  GPL'ed, copyleft
-#
-
-# stuff to be downloaded
-SILO_DOWNLOAD_FILE='silo-loaders-1.4.11.tar.gz'
-SILO_DOWNLOAD_URL='http://silo.auxio.org/pub/silo/old/'$SILO_DOWNLOAD_FILE
-
-# check whether the last command failed, if so, write an error message and exit
-check_error() {
-    if [ "$1" -ne "0" ]; then
-        echo
-        echo "Script failed: $2"
-        exit
-    fi
-}
-
-# temporary files are to be stored in /tmp
-# the resulting file in the current directory
-WD=`pwd`
-cd /tmp
-
-# download SILO from its official website
-echo ">>> Downloading SILO"
-wget $SILO_DOWNLOAD_URL
-check_error $? "Error downloading SILO."
-
-# unpack the downloaded file
-echo ">>> Unpacking tarball"
-tar xvzf $SILO_DOWNLOAD_FILE
-check_error $? "Error unpacking tarball."
-
-# CD to the unpacked directory
-echo ">>> Changing to the unpacked SILO directory"
-cd boot
-check_error $? "Changing directory failed."
-
-# patch it - remove bytes 512 to 512 + 32 (counted from 0), which belong to
-# the ELF header which is not recognized by the Serengeti firmware
-echo ">>> Patching SILO"
-(((xxd -p -l 512 isofs.b) && (xxd -p -s 544 isofs.b)) | xxd -r -p) \
-	 > isofs.b.patched
-check_error $? "Patching SILO failed"
-mv isofs.b.patched isofs.b
-
-# get rid of files which are not needed for creating the bootable CD
-echo ">>> Purging SILO directory"
-for file in `ls`; do
-	if [ \( -f $file \) -a \( $file != "isofs.b" \) -a \( $file != "second.b" \) ];
-		then
-		rm -fr $file;
-	fi
-done
-check_error $? "Purging SILO directory failed"
-
-# create the gzipped tarball with patched SILO
-echo ">>> Creating tarball with patched SILO"
-tar cvzf silo.patched.tar.gz *.b
-check_error $? "Creating tarball with patched SILO failed"
-
-# and move it to the directory where the user expects it to be
-echo ">>> Moving the tarball with patched SILO to the current directory"
-mv silo.patched.tar.gz $WD
-check_error $? "Moving the tarball with patched SILO failed"
-
-# move back to the working directory from /tmp
-cd $WD
-
Index: contrib/tools/font/bdf2c.pl
===================================================================
--- contrib/tools/font/bdf2c.pl	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ contrib/tools/font/bdf2c.pl	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,164 @@
+#!/usr/bin/perl -w
+
+#
+# Copyright (c) 2000 Dmitry Bolkhovityanov
+# Copyright (c) 2009 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.
+#
+
+use strict;
+
+my $skip;
+
+my $width;
+my $height;
+my $offset_x;
+my $offset_y;
+
+my $gwidth;
+my $gheight;
+my $goffset_x;
+my $goffset_y;
+
+my $index;
+my @glyphs;
+my @chars;
+
+open(BDF, "u_vga16.bdf") or die("Unable to open source font\n");
+
+READHEADER: while (<BDF>) {
+	/^FONTBOUNDINGBOX\s/ and do {
+		($skip, $width, $height, $offset_x, $offset_y) = (split);
+		
+		die("Font width is not 8px\n") if ($width != 8);
+		die("Font height is not 16px\n") if ($height != 16);
+	};
+	/^CHARS\s/ && last READHEADER;
+}
+
+READCHARS: while (<BDF>) {
+	/^ENCODING\s+([0-9]+)\s*$/ && do {
+		$index = $1;
+	};
+	/^BBX\s/ && do {
+		($skip, $gwidth, $gheight, $goffset_x, $goffset_y) = (split);
+	};
+	/^BITMAP/ && do {
+		my @glyph = ();
+		my $y;
+		
+		# Add empty lines at top
+		my $empties = $height + $offset_y - $goffset_y - $gheight;
+		
+		for ($y = 0; $y < $empties; $y++) {
+			$glyph[$y] = 0;
+		}
+		
+		# Scan the hex bitmap
+		for ($y = $empties; $y < $empties + $gheight; $y++) {
+			$_ = <BDF>;
+			$glyph[$y] = hex(substr($_, 0, 2)) >> $goffset_x;
+		}
+		
+		# Add empty lines at bottom
+		my $fill = $height - $gheight - $empties;
+		for ($y = $empties + $gheight; $y < $empties + $gheight + $fill; $y++) {
+			$glyph[$y] = 0;
+		}
+		
+		if ($index != 0) {
+			$glyphs[$index] = (\@glyph);
+			push(@chars, $index);
+		}
+	};
+	/^ENDFONT/ && last READCHARS;
+}
+
+close(BDF);
+
+@chars = sort { $a <=> $b } (@chars);
+
+print "#define FONT_GLYPHS     " . (@chars + 1). "\n";
+print "#define FONT_SCANLINES  " . $height . "\n";
+
+print "\n";
+print "uint16_t fb_font_glyph(const wchar_t ch)\n";
+print "{\n";
+print "\tif (ch == 0x0000)\n";
+print "\t\treturn 0;\n\n";
+
+my $pos = 0;
+my $start = -1;
+my $start_pos = 0;
+my $prev = 0;
+for $index (@chars) {
+	if ($prev + 1 < $index) {
+		if ($start != -1) {
+			if ($start == $prev) {
+				printf "\tif (ch == 0x%.4x)\n", $start;
+				print "\t\treturn " . $start_pos . ";\n";
+			} else {
+				printf "\tif ((ch >= 0x%.4x) && (ch <= 0x%.4x))\n", $start, $prev;
+				print "\t\treturn (ch - " . ($start - $start_pos) . ");\n";
+			}
+			
+			print "\t\n";
+		}
+		
+		$start = $index;
+		$start_pos = $pos;
+	}
+	
+	$pos++;
+	$prev = $index;
+}
+
+print "\treturn " . @chars . ";\n";
+print "}\n";
+
+print "\n";
+print "uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES] = {";
+
+for $index (@chars) {
+	print "\n\t{";
+	
+	my $y;
+	for ($y = 0; $y < $height; $y++) {
+		print ", " if ($y > 0);
+		printf "0x%.2x", $glyphs[$index]->[$y];
+	}
+	
+	print "},";
+}
+
+print "\n\t\n\t/* Special glyph for unknown character */\n\t{";
+my $y;
+for ($y = 0; $y < $height; $y++) {
+	print ", " if ($y > 0);
+	printf "0x%.2x", $glyphs[63]->[$y];
+}
+
+print "}\n};\n";
Index: contrib/tools/font/u_vga16.bdf
===================================================================
--- contrib/tools/font/u_vga16.bdf	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ contrib/tools/font/u_vga16.bdf	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,66709 @@
+STARTFONT 2.1
+FONT -Bolkhov-VGA-Medium-R-Normal--16-160-75-75-C-80-iso10646-1
+SIZE 16 75 75
+FONTBOUNDINGBOX 8 16 0 -4
+STARTPROPERTIES 24
+FOUNDRY "Bolkhov"
+FAMILY_NAME "VGA"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 16
+POINT_SIZE 160
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 80
+CHARSET_REGISTRY "iso10646"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 10
+X_HEIGHT 7
+FONT_ASCENT 12
+FONT_DESCENT 4
+FACE_NAME "VGA Unicode"
+COPYRIGHT "Copyright (c) 2000 Dmitry Bolkhovityanov, bolkhov@inp.nsk.su"
+HOMEPAGE "http://www.inp.nsk.su/~bolkhov/files/fonts/univga/"
+NOTICE "VGA is a trademark of IBM Corporation."
+DEFAULT_CHAR 0
+_XMBDFED_INFO "Edited with xmbdfed 4.4."
+ENDPROPERTIES
+CHARS 2899
+STARTCHAR char0
+ENCODING 0
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DA
+02
+80
+82
+02
+80
+82
+02
+80
+B6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+3C
+3C
+18
+18
+18
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+66
+66
+66
+24
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+6C
+6C
+FE
+6C
+6C
+6C
+FE
+6C
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+7C
+C6
+C2
+C0
+7C
+06
+06
+86
+C6
+7C
+18
+18
+00
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C2
+C6
+0C
+18
+30
+60
+C6
+86
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+6C
+38
+76
+DC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+30
+30
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+30
+30
+30
+30
+30
+30
+18
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+18
+0C
+0C
+0C
+0C
+0C
+0C
+18
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+3C
+FF
+3C
+66
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+18
+7E
+18
+18
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+18
+18
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+02
+06
+0C
+18
+30
+60
+C0
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+C6
+C6
+D6
+D6
+C6
+C6
+6C
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+38
+78
+18
+18
+18
+18
+18
+18
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+06
+0C
+18
+30
+60
+C0
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+06
+06
+3C
+06
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+1C
+3C
+6C
+CC
+FE
+0C
+0C
+0C
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C0
+C0
+C0
+FC
+06
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+60
+C0
+C0
+FC
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+06
+06
+0C
+18
+30
+30
+30
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+7C
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+7E
+06
+06
+06
+0C
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+18
+00
+00
+00
+18
+18
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+18
+00
+00
+00
+18
+18
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+06
+0C
+18
+30
+60
+30
+18
+0C
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+00
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+60
+30
+18
+0C
+06
+0C
+18
+30
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+0C
+18
+18
+18
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+C6
+C6
+DE
+DE
+DE
+DC
+C0
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+66
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+66
+66
+66
+66
+6C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+DE
+C6
+C6
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+0C
+0C
+0C
+0C
+0C
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+60
+60
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+D6
+DE
+7C
+0C
+0E
+00
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+60
+38
+0C
+06
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+D6
+D6
+D6
+FE
+EE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+6C
+7C
+38
+38
+7C
+6C
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+86
+0C
+18
+30
+60
+C2
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+30
+30
+30
+30
+30
+30
+30
+30
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+80
+C0
+E0
+70
+38
+1C
+0E
+06
+02
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+6C
+C6
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+78
+6C
+66
+66
+66
+66
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+64
+60
+F0
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+06
+00
+0E
+06
+06
+06
+06
+06
+06
+66
+66
+3C
+00
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+66
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+EC
+FE
+D6
+D6
+D6
+D6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+7C
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+0C
+1E
+00
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+30
+30
+36
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+66
+66
+66
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+6C
+38
+38
+38
+6C
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+CC
+18
+30
+60
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+18
+18
+18
+70
+18
+18
+18
+18
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+00
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+18
+18
+18
+0E
+18
+18
+18
+18
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR char127
+ENCODING 127
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+38
+6C
+C6
+C6
+C6
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+18
+18
+18
+3C
+3C
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+18
+3C
+66
+60
+60
+60
+66
+3C
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+6C
+64
+60
+F0
+60
+60
+60
+60
+E6
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+66
+3C
+66
+66
+66
+3C
+66
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+3C
+18
+7E
+18
+7E
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+00
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+C6
+60
+38
+6C
+C6
+C6
+6C
+38
+0C
+C6
+7C
+00
+00
+00
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+99
+A5
+A1
+A1
+A5
+99
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+3C
+6C
+6C
+3E
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+36
+6C
+D8
+6C
+36
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FE
+06
+06
+06
+06
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+3C
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+44
+BA
+B2
+AA
+44
+38
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+6C
+6C
+38
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+18
+7E
+18
+18
+00
+7E
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+D8
+30
+60
+C8
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+D8
+30
+18
+D8
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+F6
+C0
+C0
+C0
+00
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7F
+DB
+DB
+DB
+7B
+1B
+1B
+1B
+1B
+1B
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+70
+30
+30
+30
+78
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+6C
+6C
+38
+00
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+D8
+6C
+36
+6C
+D8
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+C2
+C6
+CC
+18
+30
+66
+CE
+9E
+3E
+06
+06
+00
+00
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+C2
+C6
+CC
+18
+30
+60
+DC
+86
+0C
+18
+3E
+00
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+E0
+30
+62
+36
+EC
+18
+30
+66
+CE
+9E
+3E
+06
+06
+00
+00
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+30
+30
+60
+C0
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+6C
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+38
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+6C
+CC
+CC
+FE
+CC
+CC
+CC
+CC
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+C0
+C0
+C2
+66
+3C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+18
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+18
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+3C
+42
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+66
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+F6
+66
+66
+66
+6C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+3C
+18
+3C
+66
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7A
+C4
+CE
+CE
+D6
+D6
+E6
+E6
+46
+BC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+7C
+66
+66
+66
+66
+7C
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+6C
+66
+66
+66
+66
+EC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+30
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+6C
+38
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+76
+36
+7E
+D8
+D8
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+18
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+1C
+3C
+06
+7E
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+18
+00
+7E
+00
+18
+18
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7A
+C4
+CE
+D6
+E6
+46
+BC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+30
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+CC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+7C
+66
+66
+66
+66
+66
+7C
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+0C
+18
+0E
+00
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+0C
+18
+0E
+00
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+3C
+66
+C2
+C0
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+3C
+66
+C2
+C0
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+3C
+66
+C2
+C0
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+3C
+66
+C2
+C0
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+F8
+6C
+66
+66
+66
+66
+66
+6C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+F6
+66
+66
+66
+6C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+3E
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+18
+30
+1C
+00
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+3C
+66
+C2
+C0
+DE
+C6
+C6
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+3C
+66
+C2
+C0
+DE
+C6
+C6
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+3C
+66
+C2
+C0
+DE
+C6
+C6
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+DE
+C6
+C6
+66
+3A
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+30
+30
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+E0
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+FF
+66
+66
+7E
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+F8
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7E
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7E
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+3C
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+3C
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+18
+30
+1C
+00
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+38
+18
+18
+18
+18
+18
+3C
+18
+30
+1C
+00
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F7
+63
+63
+63
+63
+63
+63
+7B
+7B
+EE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+00
+EE
+66
+66
+66
+66
+66
+F6
+06
+66
+3C
+00
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+1C
+22
+1E
+0C
+0C
+0C
+0C
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+04
+0E
+1B
+00
+0E
+06
+06
+06
+06
+06
+06
+66
+66
+3C
+00
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E6
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+66
+6C
+78
+78
+6C
+66
+E6
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+E6
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+30
+00
+F0
+60
+60
+60
+60
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+38
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+60
+60
+60
+62
+66
+FE
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+F0
+60
+60
+60
+60
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+38
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+66
+66
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+30
+30
+30
+36
+36
+30
+30
+30
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+78
+E0
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+1E
+78
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+C6
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+60
+60
+C0
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+C6
+06
+06
+1C
+00
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+06
+06
+1C
+00
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+CC
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+CC
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6E
+D8
+D8
+D8
+DE
+D8
+D8
+D8
+D8
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+D6
+D6
+DE
+D8
+D8
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+66
+E6
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+FC
+66
+66
+66
+7C
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+7C
+C6
+C6
+60
+38
+0C
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+7C
+C6
+C6
+60
+38
+0C
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+C6
+C6
+60
+38
+0C
+C6
+C6
+7C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+7C
+C6
+C6
+60
+38
+0C
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+30
+30
+36
+1C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+7E
+7E
+5A
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+10
+30
+FC
+30
+30
+30
+30
+36
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+3C
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+FC
+30
+30
+36
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+78
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+78
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+38
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+6C
+38
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+CC
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+CC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+C6
+C6
+C6
+D6
+D6
+D6
+FE
+EE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+C6
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+66
+00
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+FE
+C6
+8C
+18
+30
+60
+C2
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+FE
+CC
+18
+30
+60
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+FE
+C6
+8C
+18
+30
+60
+C2
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+FE
+CC
+18
+30
+60
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+FE
+C6
+8C
+18
+30
+60
+C2
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+FE
+CC
+18
+30
+60
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR longs
+ENCODING 383
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+64
+60
+60
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0180
+ENCODING 384
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+F8
+60
+78
+6C
+66
+66
+66
+66
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0181
+ENCODING 385
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+B3
+B3
+33
+3E
+33
+33
+33
+33
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0182
+ENCODING 386
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+64
+60
+60
+7C
+66
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0183
+ENCODING 387
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+62
+60
+78
+6C
+66
+66
+66
+66
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0184
+ENCODING 388
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+E6
+E6
+66
+7C
+66
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0185
+ENCODING 389
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+E0
+E0
+78
+6C
+66
+66
+66
+66
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0186
+ENCODING 390
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+86
+06
+06
+06
+06
+86
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0187
+ENCODING 391
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+03
+3E
+66
+C2
+C0
+C0
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0188
+ENCODING 392
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+03
+7E
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0189
+ENCODING 393
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+F6
+66
+66
+66
+6C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018A
+ENCODING 394
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+B6
+B3
+33
+33
+33
+33
+33
+36
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018B
+ENCODING 395
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+4C
+0C
+0C
+7C
+CC
+CC
+CC
+CC
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018C
+ENCODING 396
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+4C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018D
+ENCODING 397
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+C6
+C6
+7C
+30
+18
+CC
+78
+00
+ENDCHAR
+STARTCHAR uni018E
+ENCODING 398
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+CC
+8C
+2C
+3C
+2C
+0C
+8C
+CC
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni018F
+ENCODING 399
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+06
+06
+06
+FE
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0190
+ENCODING 400
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C2
+C0
+78
+C0
+C0
+C2
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0191
+ENCODING 401
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+60
+60
+60
+60
+60
+C0
+00
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+36
+32
+30
+78
+30
+30
+30
+30
+30
+30
+30
+E0
+00
+ENDCHAR
+STARTCHAR uni0193
+ENCODING 403
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+03
+3E
+66
+C2
+C0
+C0
+DE
+C6
+C6
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0194
+ENCODING 404
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+6C
+6C
+6C
+38
+38
+10
+38
+6C
+38
+00
+00
+ENDCHAR
+STARTCHAR uni0195
+ENCODING 405
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+C0
+F3
+DB
+DB
+DB
+DB
+DB
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0196
+ENCODING 406
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+30
+30
+30
+30
+30
+30
+30
+36
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0197
+ENCODING 407
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0198
+ENCODING 408
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+6D
+6C
+78
+70
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0199
+ENCODING 409
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+60
+66
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni019A
+ENCODING 410
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni019B
+ENCODING 411
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C8
+38
+70
+D0
+38
+38
+6C
+64
+C6
+C2
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni019C
+ENCODING 412
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D6
+D6
+D6
+D6
+D6
+D6
+D6
+D6
+FE
+EC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni019D
+ENCODING 413
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+76
+7E
+7E
+6E
+66
+66
+66
+66
+60
+60
+C0
+00
+ENDCHAR
+STARTCHAR uni019E
+ENCODING 414
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+06
+06
+06
+00
+ENDCHAR
+STARTCHAR uni019F
+ENCODING 415
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ohorn
+ENCODING 416
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+03
+7A
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ohorn
+ENCODING 417
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+06
+78
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A2
+ENCODING 418
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+73
+DF
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+73
+03
+03
+03
+00
+ENDCHAR
+STARTCHAR uni01A3
+ENCODING 419
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+73
+DF
+DB
+DB
+DB
+DB
+73
+03
+03
+03
+00
+ENDCHAR
+STARTCHAR uni01A4
+ENCODING 420
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+B3
+B3
+33
+3E
+30
+30
+30
+30
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A5
+ENCODING 421
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+60
+7C
+66
+66
+66
+66
+66
+7C
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR uni01A6
+ENCODING 422
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+7C
+66
+66
+7C
+78
+6C
+6C
+E6
+06
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A7
+ENCODING 423
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+0C
+38
+60
+C0
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A8
+ENCODING 424
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+0C
+38
+60
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01A9
+ENCODING 425
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+62
+30
+18
+18
+30
+62
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01AA
+ENCODING 426
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+D8
+78
+18
+18
+18
+18
+18
+18
+18
+18
+1B
+0E
+00
+ENDCHAR
+STARTCHAR uni01AB
+ENCODING 427
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+30
+30
+36
+1C
+0C
+6C
+38
+00
+ENDCHAR
+STARTCHAR uni01AC
+ENCODING 428
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+FE
+9A
+58
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01AD
+ENCODING 429
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+36
+30
+FC
+30
+30
+30
+30
+36
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01AE
+ENCODING 430
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+18
+18
+18
+0E
+00
+ENDCHAR
+STARTCHAR Uhorn
+ENCODING 431
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+03
+CE
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uhorn
+ENCODING 432
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+06
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B1
+ENCODING 433
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+EE
+6C
+6C
+6C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B2
+ENCODING 434
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B3
+ENCODING 435
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+63
+B3
+B3
+33
+1E
+0C
+0C
+0C
+0C
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B4
+ENCODING 436
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+06
+0D
+CC
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+18
+F0
+00
+ENDCHAR
+STARTCHAR uni01B5
+ENCODING 437
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+86
+0C
+7E
+30
+60
+C2
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B6
+ENCODING 438
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+CC
+18
+FC
+60
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01B7
+ENCODING 439
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+06
+0C
+18
+30
+7C
+06
+06
+06
+06
+C6
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni01B8
+ENCODING 440
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C0
+60
+30
+18
+7C
+C0
+C0
+C0
+C0
+C6
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni01B9
+ENCODING 441
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+C0
+60
+30
+78
+C0
+C0
+C0
+C6
+7C
+00
+ENDCHAR
+STARTCHAR uni01BA
+ENCODING 442
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+06
+0C
+18
+3C
+06
+7C
+C0
+C6
+7C
+00
+ENDCHAR
+STARTCHAR uni01BB
+ENCODING 443
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+06
+0C
+7E
+30
+60
+C0
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01BC
+ENCODING 444
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+60
+60
+78
+0C
+06
+06
+06
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01BD
+ENCODING 445
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+60
+78
+0C
+06
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01BE
+ENCODING 446
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+18
+4C
+6C
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01BF
+ENCODING 447
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+6C
+78
+70
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR uni01C0
+ENCODING 448
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C1
+ENCODING 449
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C2
+ENCODING 450
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+7E
+18
+7E
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C3
+ENCODING 451
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+3C
+3C
+18
+18
+18
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C4
+ENCODING 452
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1B
+0E
+04
+F7
+D9
+D9
+DA
+DA
+DA
+DC
+DC
+F7
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C5
+ENCODING 453
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F5
+DA
+D8
+DF
+D9
+DA
+DA
+DA
+DC
+F7
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C6
+ENCODING 454
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3D
+1A
+18
+7F
+D9
+DA
+DA
+DA
+DC
+6F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C7
+ENCODING 455
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C7
+C3
+C3
+C3
+C3
+C3
+C3
+C3
+CB
+F6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01C8
+ENCODING 456
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F3
+63
+60
+67
+63
+63
+63
+67
+6F
+FF
+03
+1B
+0E
+00
+ENDCHAR
+STARTCHAR uni01C9
+ENCODING 457
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E3
+63
+60
+67
+63
+63
+63
+63
+63
+F3
+03
+33
+1E
+00
+ENDCHAR
+STARTCHAR uni01CA
+ENCODING 458
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+FB
+FB
+FB
+DB
+DB
+DB
+DB
+DE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01CB
+ENCODING 459
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+F8
+FF
+FB
+FB
+DB
+DB
+DB
+DB
+03
+33
+1E
+00
+ENDCHAR
+STARTCHAR uni01CC
+ENCODING 460
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+00
+B7
+DB
+DB
+DB
+DB
+DB
+DB
+03
+33
+1E
+00
+ENDCHAR
+STARTCHAR uni01CD
+ENCODING 461
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01CE
+ENCODING 462
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01CF
+ENCODING 463
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D0
+ENCODING 464
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D1
+ENCODING 465
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D2
+ENCODING 466
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D3
+ENCODING 467
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D4
+ENCODING 468
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D5
+ENCODING 469
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+00
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D6
+ENCODING 470
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+78
+00
+CC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D7
+ENCODING 471
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+10
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D8
+ENCODING 472
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+30
+00
+CC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01D9
+ENCODING 473
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+10
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DA
+ENCODING 474
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+78
+30
+00
+CC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DB
+ENCODING 475
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+20
+10
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DC
+ENCODING 476
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+CC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DD
+ENCODING 477
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+06
+FE
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DE
+ENCODING 478
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+00
+6C
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01DF
+ENCODING 479
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+6C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E0
+ENCODING 480
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+30
+30
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E1
+ENCODING 481
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+30
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E2
+ENCODING 482
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+3E
+6C
+CC
+CC
+FE
+CC
+CC
+CC
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E3
+ENCODING 483
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+CC
+76
+36
+7E
+D8
+D8
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E4
+ENCODING 484
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+DE
+C6
+DF
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E5
+ENCODING 485
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+CC
+CC
+CC
+CC
+7C
+0C
+3E
+CC
+78
+00
+ENDCHAR
+STARTCHAR Gcaron
+ENCODING 486
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+3C
+66
+C2
+C0
+DE
+C6
+C6
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR gcaron
+ENCODING 487
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR uni01E8
+ENCODING 488
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+E6
+66
+66
+6C
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01E9
+ENCODING 489
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+E0
+60
+66
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01EA
+ENCODING 490
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR uni01EB
+ENCODING 491
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR uni01EC
+ENCODING 492
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR uni01ED
+ENCODING 493
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR uni01EE
+ENCODING 494
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+FE
+0C
+18
+30
+7C
+06
+06
+06
+06
+C6
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni01EF
+ENCODING 495
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+FE
+06
+0C
+18
+3C
+06
+06
+06
+C6
+7C
+00
+ENDCHAR
+STARTCHAR uni01F0
+ENCODING 496
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+1B
+0E
+04
+00
+0E
+06
+06
+06
+06
+06
+06
+66
+66
+3C
+00
+ENDCHAR
+STARTCHAR uni01F1
+ENCODING 497
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F7
+D9
+D9
+DA
+DA
+DA
+DA
+DC
+DC
+F7
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F2
+ENCODING 498
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+D8
+D8
+DF
+D9
+DA
+DA
+DA
+DC
+F7
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F3
+ENCODING 499
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+7F
+D9
+DA
+DA
+DA
+DC
+6F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F4
+ENCODING 500
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+3C
+66
+C2
+C0
+DE
+C6
+C6
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F5
+ENCODING 501
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+30
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR uni01F6
+ENCODING 502
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D8
+D8
+D8
+DB
+FB
+DB
+DB
+DB
+DB
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F7
+ENCODING 503
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+66
+6C
+78
+70
+60
+60
+60
+60
+E0
+00
+ENDCHAR
+STARTCHAR uni01F8
+ENCODING 504
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni01F9
+ENCODING 505
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+18
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Aringacute
+ENCODING 506
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+38
+6C
+38
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR aringacute
+ENCODING 507
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+38
+6C
+38
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR AEacute
+ENCODING 508
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+3E
+6C
+CC
+CC
+FE
+CC
+CC
+CC
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR aeacute
+ENCODING 509
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+CC
+76
+36
+7E
+D8
+D8
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Oslashacute
+ENCODING 510
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+7A
+C4
+CE
+CE
+D6
+E6
+E6
+46
+BC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oslashacute
+ENCODING 511
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+7A
+C4
+CE
+D6
+E6
+46
+BC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0200
+ENCODING 512
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+CC
+66
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0201
+ENCODING 513
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+66
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0202
+ENCODING 514
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0203
+ENCODING 515
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0204
+ENCODING 516
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+CC
+66
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0205
+ENCODING 517
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+66
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0206
+ENCODING 518
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0207
+ENCODING 519
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0208
+ENCODING 520
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+CC
+66
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0209
+ENCODING 521
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+66
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020A
+ENCODING 522
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+3C
+66
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020B
+ENCODING 523
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020C
+ENCODING 524
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+CC
+66
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020D
+ENCODING 525
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+66
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020E
+ENCODING 526
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni020F
+ENCODING 527
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0210
+ENCODING 528
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+CC
+66
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0211
+ENCODING 529
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+66
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0212
+ENCODING 530
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0213
+ENCODING 531
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0214
+ENCODING 532
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+CC
+66
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0215
+ENCODING 533
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+66
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0216
+ENCODING 534
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0217
+ENCODING 535
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+60
+38
+0C
+06
+C6
+C6
+7C
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+30
+30
+36
+1C
+00
+18
+18
+30
+ENDCHAR
+STARTCHAR uni021C
+ENCODING 540
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+86
+06
+1C
+74
+06
+06
+06
+06
+1C
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni021D
+ENCODING 541
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+0E
+3C
+06
+06
+1C
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni021E
+ENCODING 542
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni021F
+ENCODING 543
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+E0
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0222
+ENCODING 546
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+C6
+C6
+C6
+7C
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0223
+ENCODING 547
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+66
+66
+66
+3C
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0224
+ENCODING 548
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+86
+0C
+18
+30
+60
+C0
+C0
+FC
+06
+0C
+00
+00
+ENDCHAR
+STARTCHAR uni0225
+ENCODING 549
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+CC
+18
+30
+60
+C0
+FC
+06
+0C
+00
+00
+ENDCHAR
+STARTCHAR uni0226
+ENCODING 550
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0227
+ENCODING 551
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0228
+ENCODING 552
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+62
+66
+FE
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR uni0229
+ENCODING 553
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR uni022A
+ENCODING 554
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+00
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni022B
+ENCODING 555
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni022C
+ENCODING 556
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+00
+72
+9C
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni022D
+ENCODING 557
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+00
+76
+DC
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni022E
+ENCODING 558
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni022F
+ENCODING 559
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0230
+ENCODING 560
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+00
+30
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0231
+ENCODING 561
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+30
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0232
+ENCODING 562
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+3C
+00
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0233
+ENCODING 563
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni0250
+ENCODING 592
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+7C
+60
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0251
+ENCODING 593
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+74
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0252
+ENCODING 594
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+5C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0253
+ENCODING 595
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+60
+78
+6C
+66
+66
+66
+66
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0254
+ENCODING 596
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0255
+ENCODING 597
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+DC
+E6
+7C
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0256
+ENCODING 598
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+7C
+0C
+0D
+06
+00
+ENDCHAR
+STARTCHAR uni0257
+ENCODING 599
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+0D
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0258
+ENCODING 600
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+FE
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+06
+FE
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni025A
+ENCODING 602
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3B
+6C
+8E
+16
+26
+6C
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni025B
+ENCODING 603
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+78
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni025C
+ENCODING 604
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+3C
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni025D
+ENCODING 605
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7A
+CD
+0D
+38
+0C
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni025E
+ENCODING 606
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+DC
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni025F
+ENCODING 607
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0E
+06
+06
+1F
+06
+06
+06
+66
+66
+3C
+00
+ENDCHAR
+STARTCHAR uni0260
+ENCODING 608
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+06
+0D
+7C
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR uni0261
+ENCODING 609
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR uni0262
+ENCODING 610
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+CE
+C6
+C6
+7A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0263
+ENCODING 611
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+46
+6C
+2C
+2C
+38
+18
+18
+18
+18
+00
+ENDCHAR
+STARTCHAR uni0264
+ENCODING 612
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C2
+64
+28
+38
+38
+6C
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0265
+ENCODING 613
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CE
+CC
+CC
+CC
+CC
+DC
+6C
+0C
+0C
+0E
+00
+ENDCHAR
+STARTCHAR uni0266
+ENCODING 614
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0267
+ENCODING 615
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+60
+6C
+76
+66
+66
+66
+66
+E6
+06
+06
+1C
+00
+ENDCHAR
+STARTCHAR uni0268
+ENCODING 616
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+38
+18
+18
+3C
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0269
+ENCODING 617
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+18
+18
+18
+18
+18
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni026A
+ENCODING 618
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni026B
+ENCODING 619
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+7B
+DE
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni026C
+ENCODING 620
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+78
+58
+3E
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni026D
+ENCODING 621
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+1B
+0E
+00
+ENDCHAR
+STARTCHAR uni026E
+ENCODING 622
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+7F
+63
+66
+6C
+7E
+63
+F3
+03
+33
+1E
+00
+ENDCHAR
+STARTCHAR uni026F
+ENCODING 623
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+D6
+D6
+D6
+D6
+FE
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0270
+ENCODING 624
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+D6
+D6
+D6
+D6
+FE
+6E
+06
+06
+06
+00
+ENDCHAR
+STARTCHAR uni0271
+ENCODING 625
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+EC
+FE
+D6
+D6
+D6
+D6
+C6
+06
+06
+1C
+00
+ENDCHAR
+STARTCHAR uni0272
+ENCODING 626
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+60
+60
+C0
+00
+ENDCHAR
+STARTCHAR uni0273
+ENCODING 627
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+06
+06
+03
+00
+ENDCHAR
+STARTCHAR uni0274
+ENCODING 628
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0275
+ENCODING 629
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+FE
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0276
+ENCODING 630
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6E
+D8
+D8
+DE
+D8
+D8
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0277
+ENCODING 631
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+C6
+D6
+D6
+D6
+D6
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0278
+ENCODING 632
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+7C
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR uni0279
+ENCODING 633
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+1E
+0C
+0C
+0C
+CC
+DC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni027A
+ENCODING 634
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+0C
+0C
+0C
+0C
+0C
+0C
+CC
+DC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni027B
+ENCODING 635
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+1E
+0C
+0C
+0C
+CC
+DC
+6C
+0C
+0D
+06
+00
+ENDCHAR
+STARTCHAR uni027C
+ENCODING 636
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+76
+66
+60
+60
+60
+60
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR uni027D
+ENCODING 637
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+76
+66
+60
+60
+60
+60
+60
+6C
+38
+00
+ENDCHAR
+STARTCHAR uni027E
+ENCODING 638
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+66
+66
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni027F
+ENCODING 639
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+78
+CC
+CC
+0C
+0C
+0C
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0280
+ENCODING 640
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FC
+66
+66
+7C
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0281
+ENCODING 641
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+E6
+66
+6C
+7C
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0282
+ENCODING 642
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+60
+38
+0C
+C6
+FC
+C0
+D8
+70
+00
+ENDCHAR
+STARTCHAR uni0283
+ENCODING 643
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+1B
+19
+18
+18
+18
+18
+18
+18
+18
+98
+D8
+70
+00
+ENDCHAR
+STARTCHAR uni0284
+ENCODING 644
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+1B
+19
+18
+18
+18
+18
+18
+18
+3C
+98
+D8
+70
+00
+ENDCHAR
+STARTCHAR uni0285
+ENCODING 645
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+D8
+18
+18
+18
+18
+1B
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0286
+ENCODING 646
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0E
+1B
+18
+18
+18
+18
+18
+18
+7E
+D8
+70
+00
+ENDCHAR
+STARTCHAR uni0287
+ENCODING 647
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+D8
+18
+18
+18
+18
+7E
+18
+18
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0288
+ENCODING 648
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+30
+30
+30
+30
+30
+36
+1C
+00
+ENDCHAR
+STARTCHAR uni0289
+ENCODING 649
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+66
+FF
+66
+66
+3B
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni028A
+ENCODING 650
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+EE
+6C
+6C
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni028B
+ENCODING 651
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni028C
+ENCODING 652
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+3C
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni028D
+ENCODING 653
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+FE
+D6
+D6
+D6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni028E
+ENCODING 654
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+60
+C0
+FC
+C6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni028F
+ENCODING 655
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+66
+3C
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0290
+ENCODING 656
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+CC
+18
+30
+60
+C6
+FE
+06
+06
+03
+00
+ENDCHAR
+STARTCHAR uni0291
+ENCODING 657
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+CC
+18
+30
+66
+CB
+FE
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0292
+ENCODING 658
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+06
+0C
+18
+3C
+06
+06
+06
+C6
+7C
+00
+ENDCHAR
+STARTCHAR uni0293
+ENCODING 659
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+06
+0C
+18
+3C
+06
+06
+7E
+C7
+7C
+00
+ENDCHAR
+STARTCHAR uni0294
+ENCODING 660
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+06
+1C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0295
+ENCODING 661
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C0
+70
+30
+30
+30
+30
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0296
+ENCODING 662
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+18
+1C
+06
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0297
+ENCODING 663
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+C0
+C0
+C0
+C6
+7C
+00
+ENDCHAR
+STARTCHAR uni0298
+ENCODING 664
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C3
+C3
+DB
+DB
+C3
+C3
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0299
+ENCODING 665
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FC
+66
+66
+7C
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni029A
+ENCODING 666
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+76
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni029B
+ENCODING 667
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+03
+7E
+C6
+C0
+CE
+C6
+C6
+7A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni029C
+ENCODING 668
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 669
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+0C
+00
+1C
+0C
+0C
+0C
+0C
+0C
+0C
+7E
+CC
+78
+00
+ENDCHAR
+STARTCHAR uni029D
+ENCODING 670
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CE
+CC
+6C
+3C
+3C
+6C
+CC
+0C
+0C
+0E
+00
+ENDCHAR
+STARTCHAR uni029E
+ENCODING 671
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+F0
+60
+60
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni029F
+ENCODING 672
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+06
+0D
+7C
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+0C
+1E
+00
+ENDCHAR
+STARTCHAR uni02A0
+ENCODING 673
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+06
+1C
+18
+7E
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02A1
+ENCODING 674
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C0
+70
+30
+FC
+30
+30
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02A2
+ENCODING 675
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+7F
+D9
+DA
+DA
+DA
+DC
+6F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02A3
+ENCODING 676
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+7F
+DB
+DB
+DE
+DE
+DB
+6B
+03
+1B
+0E
+00
+ENDCHAR
+STARTCHAR uni02A4
+ENCODING 677
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+7F
+D9
+DA
+DA
+DB
+DD
+6F
+04
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02A5
+ENCODING 678
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+60
+60
+F6
+6D
+6C
+66
+63
+6B
+36
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02A6
+ENCODING 679
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+26
+6D
+6C
+FC
+6C
+6C
+6C
+6C
+6C
+3C
+0C
+2C
+18
+00
+ENDCHAR
+STARTCHAR uni02A7
+ENCODING 680
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+60
+60
+F6
+6D
+6C
+6C
+6E
+6D
+36
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02A8
+ENCODING 681
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+D8
+C0
+FE
+DB
+DB
+DB
+DB
+DB
+DB
+03
+03
+0E
+00
+ENDCHAR
+STARTCHAR uni02A9
+ENCODING 682
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+66
+6D
+6C
+66
+63
+6B
+F6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02AA
+ENCODING 683
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+6F
+6B
+63
+66
+6C
+6D
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02AB
+ENCODING 684
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+D6
+7C
+6C
+28
+C6
+D6
+7C
+6C
+28
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02AC
+ENCODING 685
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+C6
+C6
+00
+00
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B0
+ENCODING 688
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+F0
+D8
+D8
+D8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B1
+ENCODING 689
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+C0
+F0
+D8
+D8
+D8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B2
+ENCODING 690
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+00
+38
+18
+18
+D8
+70
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B3
+ENCODING 691
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+B0
+D8
+C0
+C0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B4
+ENCODING 692
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+18
+D8
+68
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B5
+ENCODING 693
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+18
+D8
+68
+0C
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B6
+ENCODING 694
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+D8
+D8
+F0
+D8
+D8
+F0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B7
+ENCODING 695
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C6
+D6
+7C
+6C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B8
+ENCODING 696
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+D8
+D8
+78
+18
+70
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02B9
+ENCODING 697
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+30
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02BA
+ENCODING 698
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+36
+6C
+D8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02BB
+ENCODING 699
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+30
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57929
+ENCODING 700
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+18
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii64937
+ENCODING 701
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+30
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02BE
+ENCODING 702
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+0C
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02BF
+ENCODING 703
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+60
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02C0
+ENCODING 704
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+D8
+18
+30
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02C1
+ENCODING 705
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+D8
+C0
+60
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02C2
+ENCODING 706
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+70
+C0
+70
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02C3
+ENCODING 707
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+70
+18
+70
+C0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02C4
+ENCODING 708
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+20
+20
+70
+70
+D8
+D8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02C5
+ENCODING 709
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+D8
+D8
+70
+70
+20
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02C8
+ENCODING 712
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+18
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02CA
+ENCODING 714
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02CB
+ENCODING 715
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02CC
+ENCODING 716
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+18
+18
+00
+ENDCHAR
+STARTCHAR uni02CD
+ENCODING 717
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni02CE
+ENCODING 718
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+0C
+00
+ENDCHAR
+STARTCHAR uni02CF
+ENCODING 719
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+30
+60
+00
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+6C
+38
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+30
+1C
+00
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+CC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni02EE
+ENCODING 750
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+6C
+6C
+48
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR gravecomb
+ENCODING 768
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR acutecomb
+ENCODING 769
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR tildecomb
+ENCODING 771
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+34
+58
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hookabovecomb
+ENCODING 777
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+18
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0312
+ENCODING 786
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+30
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0313
+ENCODING 787
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+18
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0314
+ENCODING 788
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+30
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotbelowcomb
+ENCODING 803
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni0340
+ENCODING 832
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C0
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0341
+ENCODING 833
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0374
+ENCODING 884
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+20
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0375
+ENCODING 885
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+20
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni037A
+ENCODING 890
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+30
+34
+18
+00
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+18
+00
+00
+00
+18
+18
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+6C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Alphatonos
+ENCODING 902
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Epsilontonos
+ENCODING 904
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+3E
+32
+30
+34
+3C
+34
+30
+30
+32
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Etatonos
+ENCODING 905
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+33
+33
+33
+33
+3F
+33
+33
+33
+33
+33
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Iotatonos
+ENCODING 906
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+3C
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Omicrontonos
+ENCODING 908
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+3C
+66
+66
+66
+66
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Upsilontonos
+ENCODING 910
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+66
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Omegatonos
+ENCODING 911
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+3E
+63
+63
+63
+63
+63
+36
+36
+36
+77
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR iotadieresistonos
+ENCODING 912
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+6C
+00
+38
+18
+18
+18
+18
+18
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Alpha
+ENCODING 913
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Beta
+ENCODING 914
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+66
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Gamma
+ENCODING 915
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+60
+60
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Delta
+ENCODING 916
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+38
+38
+6C
+6C
+C6
+C6
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Epsilon
+ENCODING 917
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Zeta
+ENCODING 918
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+86
+0C
+18
+30
+60
+C2
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Eta
+ENCODING 919
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Theta
+ENCODING 920
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Iota
+ENCODING 921
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Kappa
+ENCODING 922
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Lambda
+ENCODING 923
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+38
+38
+6C
+6C
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Mu
+ENCODING 924
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Nu
+ENCODING 925
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Xi
+ENCODING 926
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+82
+44
+7C
+44
+00
+82
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Omicron
+ENCODING 927
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Pi
+ENCODING 928
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Rho
+ENCODING 929
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Sigma
+ENCODING 931
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+62
+30
+18
+18
+30
+62
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Tau
+ENCODING 932
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Upsilon
+ENCODING 933
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Phi
+ENCODING 934
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+7C
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Chi
+ENCODING 935
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+6C
+7C
+38
+38
+7C
+6C
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Psi
+ENCODING 936
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+92
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 937
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+6C
+6C
+6C
+EE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Iotadieresis
+ENCODING 938
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+66
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Upsilondieresis
+ENCODING 939
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+66
+00
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR alphatonos
+ENCODING 940
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR epsilontonos
+ENCODING 941
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+7C
+C6
+C0
+78
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR etatonos
+ENCODING 942
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+DC
+66
+66
+66
+66
+66
+66
+06
+06
+06
+00
+ENDCHAR
+STARTCHAR iotatonos
+ENCODING 943
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+38
+18
+18
+18
+18
+18
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR upsilondieresistonos
+ENCODING 944
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+6C
+00
+CC
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR alpha
+ENCODING 945
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR beta
+ENCODING 946
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+6C
+66
+66
+66
+66
+6C
+60
+60
+60
+00
+ENDCHAR
+STARTCHAR gamma
+ENCODING 947
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+46
+6C
+2C
+2C
+38
+18
+18
+18
+18
+00
+ENDCHAR
+STARTCHAR delta
+ENCODING 948
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+30
+18
+7C
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR epsilon
+ENCODING 949
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+78
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zeta
+ENCODING 950
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+46
+7C
+18
+30
+60
+60
+C0
+C0
+C0
+7C
+06
+06
+1C
+00
+ENDCHAR
+STARTCHAR eta
+ENCODING 951
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+06
+06
+06
+00
+ENDCHAR
+STARTCHAR theta
+ENCODING 952
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+7E
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR iota
+ENCODING 953
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+18
+18
+18
+18
+18
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR kappa
+ENCODING 954
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+E6
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR lambda
+ENCODING 955
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+20
+30
+10
+38
+38
+6C
+64
+C6
+C2
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+F6
+C0
+C0
+C0
+00
+ENDCHAR
+STARTCHAR nu
+ENCODING 957
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+66
+6C
+3C
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR xi
+ENCODING 958
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+3C
+30
+60
+3C
+60
+C0
+C0
+C0
+7C
+06
+06
+1C
+00
+ENDCHAR
+STARTCHAR omicron
+ENCODING 959
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 960
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+6C
+6C
+6C
+6C
+6C
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR rho
+ENCODING 961
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+66
+66
+66
+66
+66
+7C
+60
+60
+60
+00
+ENDCHAR
+STARTCHAR sigma1
+ENCODING 962
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+7C
+06
+06
+1C
+00
+00
+ENDCHAR
+STARTCHAR sigma
+ENCODING 963
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR tau
+ENCODING 964
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+18
+18
+18
+18
+18
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR upsilon
+ENCODING 965
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR phi
+ENCODING 966
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR chi
+ENCODING 967
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+86
+46
+2C
+2C
+18
+30
+68
+68
+C4
+C2
+00
+ENDCHAR
+STARTCHAR psi
+ENCODING 968
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+92
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR omega
+ENCODING 969
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+C6
+D6
+D6
+D6
+D6
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR iotadieresis
+ENCODING 970
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+00
+38
+18
+18
+18
+18
+18
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR upsilondieresis
+ENCODING 971
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+CC
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR omicrontonos
+ENCODING 972
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR upsilontonos
+ENCODING 973
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+CC
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR omegatonos
+ENCODING 974
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+6C
+C6
+D6
+D6
+D6
+D6
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03D0
+ENCODING 976
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+6C
+7C
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR theta1
+ENCODING 977
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+36
+1E
+C6
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Upsilon1
+ENCODING 978
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C2
+65
+24
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03D3
+ENCODING 979
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+C0
+21
+32
+12
+1C
+0C
+0C
+0C
+0C
+0C
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03D4
+ENCODING 980
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C2
+65
+24
+38
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR phi1
+ENCODING 981
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+7C
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR omega1
+ENCODING 982
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+6C
+C6
+D6
+D6
+D6
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03D7
+ENCODING 983
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+46
+A6
+2C
+38
+68
+CA
+C4
+0C
+18
+00
+00
+ENDCHAR
+STARTCHAR uni03DA
+ENCODING 986
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+C0
+C0
+60
+3C
+06
+06
+1C
+00
+00
+ENDCHAR
+STARTCHAR uni03DB
+ENCODING 987
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+C0
+C0
+C0
+C0
+C0
+7C
+06
+06
+1C
+00
+ENDCHAR
+STARTCHAR uni03DC
+ENCODING 988
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+60
+78
+68
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03DD
+ENCODING 989
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+32
+30
+30
+3C
+34
+30
+30
+30
+30
+00
+ENDCHAR
+STARTCHAR uni03DE
+ENCODING 990
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+60
+30
+30
+60
+63
+FF
+C6
+06
+0C
+0C
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03DF
+ENCODING 991
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+60
+60
+FE
+FE
+0C
+0C
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03E0
+ENCODING 992
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+AC
+26
+26
+0B
+0B
+1B
+1B
+1B
+1B
+03
+02
+04
+00
+ENDCHAR
+STARTCHAR uni03E1
+ENCODING 993
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C0
+60
+30
+18
+28
+4C
+14
+24
+06
+02
+02
+00
+ENDCHAR
+STARTCHAR uni03E2
+ENCODING 994
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+6D
+03
+3E
+00
+00
+ENDCHAR
+STARTCHAR uni03E3
+ENCODING 995
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DB
+DB
+DB
+DB
+DB
+DB
+6D
+03
+7E
+00
+00
+ENDCHAR
+STARTCHAR uni03E4
+ENCODING 996
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+D6
+C6
+C6
+C6
+7E
+06
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03E5
+ENCODING 997
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+36
+66
+66
+66
+66
+3E
+06
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03E6
+ENCODING 998
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+C0
+C0
+FC
+C6
+C6
+C6
+C6
+C6
+06
+76
+9C
+00
+ENDCHAR
+STARTCHAR uni03E7
+ENCODING 999
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+7C
+D6
+66
+06
+06
+66
+BC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03E8
+ENCODING 1000
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+06
+3C
+60
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03E9
+ENCODING 1001
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+26
+1C
+70
+C0
+C2
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03EA
+ENCODING 1002
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+68
+38
+30
+38
+38
+4C
+4C
+86
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03EB
+ENCODING 1003
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+64
+BA
+30
+38
+28
+4C
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03EC
+ENCODING 1004
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+C0
+CC
+D6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03ED
+ENCODING 1005
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+C0
+DC
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03EE
+ENCODING 1006
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+7E
+99
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03EF
+ENCODING 1007
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+1C
+18
+7E
+58
+18
+18
+18
+38
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03F0
+ENCODING 1008
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+46
+A6
+2C
+38
+68
+CA
+C4
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03F1
+ENCODING 1009
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+C6
+C6
+FC
+C0
+60
+3C
+06
+00
+ENDCHAR
+STARTCHAR uni03F2
+ENCODING 1010
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni03F3
+ENCODING 1011
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+06
+00
+0E
+06
+06
+06
+06
+06
+06
+66
+66
+3C
+00
+ENDCHAR
+STARTCHAR uni0400
+ENCODING 1024
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+18
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10023
+ENCODING 1025
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10051
+ENCODING 1026
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+B2
+30
+3E
+33
+33
+33
+33
+33
+33
+03
+06
+00
+00
+ENDCHAR
+STARTCHAR afii10052
+ENCODING 1027
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+FE
+66
+62
+60
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10053
+ENCODING 1028
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+F8
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10054
+ENCODING 1029
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+60
+38
+0C
+06
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10055
+ENCODING 1030
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10056
+ENCODING 1031
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+66
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10057
+ENCODING 1032
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+0C
+0C
+0C
+0C
+0C
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10058
+ENCODING 1033
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+D8
+D8
+D8
+DE
+DB
+DB
+DB
+DB
+DE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10059
+ENCODING 1034
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D8
+D8
+D8
+D8
+FE
+DB
+DB
+DB
+DB
+DE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10060
+ENCODING 1035
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+B2
+30
+3E
+33
+33
+33
+33
+33
+33
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10061
+ENCODING 1036
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+E6
+66
+66
+6C
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni040D
+ENCODING 1037
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+18
+00
+C6
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10062
+ENCODING 1038
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+C6
+C6
+C6
+C6
+7E
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10145
+ENCODING 1039
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+FE
+38
+10
+10
+00
+ENDCHAR
+STARTCHAR afii10017
+ENCODING 1040
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10018
+ENCODING 1041
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+60
+7C
+66
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10019
+ENCODING 1042
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+66
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10020
+ENCODING 1043
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+60
+60
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10021
+ENCODING 1044
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+FE
+C6
+82
+00
+00
+ENDCHAR
+STARTCHAR afii10022
+ENCODING 1045
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10024
+ENCODING 1046
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D6
+D6
+D6
+7C
+38
+7C
+D6
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10025
+ENCODING 1047
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+86
+06
+3C
+06
+06
+86
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10026
+ENCODING 1048
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10027
+ENCODING 1049
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+C6
+C6
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10028
+ENCODING 1050
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10029
+ENCODING 1051
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+66
+66
+66
+66
+66
+66
+66
+66
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10030
+ENCODING 1052
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10031
+ENCODING 1053
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10032
+ENCODING 1054
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10033
+ENCODING 1055
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10034
+ENCODING 1056
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10035
+ENCODING 1057
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10036
+ENCODING 1058
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10037
+ENCODING 1059
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+7E
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10038
+ENCODING 1060
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+7C
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10039
+ENCODING 1061
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+6C
+7C
+38
+38
+7C
+6C
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10040
+ENCODING 1062
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+FE
+06
+02
+00
+00
+ENDCHAR
+STARTCHAR afii10041
+ENCODING 1063
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+7E
+06
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10042
+ENCODING 1064
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+D6
+D6
+D6
+D6
+D6
+D6
+D6
+D6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10043
+ENCODING 1065
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+D6
+D6
+D6
+D6
+D6
+D6
+D6
+D6
+FF
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR afii10044
+ENCODING 1066
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+B0
+B0
+30
+3C
+36
+36
+36
+36
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10045
+ENCODING 1067
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C3
+C3
+C3
+C3
+F3
+DB
+DB
+DB
+DB
+F3
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10046
+ENCODING 1068
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+7C
+66
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10047
+ENCODING 1069
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+86
+06
+3E
+06
+06
+86
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10048
+ENCODING 1070
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+9C
+B6
+B6
+B6
+F6
+B6
+B6
+B6
+B6
+9C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10049
+ENCODING 1071
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+CC
+CC
+CC
+7C
+6C
+6C
+6C
+6C
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10065
+ENCODING 1072
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10066
+ENCODING 1073
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+7C
+C0
+C0
+FC
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10067
+ENCODING 1074
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FC
+66
+66
+7C
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10068
+ENCODING 1075
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+66
+62
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10069
+ENCODING 1076
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+6C
+6C
+6C
+6C
+6C
+FE
+C6
+82
+00
+00
+ENDCHAR
+STARTCHAR afii10070
+ENCODING 1077
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10072
+ENCODING 1078
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+D6
+D6
+D6
+7C
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10073
+ENCODING 1079
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+3C
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10074
+ENCODING 1080
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10075
+ENCODING 1081
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10076
+ENCODING 1082
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+E6
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10077
+ENCODING 1083
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3E
+66
+66
+66
+66
+66
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10078
+ENCODING 1084
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10079
+ENCODING 1085
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10080
+ENCODING 1086
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10081
+ENCODING 1087
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+C6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10082
+ENCODING 1088
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+7C
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR afii10083
+ENCODING 1089
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10084
+ENCODING 1090
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+5A
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10085
+ENCODING 1091
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR afii10086
+ENCODING 1092
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+7C
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR afii10087
+ENCODING 1093
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+6C
+38
+38
+38
+6C
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10088
+ENCODING 1094
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+FE
+06
+02
+00
+00
+ENDCHAR
+STARTCHAR afii10089
+ENCODING 1095
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+7E
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10090
+ENCODING 1096
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+D6
+D6
+D6
+D6
+D6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10091
+ENCODING 1097
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+D6
+D6
+D6
+D6
+D6
+FF
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR afii10092
+ENCODING 1098
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+F8
+B0
+30
+3C
+36
+36
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10093
+ENCODING 1099
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C3
+C3
+C3
+F3
+DB
+DB
+F3
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10094
+ENCODING 1100
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+F0
+60
+60
+7C
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10095
+ENCODING 1101
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+3E
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10096
+ENCODING 1102
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+9C
+B6
+B6
+F6
+B6
+B6
+9C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10097
+ENCODING 1103
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+CC
+CC
+7C
+6C
+6C
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0450
+ENCODING 1104
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10071
+ENCODING 1105
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10099
+ENCODING 1106
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+F8
+60
+6C
+76
+66
+66
+66
+66
+E6
+06
+06
+1C
+00
+ENDCHAR
+STARTCHAR afii10100
+ENCODING 1107
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+FE
+66
+62
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10101
+ENCODING 1108
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+F8
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10102
+ENCODING 1109
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10103
+ENCODING 1110
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10104
+ENCODING 1111
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10105
+ENCODING 1112
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+06
+00
+0E
+06
+06
+06
+06
+06
+06
+66
+66
+3C
+00
+ENDCHAR
+STARTCHAR afii10106
+ENCODING 1113
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+78
+D8
+D8
+DE
+DB
+DB
+DE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10107
+ENCODING 1114
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+D8
+D8
+D8
+FE
+DB
+DB
+DE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10108
+ENCODING 1115
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+F8
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10109
+ENCODING 1116
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+E6
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni045D
+ENCODING 1117
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10110
+ENCODING 1118
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR afii10193
+ENCODING 1119
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+FE
+38
+10
+10
+00
+ENDCHAR
+STARTCHAR uni0460
+ENCODING 1120
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+C6
+C6
+D6
+D6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0461
+ENCODING 1121
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10146
+ENCODING 1122
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+FC
+B4
+30
+3C
+36
+36
+36
+36
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10194
+ENCODING 1123
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+30
+FC
+B4
+30
+3C
+36
+36
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0464
+ENCODING 1124
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CE
+DB
+D9
+D8
+FE
+D8
+D8
+D9
+DB
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0465
+ENCODING 1125
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CE
+DB
+D8
+FE
+D8
+DB
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0466
+ENCODING 1126
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+38
+6C
+6C
+6C
+FE
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0467
+ENCODING 1127
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+38
+38
+6C
+7C
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0468
+ENCODING 1128
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+88
+8C
+9C
+96
+F6
+B6
+BF
+AB
+EB
+EB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0469
+ENCODING 1129
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+88
+8C
+9C
+F6
+BE
+AB
+EB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni046A
+ENCODING 1130
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+6C
+6C
+38
+7C
+D6
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni046B
+ENCODING 1131
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+C6
+6C
+7C
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni046C
+ENCODING 1132
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+A3
+B2
+96
+FC
+9C
+BE
+AA
+AB
+EB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni046D
+ENCODING 1133
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+BF
+A3
+96
+FE
+AB
+AB
+EB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni046E
+ENCODING 1134
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+10
+7C
+C6
+06
+06
+7C
+06
+06
+06
+7C
+C0
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni046F
+ENCODING 1135
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+6C
+38
+10
+00
+7C
+86
+06
+7C
+06
+06
+7C
+C0
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni0470
+ENCODING 1136
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+96
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0471
+ENCODING 1137
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+96
+D6
+D6
+D6
+D6
+D6
+7C
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR afii10147
+ENCODING 1138
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10195
+ENCODING 1139
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+FE
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10148
+ENCODING 1140
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C2
+C6
+C6
+C4
+CC
+6C
+68
+78
+38
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10196
+ENCODING 1141
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C2
+C6
+64
+6C
+38
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0476
+ENCODING 1142
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+CC
+66
+00
+C2
+C6
+C4
+C4
+6C
+68
+78
+38
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0477
+ENCODING 1143
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+66
+00
+C2
+C6
+64
+6C
+38
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0478
+ENCODING 1144
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+D8
+D8
+DB
+DB
+DB
+DB
+DB
+DB
+6F
+03
+06
+1C
+00
+ENDCHAR
+STARTCHAR uni0479
+ENCODING 1145
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+73
+DB
+DB
+DB
+DB
+DB
+6F
+03
+06
+1C
+00
+ENDCHAR
+STARTCHAR uni047A
+ENCODING 1146
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+7C
+D6
+C6
+C6
+C6
+C6
+C6
+C6
+D6
+7C
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni047B
+ENCODING 1147
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+7C
+D6
+C6
+C6
+C6
+D6
+7C
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni047C
+ENCODING 1148
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+7C
+40
+6C
+C6
+C6
+D6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni047D
+ENCODING 1149
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+04
+7C
+40
+00
+6C
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni047E
+ENCODING 1150
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+54
+00
+6C
+C6
+C6
+D6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni047F
+ENCODING 1151
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+54
+00
+6C
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0480
+ENCODING 1152
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+C0
+C0
+C0
+60
+3C
+0C
+0C
+0C
+00
+ENDCHAR
+STARTCHAR uni0481
+ENCODING 1153
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+C0
+78
+18
+18
+00
+00
+ENDCHAR
+STARTCHAR uni0482
+ENCODING 1154
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+06
+3C
+0F
+18
+18
+F0
+3C
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0483
+ENCODING 1155
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+04
+7C
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0484
+ENCODING 1156
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+24
+44
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0485
+ENCODING 1157
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+40
+7C
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0486
+ENCODING 1158
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+04
+7C
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0488
+ENCODING 1160
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+66
+00
+C3
+00
+66
+18
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0489
+ENCODING 1161
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+50
+46
+00
+82
+41
+00
+62
+0A
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni048A
+ENCODING 1162
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+C6
+C6
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni048B
+ENCODING 1163
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+C6
+CE
+DE
+FE
+F6
+E6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni048C
+ENCODING 1164
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+60
+F0
+60
+60
+60
+7C
+66
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni048D
+ENCODING 1165
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+60
+F0
+60
+60
+7C
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni048E
+ENCODING 1166
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+6E
+64
+7A
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni048F
+ENCODING 1167
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+6E
+64
+7A
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR afii10050
+ENCODING 1168
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+02
+06
+FE
+60
+60
+60
+60
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10098
+ENCODING 1169
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+02
+06
+FE
+60
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0492
+ENCODING 1170
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+60
+F8
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0493
+ENCODING 1171
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+66
+62
+F8
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0494
+ENCODING 1172
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+60
+7C
+66
+66
+66
+66
+F6
+06
+16
+0C
+00
+ENDCHAR
+STARTCHAR uni0495
+ENCODING 1173
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+66
+62
+78
+6C
+66
+F6
+06
+16
+0C
+00
+ENDCHAR
+STARTCHAR uni0496
+ENCODING 1174
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D6
+D6
+D6
+7C
+38
+7C
+D6
+D6
+D6
+D7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni0497
+ENCODING 1175
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+D6
+D6
+D6
+7C
+D6
+D6
+D7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni0498
+ENCODING 1176
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+86
+06
+3C
+06
+06
+86
+C6
+7C
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR uni0499
+ENCODING 1177
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+3C
+06
+C6
+7C
+30
+60
+38
+00
+ENDCHAR
+STARTCHAR uni049A
+ENCODING 1178
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni049B
+ENCODING 1179
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+E6
+6C
+78
+78
+6C
+66
+E7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni049C
+ENCODING 1180
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+D6
+D6
+DC
+F8
+DC
+D6
+D6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni049D
+ENCODING 1181
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+D6
+DC
+F8
+DC
+D6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni049E
+ENCODING 1182
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+F6
+6C
+78
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni049F
+ENCODING 1183
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+F0
+66
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04A0
+ENCODING 1184
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F3
+B3
+B3
+36
+3C
+3C
+36
+33
+33
+73
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04A1
+ENCODING 1185
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+F3
+B6
+BC
+3C
+36
+33
+73
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04A2
+ENCODING 1186
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04A3
+ENCODING 1187
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+FE
+C6
+C6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04A4
+ENCODING 1188
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DF
+DB
+D9
+D8
+F8
+D8
+D8
+D8
+D8
+D8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04A5
+ENCODING 1189
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DF
+DB
+D9
+F8
+D8
+D8
+D8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04A6
+ENCODING 1190
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+D8
+D8
+D8
+DE
+DB
+DB
+DB
+DB
+DB
+03
+0B
+06
+00
+ENDCHAR
+STARTCHAR uni04A7
+ENCODING 1191
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+D8
+D8
+D8
+FE
+DB
+DB
+DB
+03
+0B
+06
+00
+ENDCHAR
+STARTCHAR uni04A8
+ENCODING 1192
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C2
+CC
+D6
+D6
+D6
+D6
+D6
+CC
+7A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04A9
+ENCODING 1193
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C2
+CC
+D6
+D6
+CC
+7A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04AA
+ENCODING 1194
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+C0
+C0
+C2
+66
+3C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR uni04AB
+ENCODING 1195
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR uni04AC
+ENCODING 1196
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+0C
+04
+00
+00
+ENDCHAR
+STARTCHAR uni04AD
+ENCODING 1197
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+5A
+18
+18
+18
+18
+3C
+0C
+04
+00
+00
+ENDCHAR
+STARTCHAR uni04AE
+ENCODING 1198
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04AF
+ENCODING 1199
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+66
+66
+66
+3C
+18
+18
+18
+3C
+00
+ENDCHAR
+STARTCHAR uni04B0
+ENCODING 1200
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+66
+66
+3C
+18
+7E
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04B1
+ENCODING 1201
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+66
+66
+66
+3C
+18
+7E
+18
+3C
+00
+ENDCHAR
+STARTCHAR uni04B2
+ENCODING 1202
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+6C
+7C
+38
+38
+7C
+6C
+C6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04B3
+ENCODING 1203
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+6C
+38
+38
+38
+6C
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04B4
+ENCODING 1204
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F6
+66
+66
+66
+66
+66
+66
+66
+66
+7F
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04B5
+ENCODING 1205
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+F6
+66
+66
+66
+66
+66
+7F
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04B6
+ENCODING 1206
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+7E
+06
+06
+06
+07
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04B7
+ENCODING 1207
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+7E
+06
+06
+07
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04B8
+ENCODING 1208
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+D6
+D6
+7E
+16
+16
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04B9
+ENCODING 1209
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+D6
+D6
+7E
+16
+16
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04BA
+ENCODING 1210
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+C0
+C0
+FC
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04BB
+ENCODING 1211
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C0
+C0
+C0
+FC
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04BC
+ENCODING 1212
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+33
+B3
+B3
+7F
+30
+30
+30
+33
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04BD
+ENCODING 1213
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+9E
+B3
+7F
+30
+30
+33
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04BE
+ENCODING 1214
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+33
+B3
+B3
+7F
+30
+30
+30
+33
+1E
+0C
+18
+0E
+00
+ENDCHAR
+STARTCHAR uni04BF
+ENCODING 1215
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+9E
+B3
+7F
+30
+30
+33
+1E
+0C
+18
+0E
+00
+ENDCHAR
+STARTCHAR uni04C0
+ENCODING 1216
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04C1
+ENCODING 1217
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+D6
+D6
+D6
+7C
+38
+7C
+D6
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04C2
+ENCODING 1218
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+D6
+D6
+D6
+7C
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04C3
+ENCODING 1219
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E6
+06
+16
+0C
+00
+ENDCHAR
+STARTCHAR uni04C4
+ENCODING 1220
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+E6
+6C
+78
+78
+6C
+66
+E6
+06
+16
+0C
+00
+ENDCHAR
+STARTCHAR uni04C5
+ENCODING 1221
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+66
+66
+66
+66
+66
+66
+66
+66
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04C6
+ENCODING 1222
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3E
+66
+66
+66
+66
+66
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04C7
+ENCODING 1223
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C6
+06
+16
+0C
+00
+ENDCHAR
+STARTCHAR uni04C8
+ENCODING 1224
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+06
+16
+0C
+00
+ENDCHAR
+STARTCHAR uni04C9
+ENCODING 1225
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04CA
+ENCODING 1226
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+FE
+C6
+C6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04CB
+ENCODING 1227
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+7E
+06
+06
+06
+0E
+0C
+08
+00
+00
+ENDCHAR
+STARTCHAR uni04CC
+ENCODING 1228
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+7E
+06
+06
+0E
+0C
+08
+00
+00
+ENDCHAR
+STARTCHAR uni04CD
+ENCODING 1229
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+C6
+C6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04CE
+ENCODING 1230
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C7
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni04D0
+ENCODING 1232
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04D1
+ENCODING 1233
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04D2
+ENCODING 1234
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04D3
+ENCODING 1235
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04D4
+ENCODING 1236
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+6C
+CC
+CC
+FE
+CC
+CC
+CC
+CC
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04D5
+ENCODING 1237
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+76
+36
+7E
+D8
+D8
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04D6
+ENCODING 1238
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04D7
+ENCODING 1239
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04D8
+ENCODING 1240
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+06
+06
+06
+FE
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii10846
+ENCODING 1241
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+06
+FE
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04DA
+ENCODING 1242
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+7C
+C6
+06
+06
+FE
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04DB
+ENCODING 1243
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+7C
+C6
+06
+06
+FE
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04DC
+ENCODING 1244
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+D6
+D6
+D6
+7C
+38
+7C
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04DD
+ENCODING 1245
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+D6
+D6
+D6
+7C
+D6
+D6
+D6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04DE
+ENCODING 1246
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+7C
+C6
+86
+06
+3C
+06
+86
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04DF
+ENCODING 1247
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+7C
+C6
+06
+3C
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E0
+ENCODING 1248
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+06
+0C
+18
+3C
+06
+06
+86
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E1
+ENCODING 1249
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+06
+0C
+18
+3C
+06
+06
+06
+C6
+7C
+00
+ENDCHAR
+STARTCHAR uni04E2
+ENCODING 1250
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+C6
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E3
+ENCODING 1251
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E4
+ENCODING 1252
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C6
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E5
+ENCODING 1253
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+C6
+CE
+DE
+FE
+F6
+E6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E6
+ENCODING 1254
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E7
+ENCODING 1255
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E8
+ENCODING 1256
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04E9
+ENCODING 1257
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+FE
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04EA
+ENCODING 1258
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+7C
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04EB
+ENCODING 1259
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+7C
+C6
+C6
+FE
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04EC
+ENCODING 1260
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+78
+CC
+86
+06
+3E
+06
+86
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04ED
+ENCODING 1261
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+7C
+C6
+06
+3E
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04EE
+ENCODING 1262
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+C6
+C6
+C6
+C6
+7E
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04EF
+ENCODING 1263
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni04F0
+ENCODING 1264
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C6
+C6
+C6
+C6
+7E
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04F1
+ENCODING 1265
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni04F2
+ENCODING 1266
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+66
+CC
+00
+C6
+C6
+C6
+C6
+7E
+06
+06
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04F3
+ENCODING 1267
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+CC
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni04F4
+ENCODING 1268
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C6
+C6
+C6
+C6
+7E
+06
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04F5
+ENCODING 1269
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+C6
+C6
+C6
+7E
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04F8
+ENCODING 1272
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C3
+C3
+C3
+F3
+DB
+DB
+DB
+DB
+F3
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni04F9
+ENCODING 1273
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+C3
+C3
+C3
+F3
+DB
+DB
+F3
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0500
+ENCODING 1280
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+0C
+0C
+0C
+7C
+CC
+CC
+CC
+CC
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0501
+ENCODING 1281
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0502
+ENCODING 1282
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+0C
+0C
+0C
+7C
+CD
+CD
+CD
+CD
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0503
+ENCODING 1283
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CD
+CD
+CD
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0504
+ENCODING 1284
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+8C
+0C
+38
+0D
+0D
+0D
+0D
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0505
+ENCODING 1285
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+78
+CC
+0C
+39
+0D
+0D
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0506
+ENCODING 1286
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+86
+06
+3C
+06
+06
+06
+06
+07
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni0507
+ENCODING 1287
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+06
+3C
+06
+06
+07
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni0508
+ENCODING 1288
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+6C
+6C
+6C
+6C
+6D
+6D
+6D
+6D
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0509
+ENCODING 1289
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+6C
+6C
+6D
+6D
+6D
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni050A
+ENCODING 1290
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+CC
+CC
+CC
+FC
+CD
+CD
+CD
+CD
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni050B
+ENCODING 1291
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+FD
+CD
+CD
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni050C
+ENCODING 1292
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+CE
+C6
+C6
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni050D
+ENCODING 1293
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+CE
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni050E
+ENCODING 1294
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+1B
+1B
+1B
+1B
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni050F
+ENCODING 1295
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+5A
+18
+1B
+1B
+1B
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0530
+ENCODING 1328
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+64
+94
+BA
+52
+4C
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0531
+ENCODING 1329
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CF
+7B
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0532
+ENCODING 1330
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+66
+60
+60
+7E
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0533
+ENCODING 1331
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+CC
+CC
+CC
+7F
+0C
+0C
+0C
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0534
+ENCODING 1332
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+CC
+CC
+CC
+CF
+0C
+0C
+0C
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0535
+ENCODING 1333
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+7E
+60
+60
+66
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0536
+ENCODING 1334
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+66
+3E
+06
+0C
+D8
+FE
+C3
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0537
+ENCODING 1335
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+7E
+60
+60
+60
+60
+60
+60
+7C
+06
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0538
+ENCODING 1336
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+66
+66
+60
+60
+60
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0539
+ENCODING 1337
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+CF
+D6
+D6
+D6
+D6
+CC
+C0
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni053A
+ENCODING 1338
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+0C
+0C
+0C
+7F
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni053B
+ENCODING 1339
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+7C
+66
+66
+66
+66
+66
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni053C
+ENCODING 1340
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+7C
+06
+00
+00
+00
+ENDCHAR
+STARTCHAR uni053D
+ENCODING 1341
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+F6
+D6
+D6
+D6
+D6
+CC
+C0
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni053E
+ENCODING 1342
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+7F
+24
+66
+66
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni053F
+ENCODING 1343
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+66
+66
+66
+66
+66
+3E
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0540
+ENCODING 1344
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+30
+18
+0C
+18
+30
+60
+F0
+3C
+0E
+04
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0541
+ENCODING 1345
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+06
+06
+06
+6C
+D8
+6E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0542
+ENCODING 1346
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+CC
+CC
+CC
+CC
+0C
+0C
+0C
+0F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0543
+ENCODING 1347
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+30
+60
+F8
+6C
+66
+66
+66
+66
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0544
+ENCODING 1348
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CF
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0545
+ENCODING 1349
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+06
+06
+7C
+06
+06
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0546
+ENCODING 1350
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+60
+66
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0547
+ENCODING 1351
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+06
+3E
+66
+60
+60
+60
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0548
+ENCODING 1352
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0549
+ENCODING 1353
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+06
+06
+06
+6C
+38
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni054A
+ENCODING 1354
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+D6
+D6
+D6
+D6
+D6
+16
+16
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni054B
+ENCODING 1355
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+76
+1E
+0E
+0C
+D8
+FE
+C3
+00
+00
+00
+ENDCHAR
+STARTCHAR uni054C
+ENCODING 1356
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+CC
+CC
+CC
+CF
+CC
+CC
+CC
+CC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni054D
+ENCODING 1357
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+66
+66
+66
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni054E
+ENCODING 1358
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+0C
+CC
+CC
+CC
+CC
+7C
+0C
+0C
+0F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni054F
+ENCODING 1359
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+60
+30
+18
+0C
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0550
+ENCODING 1360
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+66
+66
+60
+60
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0551
+ENCODING 1361
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+3C
+66
+06
+06
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0552
+ENCODING 1362
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+7C
+66
+66
+66
+66
+63
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0553
+ENCODING 1363
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+7C
+D6
+D6
+D6
+D6
+D6
+D6
+7C
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0554
+ENCODING 1364
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+7C
+60
+60
+FE
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0555
+ENCODING 1365
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+66
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0556
+ENCODING 1366
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+D0
+D0
+D0
+7C
+16
+16
+16
+D6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0559
+ENCODING 1369
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+30
+30
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni055A
+ENCODING 1370
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+18
+18
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni055B
+ENCODING 1371
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+30
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni055C
+ENCODING 1372
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+06
+3C
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni055D
+ENCODING 1373
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+18
+0C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni055E
+ENCODING 1374
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+1C
+36
+6C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni055F
+ENCODING 1375
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+60
+3E
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0561
+ENCODING 1377
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+D6
+D6
+D6
+D6
+D6
+D6
+6A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0562
+ENCODING 1378
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+66
+66
+66
+60
+60
+7E
+60
+60
+60
+00
+ENDCHAR
+STARTCHAR uni0563
+ENCODING 1379
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+CC
+CC
+CC
+CC
+CC
+7F
+0C
+0C
+0C
+00
+ENDCHAR
+STARTCHAR uni0564
+ENCODING 1380
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+F8
+CC
+CC
+CC
+CC
+CC
+CF
+0C
+0C
+0C
+00
+ENDCHAR
+STARTCHAR uni0565
+ENCODING 1381
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+7E
+60
+60
+66
+66
+66
+66
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0566
+ENCODING 1382
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+0C
+0F
+00
+ENDCHAR
+STARTCHAR uni0567
+ENCODING 1383
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+60
+7C
+60
+60
+60
+60
+60
+78
+0C
+18
+00
+00
+ENDCHAR
+STARTCHAR uni0568
+ENCODING 1384
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+66
+66
+66
+66
+66
+66
+60
+60
+7E
+00
+ENDCHAR
+STARTCHAR uni0569
+ENCODING 1385
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FC
+C6
+C6
+CF
+D6
+D6
+CC
+C0
+C0
+C0
+00
+ENDCHAR
+STARTCHAR uni056A
+ENCODING 1386
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+0C
+0C
+7F
+CC
+CC
+CC
+CC
+CC
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni056B
+ENCODING 1387
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+60
+7C
+66
+66
+66
+66
+66
+66
+60
+60
+60
+00
+ENDCHAR
+STARTCHAR uni056C
+ENCODING 1388
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+3E
+00
+ENDCHAR
+STARTCHAR uni056D
+ENCODING 1389
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+C0
+F6
+D6
+D6
+D6
+D6
+D6
+CA
+C0
+C0
+C0
+00
+ENDCHAR
+STARTCHAR uni056E
+ENCODING 1390
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+38
+0C
+7F
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni056F
+ENCODING 1391
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+60
+66
+66
+66
+66
+66
+66
+3E
+06
+06
+06
+00
+ENDCHAR
+STARTCHAR uni0570
+ENCODING 1392
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+60
+7C
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0571
+ENCODING 1393
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+1C
+0C
+18
+3C
+64
+66
+62
+63
+3D
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0572
+ENCODING 1394
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+F8
+CC
+CC
+CC
+CC
+CC
+CC
+0C
+0C
+0F
+00
+ENDCHAR
+STARTCHAR uni0573
+ENCODING 1395
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+18
+30
+F8
+6C
+66
+66
+66
+66
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0574
+ENCODING 1396
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0F
+0C
+0C
+CC
+CC
+CC
+CC
+CC
+CC
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0575
+ENCODING 1397
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+6C
+38
+00
+ENDCHAR
+STARTCHAR uni0576
+ENCODING 1398
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+66
+66
+66
+66
+66
+66
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0577
+ENCODING 1399
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+66
+66
+66
+06
+0C
+18
+30
+60
+3E
+00
+ENDCHAR
+STARTCHAR uni0578
+ENCODING 1400
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0579
+ENCODING 1401
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+18
+18
+0C
+06
+0C
+18
+30
+60
+3E
+00
+ENDCHAR
+STARTCHAR uni057A
+ENCODING 1402
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+D6
+D6
+D6
+D6
+D6
+D6
+7E
+06
+06
+06
+00
+ENDCHAR
+STARTCHAR uni057B
+ENCODING 1403
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+66
+66
+66
+76
+1C
+18
+30
+60
+3E
+00
+ENDCHAR
+STARTCHAR uni057C
+ENCODING 1404
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+F8
+CC
+CC
+CC
+CC
+CC
+CF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni057D
+ENCODING 1405
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+66
+66
+66
+66
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni057E
+ENCODING 1406
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+0C
+0C
+CC
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+0C
+0F
+00
+ENDCHAR
+STARTCHAR uni057F
+ENCODING 1407
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+D6
+D6
+D6
+D6
+D6
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0580
+ENCODING 1408
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+66
+66
+66
+66
+66
+66
+60
+60
+60
+00
+ENDCHAR
+STARTCHAR uni0581
+ENCODING 1409
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3E
+66
+66
+66
+66
+66
+3E
+06
+66
+3C
+00
+ENDCHAR
+STARTCHAR uni0582
+ENCODING 1410
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+30
+30
+30
+30
+30
+30
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0583
+ENCODING 1411
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+DC
+D6
+D6
+D6
+D6
+D6
+76
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR uni0584
+ENCODING 1412
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+66
+66
+66
+66
+7C
+60
+FE
+60
+60
+00
+ENDCHAR
+STARTCHAR uni0585
+ENCODING 1413
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+66
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0586
+ENCODING 1414
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+D0
+D0
+7C
+16
+16
+16
+16
+D6
+7C
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR uni0587
+ENCODING 1415
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+C0
+C0
+C0
+CC
+CC
+CC
+CC
+77
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0589
+ENCODING 1417
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni058A
+ENCODING 1418
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C0
+C6
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0591
+ENCODING 1425
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+10
+38
+6C
+ENDCHAR
+STARTCHAR uni0592
+ENCODING 1426
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+00
+66
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0593
+ENCODING 1427
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+38
+10
+38
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0594
+ENCODING 1428
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+00
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0595
+ENCODING 1429
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+60
+6C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0596
+ENCODING 1430
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+18
+0C
+00
+ENDCHAR
+STARTCHAR uni0597
+ENCODING 1431
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0598
+ENCODING 1432
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+74
+D6
+5C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0599
+ENCODING 1433
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C0
+60
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni059A
+ENCODING 1434
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+03
+06
+03
+00
+ENDCHAR
+STARTCHAR uni059B
+ENCODING 1435
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+28
+18
+30
+00
+ENDCHAR
+STARTCHAR uni059C
+ENCODING 1436
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni059D
+ENCODING 1437
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+06
+04
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni059E
+ENCODING 1438
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1B
+36
+24
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni059F
+ENCODING 1439
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+44
+AA
+6C
+28
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05A0
+ENCODING 1440
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+0A
+0C
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05A1
+ENCODING 1441
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+40
+50
+E0
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05A3
+ENCODING 1443
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0C
+0C
+3C
+00
+ENDCHAR
+STARTCHAR uni05A4
+ENCODING 1444
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+30
+18
+00
+ENDCHAR
+STARTCHAR uni05A5
+ENCODING 1445
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+30
+60
+00
+ENDCHAR
+STARTCHAR uni05A6
+ENCODING 1446
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+24
+6C
+D8
+00
+ENDCHAR
+STARTCHAR uni05A7
+ENCODING 1447
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+30
+08
+30
+ENDCHAR
+STARTCHAR uni05A8
+ENCODING 1448
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05A9
+ENCODING 1449
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+40
+A0
+60
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05AA
+ENCODING 1450
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+6C
+38
+10
+10
+ENDCHAR
+STARTCHAR uni05AB
+ENCODING 1451
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+30
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05AC
+ENCODING 1452
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0C
+3C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05AD
+ENCODING 1453
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+04
+06
+03
+00
+ENDCHAR
+STARTCHAR uni05AE
+ENCODING 1454
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+48
+A8
+90
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05AF
+ENCODING 1455
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+38
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57799
+ENCODING 1456
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+00
+18
+00
+ENDCHAR
+STARTCHAR afii57801
+ENCODING 1457
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+DB
+00
+33
+00
+ENDCHAR
+STARTCHAR afii57800
+ENCODING 1458
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+F6
+00
+06
+00
+ENDCHAR
+STARTCHAR afii57802
+ENCODING 1459
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+F6
+60
+66
+00
+ENDCHAR
+STARTCHAR afii57793
+ENCODING 1460
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57794
+ENCODING 1461
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+66
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57795
+ENCODING 1462
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+66
+00
+18
+00
+ENDCHAR
+STARTCHAR afii57798
+ENCODING 1463
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+7E
+00
+00
+ENDCHAR
+STARTCHAR afii57797
+ENCODING 1464
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+7E
+18
+18
+ENDCHAR
+STARTCHAR afii57806
+ENCODING 1465
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+60
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57796
+ENCODING 1467
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+C0
+18
+03
+00
+ENDCHAR
+STARTCHAR afii57807
+ENCODING 1468
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57839
+ENCODING 1469
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+18
+18
+ENDCHAR
+STARTCHAR afii57645
+ENCODING 1470
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7E
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57841
+ENCODING 1471
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57842
+ENCODING 1472
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57804
+ENCODING 1473
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+06
+06
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57803
+ENCODING 1474
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57658
+ENCODING 1475
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05C4
+ENCODING 1476
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57664
+ENCODING 1488
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C6
+C6
+66
+76
+DC
+CC
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57665
+ENCODING 1489
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+F8
+0C
+0C
+0C
+0C
+0C
+0C
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57666
+ENCODING 1490
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+0C
+0C
+0C
+0C
+1C
+36
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57667
+ENCODING 1491
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57668
+ENCODING 1492
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+06
+06
+06
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57669
+ENCODING 1493
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57670
+ENCODING 1494
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+7E
+18
+18
+18
+0C
+0C
+18
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57671
+ENCODING 1495
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+66
+C6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57672
+ENCODING 1496
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+CC
+D6
+D6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57673
+ENCODING 1497
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+18
+18
+18
+30
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57674
+ENCODING 1498
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+06
+06
+06
+0C
+0C
+0C
+0C
+0C
+0C
+0E
+00
+ENDCHAR
+STARTCHAR afii57675
+ENCODING 1499
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+06
+06
+06
+06
+06
+06
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57676
+ENCODING 1500
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+FC
+06
+06
+06
+06
+0C
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57677
+ENCODING 1501
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+66
+C6
+C6
+C6
+C6
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57678
+ENCODING 1502
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+DC
+76
+66
+C6
+C6
+C6
+C6
+DE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57679
+ENCODING 1503
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+0C
+0C
+18
+18
+18
+18
+18
+18
+18
+1C
+00
+ENDCHAR
+STARTCHAR afii57680
+ENCODING 1504
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+0C
+0C
+0C
+0C
+0C
+0C
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57681
+ENCODING 1505
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+66
+C6
+C6
+C6
+C6
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57682
+ENCODING 1506
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+EE
+66
+66
+66
+66
+66
+2C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57683
+ENCODING 1507
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+F8
+4C
+CC
+CC
+EC
+0C
+0C
+0C
+0C
+0C
+0E
+00
+ENDCHAR
+STARTCHAR afii57684
+ENCODING 1508
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+46
+C6
+C6
+E6
+06
+06
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57685
+ENCODING 1509
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+EE
+66
+66
+6C
+78
+60
+60
+60
+60
+60
+70
+00
+ENDCHAR
+STARTCHAR afii57686
+ENCODING 1510
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+EE
+66
+66
+34
+18
+0C
+06
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57687
+ENCODING 1511
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+06
+06
+66
+64
+6C
+6E
+60
+60
+60
+60
+00
+ENDCHAR
+STARTCHAR afii57688
+ENCODING 1512
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+06
+06
+06
+06
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57689
+ENCODING 1513
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+D6
+D6
+D6
+D6
+D6
+F6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57690
+ENCODING 1514
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+66
+66
+66
+66
+66
+E6
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57716
+ENCODING 1520
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+CC
+66
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57717
+ENCODING 1521
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+CC
+66
+66
+66
+C6
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57718
+ENCODING 1522
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+CC
+66
+66
+66
+CC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05F3
+ENCODING 1523
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni05F4
+ENCODING 1524
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+CC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57388
+ENCODING 1548
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+10
+18
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57403
+ENCODING 1563
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+18
+00
+00
+00
+18
+18
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57407
+ENCODING 1567
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+22
+20
+10
+08
+08
+00
+08
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57409
+ENCODING 1569
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+24
+20
+1E
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57410
+ENCODING 1570
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+02
+3C
+40
+10
+10
+10
+10
+10
+10
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57411
+ENCODING 1571
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+20
+1C
+20
+08
+08
+08
+08
+08
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57412
+ENCODING 1572
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+1C
+20
+1C
+20
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57413
+ENCODING 1573
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+08
+08
+08
+08
+08
+00
+18
+20
+1C
+20
+00
+00
+ENDCHAR
+STARTCHAR afii57414
+ENCODING 1574
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+40
+38
+40
+07
+08
+88
+86
+81
+82
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57415
+ENCODING 1575
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+08
+08
+08
+08
+08
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57416
+ENCODING 1576
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+81
+81
+7E
+00
+00
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57417
+ENCODING 1577
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+28
+00
+00
+18
+24
+22
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57418
+ENCODING 1578
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+14
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57419
+ENCODING 1579
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57420
+ENCODING 1580
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+80
+88
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57421
+ENCODING 1581
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+80
+80
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57422
+ENCODING 1582
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+20
+00
+00
+70
+8F
+30
+40
+80
+80
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57423
+ENCODING 1583
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57424
+ENCODING 1584
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57425
+ENCODING 1585
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57426
+ENCODING 1586
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57427
+ENCODING 1587
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+01
+15
+88
+84
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57428
+ENCODING 1588
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+01
+15
+88
+84
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57429
+ENCODING 1589
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+06
+09
+31
+9E
+88
+88
+70
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57430
+ENCODING 1590
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+06
+09
+31
+9E
+88
+88
+70
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57431
+ENCODING 1591
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+20
+20
+2C
+32
+A2
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57432
+ENCODING 1592
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+20
+20
+2C
+32
+A2
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57433
+ENCODING 1593
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+80
+8C
+70
+40
+80
+80
+80
+41
+3E
+00
+00
+ENDCHAR
+STARTCHAR afii57434
+ENCODING 1594
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+40
+00
+00
+70
+80
+8C
+70
+40
+80
+80
+80
+41
+3E
+00
+00
+ENDCHAR
+STARTCHAR afii57440
+ENCODING 1600
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57441
+ENCODING 1601
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+06
+49
+85
+83
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57442
+ENCODING 1602
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0A
+00
+06
+09
+09
+47
+81
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57443
+ENCODING 1603
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+19
+21
+19
+21
+01
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57444
+ENCODING 1604
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+02
+02
+02
+02
+02
+42
+82
+82
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57445
+ENCODING 1605
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0C
+12
+12
+3C
+40
+40
+40
+40
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR afii57446
+ENCODING 1606
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+00
+41
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57470
+ENCODING 1607
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+40
+30
+4E
+49
+39
+E6
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57448
+ENCODING 1608
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57449
+ENCODING 1609
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57450
+ENCODING 1610
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+24
+00
+ENDCHAR
+STARTCHAR afii57451
+ENCODING 1611
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+30
+0C
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57452
+ENCODING 1612
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+12
+CA
+2C
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57453
+ENCODING 1613
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0C
+30
+0C
+30
+00
+00
+ENDCHAR
+STARTCHAR afii57454
+ENCODING 1614
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57455
+ENCODING 1615
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+14
+0C
+08
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57456
+ENCODING 1616
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0C
+30
+00
+00
+ENDCHAR
+STARTCHAR afii57457
+ENCODING 1617
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0A
+2A
+2C
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57458
+ENCODING 1618
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+24
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0653
+ENCODING 1619
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+01
+7E
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0654
+ENCODING 1620
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+10
+0C
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0655
+ENCODING 1621
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0C
+10
+0C
+10
+ENDCHAR
+STARTCHAR afii57392
+ENCODING 1632
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+30
+78
+30
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57393
+ENCODING 1633
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+70
+70
+38
+18
+18
+08
+08
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57394
+ENCODING 1634
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+44
+FC
+F8
+60
+30
+30
+10
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57395
+ENCODING 1635
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+4A
+FE
+F4
+60
+30
+30
+10
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57396
+ENCODING 1636
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+20
+40
+30
+10
+20
+42
+7C
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57397
+ENCODING 1637
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+2C
+44
+42
+82
+82
+FE
+7C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57398
+ENCODING 1638
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+80
+F8
+78
+08
+08
+08
+0C
+0E
+06
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57399
+ENCODING 1639
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+82
+C6
+C6
+6C
+28
+38
+10
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57400
+ENCODING 1640
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+38
+28
+6C
+C6
+C6
+82
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57401
+ENCODING 1641
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+F8
+88
+F8
+78
+08
+0C
+0E
+06
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57381
+ENCODING 1642
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+91
+92
+64
+08
+10
+26
+49
+89
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni066B
+ENCODING 1643
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+18
+18
+30
+30
+60
+60
+00
+00
+ENDCHAR
+STARTCHAR uni066C
+ENCODING 1644
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+18
+10
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii63167
+ENCODING 1645
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+38
+FE
+7C
+38
+6C
+44
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0670
+ENCODING 1648
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0671
+ENCODING 1649
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+06
+29
+5E
+00
+04
+04
+04
+04
+04
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0672
+ENCODING 1650
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+06
+28
+5E
+00
+04
+04
+04
+04
+04
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0673
+ENCODING 1651
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+04
+04
+04
+04
+04
+00
+06
+28
+5E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0674
+ENCODING 1652
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+07
+08
+07
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0675
+ENCODING 1653
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+04
+03
+14
+10
+10
+10
+10
+10
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0676
+ENCODING 1654
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+04
+03
+04
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0677
+ENCODING 1655
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+23
+54
+33
+24
+40
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0678
+ENCODING 1656
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+04
+03
+04
+00
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57511
+ENCODING 1657
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni067A
+ENCODING 1658
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+08
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni067B
+ENCODING 1659
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+81
+81
+7E
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uni067C
+ENCODING 1660
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+14
+40
+81
+81
+7E
+08
+14
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni067D
+ENCODING 1661
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+08
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57506
+ENCODING 1662
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+81
+81
+7E
+00
+00
+14
+00
+08
+00
+00
+ENDCHAR
+STARTCHAR uni067F
+ENCODING 1663
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+14
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0680
+ENCODING 1664
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+81
+81
+7E
+00
+00
+14
+00
+14
+00
+00
+ENDCHAR
+STARTCHAR uni0681
+ENCODING 1665
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+06
+08
+06
+08
+70
+8F
+30
+40
+80
+80
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0682
+ENCODING 1666
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+08
+00
+70
+8F
+30
+40
+80
+80
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0683
+ENCODING 1667
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+80
+94
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0684
+ENCODING 1668
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+88
+80
+88
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0685
+ENCODING 1669
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+70
+8F
+30
+40
+80
+80
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57507
+ENCODING 1670
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+94
+80
+88
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0687
+ENCODING 1671
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+94
+80
+94
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57512
+ENCODING 1672
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+20
+38
+28
+70
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0689
+ENCODING 1673
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+04
+02
+42
+3C
+08
+14
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni068A
+ENCODING 1674
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+04
+02
+42
+3C
+00
+00
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni068B
+ENCODING 1675
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+20
+38
+28
+70
+08
+04
+02
+42
+3C
+00
+00
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni068C
+ENCODING 1676
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni068D
+ENCODING 1677
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+04
+02
+42
+3C
+00
+00
+14
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni068E
+ENCODING 1678
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni068F
+ENCODING 1679
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+14
+00
+08
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0690
+ENCODING 1680
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+14
+00
+14
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57513
+ENCODING 1681
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0692
+ENCODING 1682
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+08
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0693
+ENCODING 1683
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+04
+02
+02
+04
+1C
+6A
+04
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0694
+ENCODING 1684
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+04
+02
+02
+04
+18
+62
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0695
+ENCODING 1685
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+04
+02
+02
+04
+18
+60
+00
+14
+08
+00
+00
+ENDCHAR
+STARTCHAR uni0696
+ENCODING 1686
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+04
+02
+12
+04
+18
+62
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0697
+ENCODING 1687
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+14
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57508
+ENCODING 1688
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0699
+ENCODING 1689
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+14
+00
+14
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni069A
+ENCODING 1690
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+00
+01
+15
+88
+88
+8A
+70
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni069B
+ENCODING 1691
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+01
+15
+88
+88
+90
+65
+00
+02
+00
+00
+00
+ENDCHAR
+STARTCHAR uni069C
+ENCODING 1692
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+04
+00
+0A
+00
+01
+15
+88
+88
+90
+65
+00
+02
+00
+00
+00
+ENDCHAR
+STARTCHAR uni069D
+ENCODING 1693
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+06
+09
+31
+9E
+88
+90
+65
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni069E
+ENCODING 1694
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+00
+0A
+00
+06
+09
+31
+9E
+88
+88
+70
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni069F
+ENCODING 1695
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+00
+2A
+20
+20
+2C
+32
+A2
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06A0
+ENCODING 1696
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+20
+00
+50
+00
+70
+80
+8C
+70
+40
+80
+80
+80
+41
+3E
+00
+00
+ENDCHAR
+STARTCHAR uni06A1
+ENCODING 1697
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+06
+49
+85
+83
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06A2
+ENCODING 1698
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+06
+49
+85
+83
+7E
+00
+02
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06A3
+ENCODING 1699
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+06
+49
+85
+83
+7E
+00
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57505
+ENCODING 1700
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+00
+0A
+00
+06
+49
+85
+83
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06A5
+ENCODING 1701
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+06
+49
+85
+83
+7E
+00
+0A
+00
+04
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06A6
+ENCODING 1702
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0A
+00
+0A
+00
+06
+49
+85
+83
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06A7
+ENCODING 1703
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+06
+09
+09
+47
+81
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06A8
+ENCODING 1704
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+00
+0A
+00
+06
+09
+09
+47
+81
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06A9
+ENCODING 1705
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+01
+02
+04
+08
+44
+82
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06AA
+ENCODING 1706
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+20
+40
+3E
+01
+81
+7E
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06AB
+ENCODING 1707
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+01
+02
+05
+0B
+48
+84
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06AC
+ENCODING 1708
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+00
+19
+21
+19
+21
+01
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06AD
+ENCODING 1709
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+00
+29
+01
+19
+21
+19
+A1
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06AE
+ENCODING 1710
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+19
+21
+19
+21
+01
+81
+7E
+00
+14
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57509
+ENCODING 1711
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+09
+12
+04
+08
+44
+82
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B0
+ENCODING 1712
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+09
+12
+05
+0B
+48
+84
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B1
+ENCODING 1713
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+A4
+09
+12
+04
+08
+44
+82
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B2
+ENCODING 1714
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+09
+12
+04
+08
+44
+82
+82
+7C
+00
+14
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B3
+ENCODING 1715
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+09
+12
+04
+08
+44
+82
+82
+7C
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B4
+ENCODING 1716
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+44
+09
+A2
+04
+08
+44
+82
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B5
+ENCODING 1717
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+14
+08
+02
+02
+02
+02
+42
+82
+82
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B6
+ENCODING 1718
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+02
+02
+02
+02
+02
+42
+82
+82
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B7
+ENCODING 1719
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+02
+2A
+02
+02
+02
+42
+82
+82
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06B8
+ENCODING 1720
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+02
+02
+02
+02
+02
+42
+82
+82
+84
+78
+00
+14
+00
+08
+00
+ENDCHAR
+STARTCHAR uni06B9
+ENCODING 1721
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+00
+00
+41
+81
+81
+81
+42
+3C
+00
+00
+04
+00
+00
+ENDCHAR
+STARTCHAR afii57514
+ENCODING 1722
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+41
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06BB
+ENCODING 1723
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+41
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06BC
+ENCODING 1724
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+00
+41
+81
+81
+81
+42
+3C
+08
+14
+08
+00
+00
+ENDCHAR
+STARTCHAR uni06BD
+ENCODING 1725
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+00
+41
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06BE
+ENCODING 1726
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+38
+4C
+52
+32
+3C
+40
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06BF
+ENCODING 1727
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+00
+70
+8F
+30
+40
+94
+80
+88
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C0
+ENCODING 1728
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+40
+38
+40
+18
+24
+22
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C1
+ENCODING 1729
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+0C
+13
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C2
+ENCODING 1730
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+40
+38
+40
+00
+0C
+13
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C3
+ENCODING 1731
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+14
+00
+00
+00
+0C
+13
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C4
+ENCODING 1732
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+12
+0E
+12
+2C
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C5
+ENCODING 1733
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+12
+0E
+02
+3C
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C6
+ENCODING 1734
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+08
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C7
+ENCODING 1735
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+28
+18
+10
+20
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C8
+ENCODING 1736
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+08
+08
+08
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06C9
+ENCODING 1737
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+14
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06CA
+ENCODING 1738
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+14
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06CB
+ENCODING 1739
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06CC
+ENCODING 1740
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06CD
+ENCODING 1741
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+20
+47
+88
+08
+86
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06CE
+ENCODING 1742
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+50
+20
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06CF
+ENCODING 1743
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06D0
+ENCODING 1744
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+82
+7C
+00
+08
+00
+08
+ENDCHAR
+STARTCHAR uni06D1
+ENCODING 1745
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+82
+7C
+00
+14
+00
+08
+ENDCHAR
+STARTCHAR afii57519
+ENCODING 1746
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+14
+60
+80
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06D3
+ENCODING 1747
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+80
+60
+80
+08
+14
+60
+80
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06D4
+ENCODING 1748
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+3C
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57534
+ENCODING 1749
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+24
+22
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06D6
+ENCODING 1750
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+40
+40
+43
+55
+7E
+80
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06D7
+ENCODING 1751
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+2A
+20
+26
+2A
+7C
+80
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06D8
+ENCODING 1752
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0E
+1C
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06D9
+ENCODING 1753
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+14
+14
+08
+14
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06DA
+ENCODING 1754
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+2C
+10
+28
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06DB
+ENCODING 1755
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06DC
+ENCODING 1756
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+15
+8A
+90
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06DD
+ENCODING 1757
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+5A
+A5
+66
+5B
+81
+81
+81
+81
+81
+81
+5A
+66
+A5
+5A
+00
+ENDCHAR
+STARTCHAR uni06DE
+ENCODING 1758
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+66
+42
+42
+81
+99
+99
+81
+42
+42
+66
+18
+00
+00
+ENDCHAR
+STARTCHAR uni06DF
+ENCODING 1759
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+1C
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E0
+ENCODING 1760
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E1
+ENCODING 1761
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+26
+08
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E2
+ENCODING 1762
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0C
+10
+10
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E3
+ENCODING 1763
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+15
+8A
+90
+60
+ENDCHAR
+STARTCHAR uni06E4
+ENCODING 1764
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+32
+2C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E5
+ENCODING 1765
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+14
+0C
+04
+08
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E6
+ENCODING 1766
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+10
+30
+40
+3E
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E7
+ENCODING 1767
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+30
+40
+3E
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E8
+ENCODING 1768
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+22
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06E9
+ENCODING 1769
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+28
+54
+AA
+92
+54
+54
+54
+54
+54
+54
+54
+82
+FE
+00
+00
+ENDCHAR
+STARTCHAR uni06EA
+ENCODING 1770
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+08
+14
+22
+14
+08
+ENDCHAR
+STARTCHAR uni06EB
+ENCODING 1771
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+14
+22
+14
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06EC
+ENCODING 1772
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+3C
+3C
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06ED
+ENCODING 1773
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0C
+0C
+10
+10
+10
+ENDCHAR
+STARTCHAR uni06F0
+ENCODING 1776
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+44
+44
+38
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F1
+ENCODING 1777
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+70
+70
+38
+18
+18
+08
+08
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F2
+ENCODING 1778
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+44
+FC
+F8
+60
+30
+30
+10
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F3
+ENCODING 1779
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+4A
+FE
+F4
+60
+30
+30
+10
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F4
+ENCODING 1780
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+4E
+F0
+FE
+7C
+30
+30
+10
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F5
+ENCODING 1781
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+38
+2C
+44
+42
+82
+92
+FE
+6C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F6
+ENCODING 1782
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+60
+7E
+3C
+30
+60
+40
+80
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F7
+ENCODING 1783
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+82
+C6
+C6
+6C
+28
+38
+10
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F8
+ENCODING 1784
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+38
+28
+6C
+C6
+C6
+82
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06F9
+ENCODING 1785
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+F8
+88
+F8
+78
+08
+0C
+0E
+06
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06FA
+ENCODING 1786
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+01
+15
+88
+88
+88
+72
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06FB
+ENCODING 1787
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+06
+09
+31
+9E
+88
+88
+72
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni06FC
+ENCODING 1788
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+40
+00
+00
+70
+80
+8C
+70
+40
+80
+88
+80
+41
+3E
+00
+00
+ENDCHAR
+STARTCHAR uni06FD
+ENCODING 1789
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+24
+20
+1E
+20
+00
+14
+14
+14
+14
+00
+00
+ENDCHAR
+STARTCHAR uni06FE
+ENCODING 1790
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0C
+12
+12
+3C
+40
+54
+54
+54
+54
+40
+00
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 4307
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+92
+92
+92
+92
+92
+4C
+30
+4C
+02
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 4311
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+92
+92
+92
+92
+92
+64
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 4314
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+54
+AA
+AA
+AA
+82
+82
+40
+30
+4C
+02
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 4317
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+92
+92
+92
+82
+82
+44
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 4326
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+92
+92
+92
+82
+82
+40
+30
+4C
+02
+00
+ENDCHAR
+STARTCHAR uni1E00
+ENCODING 7680
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+38
+6C
+38
+ENDCHAR
+STARTCHAR uni1E01
+ENCODING 7681
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+38
+6C
+38
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+FC
+66
+66
+66
+7C
+66
+66
+66
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+0C
+EC
+60
+60
+78
+6C
+66
+66
+66
+66
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E04
+ENCODING 7684
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+66
+66
+66
+66
+FC
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E05
+ENCODING 7685
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+78
+6C
+66
+66
+66
+66
+7C
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E06
+ENCODING 7686
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+66
+66
+66
+66
+FC
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E07
+ENCODING 7687
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+78
+6C
+66
+66
+66
+66
+7C
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E08
+ENCODING 7688
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+3C
+66
+C2
+C0
+C0
+C0
+C2
+66
+3C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR uni1E09
+ENCODING 7689
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+F8
+6C
+66
+66
+66
+66
+66
+6C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+60
+0C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E0C
+ENCODING 7692
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+66
+66
+66
+66
+6C
+F8
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E0D
+ENCODING 7693
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E0E
+ENCODING 7694
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+66
+66
+66
+66
+6C
+F8
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E0F
+ENCODING 7695
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E10
+ENCODING 7696
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+66
+66
+66
+66
+6C
+F8
+30
+18
+70
+00
+ENDCHAR
+STARTCHAR uni1E11
+ENCODING 7697
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+30
+18
+70
+00
+ENDCHAR
+STARTCHAR uni1E12
+ENCODING 7698
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+66
+66
+66
+66
+6C
+F8
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E13
+ENCODING 7699
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E14
+ENCODING 7700
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+7C
+00
+FE
+62
+68
+78
+68
+62
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E15
+ENCODING 7701
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+7C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E16
+ENCODING 7702
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+7C
+00
+FE
+62
+68
+78
+68
+62
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E17
+ENCODING 7703
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+7C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E18
+ENCODING 7704
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+62
+66
+FE
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E19
+ENCODING 7705
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E1A
+ENCODING 7706
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+62
+66
+FE
+00
+76
+DC
+00
+ENDCHAR
+STARTCHAR uni1E1B
+ENCODING 7707
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+76
+DC
+00
+ENDCHAR
+STARTCHAR uni1E1C
+ENCODING 7708
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR uni1E1D
+ENCODING 7709
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+18
+0C
+38
+00
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+FE
+66
+62
+68
+78
+68
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+38
+6C
+64
+F0
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E20
+ENCODING 7712
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+3C
+66
+C2
+C0
+DE
+C6
+C6
+66
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E21
+ENCODING 7713
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+76
+CC
+CC
+CC
+CC
+CC
+7C
+0C
+CC
+78
+00
+ENDCHAR
+STARTCHAR uni1E22
+ENCODING 7714
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E23
+ENCODING 7715
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0C
+E0
+60
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E24
+ENCODING 7716
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C6
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E25
+ENCODING 7717
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E26
+ENCODING 7718
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E27
+ENCODING 7719
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+E0
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E28
+ENCODING 7720
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C6
+60
+30
+E0
+00
+ENDCHAR
+STARTCHAR uni1E29
+ENCODING 7721
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+6C
+76
+66
+66
+66
+66
+E6
+30
+18
+70
+00
+ENDCHAR
+STARTCHAR uni1E2A
+ENCODING 7722
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+C6
+00
+6C
+38
+00
+ENDCHAR
+STARTCHAR uni1E2B
+ENCODING 7723
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+6C
+38
+00
+ENDCHAR
+STARTCHAR uni1E2C
+ENCODING 7724
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+76
+DC
+00
+ENDCHAR
+STARTCHAR uni1E2D
+ENCODING 7725
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+76
+DC
+00
+ENDCHAR
+STARTCHAR uni1E2E
+ENCODING 7726
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+66
+00
+3C
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E2F
+ENCODING 7727
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+66
+66
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E30
+ENCODING 7728
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+E6
+66
+66
+6C
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E31
+ENCODING 7729
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+0C
+EC
+60
+60
+66
+6C
+78
+78
+6C
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E32
+ENCODING 7730
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E6
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E33
+ENCODING 7731
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+66
+6C
+78
+78
+6C
+66
+E6
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E34
+ENCODING 7732
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E6
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E35
+ENCODING 7733
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+66
+6C
+78
+78
+6C
+66
+E6
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E36
+ENCODING 7734
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+60
+60
+60
+62
+66
+FE
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E37
+ENCODING 7735
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E38
+ENCODING 7736
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+F0
+60
+60
+60
+60
+60
+62
+66
+FE
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E39
+ENCODING 7737
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+38
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E3A
+ENCODING 7738
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+60
+60
+60
+62
+66
+FE
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E3B
+ENCODING 7739
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+7E
+00
+00
+ENDCHAR
+STARTCHAR uni1E3C
+ENCODING 7740
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+60
+60
+60
+62
+66
+FE
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E3D
+ENCODING 7741
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E3E
+ENCODING 7742
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E3F
+ENCODING 7743
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+EC
+FE
+D6
+D6
+D6
+D6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+EC
+FE
+D6
+D6
+D6
+D6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E42
+ENCODING 7746
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+C6
+C6
+C6
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E43
+ENCODING 7747
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+EC
+FE
+D6
+D6
+D6
+D6
+C6
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E44
+ENCODING 7748
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E45
+ENCODING 7749
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E46
+ENCODING 7750
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+C6
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E47
+ENCODING 7751
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E48
+ENCODING 7752
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+C6
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E49
+ENCODING 7753
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E4A
+ENCODING 7754
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+E6
+F6
+FE
+DE
+CE
+C6
+C6
+C6
+C6
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E4B
+ENCODING 7755
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+66
+66
+66
+66
+66
+66
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E4C
+ENCODING 7756
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+72
+9C
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E4D
+ENCODING 7757
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+76
+DC
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E4E
+ENCODING 7758
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+00
+72
+9C
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E4F
+ENCODING 7759
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+00
+76
+DC
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E50
+ENCODING 7760
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+7C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E51
+ENCODING 7761
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+7C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E52
+ENCODING 7762
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+7C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E53
+ENCODING 7763
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+7C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E54
+ENCODING 7764
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+FC
+66
+66
+66
+7C
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E55
+ENCODING 7765
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+DC
+66
+66
+66
+66
+66
+7C
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+FC
+66
+66
+66
+7C
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+DC
+66
+66
+66
+66
+66
+7C
+60
+60
+F0
+00
+ENDCHAR
+STARTCHAR uni1E58
+ENCODING 7768
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E59
+ENCODING 7769
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E5A
+ENCODING 7770
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+66
+E6
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E5B
+ENCODING 7771
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E5C
+ENCODING 7772
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+E6
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E5D
+ENCODING 7773
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E5E
+ENCODING 7774
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+6C
+66
+66
+66
+E6
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E5F
+ENCODING 7775
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+76
+66
+60
+60
+60
+F0
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+7C
+C6
+C6
+60
+38
+0C
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E62
+ENCODING 7778
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+60
+38
+0C
+06
+C6
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E63
+ENCODING 7779
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E64
+ENCODING 7780
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+6C
+18
+00
+7C
+C6
+C6
+70
+1C
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E65
+ENCODING 7781
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+60
+0C
+18
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E66
+ENCODING 7782
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+44
+38
+10
+7C
+C6
+C6
+70
+1C
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E67
+ENCODING 7783
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+44
+38
+10
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E68
+ENCODING 7784
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+7C
+C6
+C6
+60
+38
+0C
+C6
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E69
+ENCODING 7785
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+7C
+C6
+60
+38
+0C
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+06
+16
+30
+30
+FC
+30
+30
+30
+30
+36
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E6C
+ENCODING 7788
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E6D
+ENCODING 7789
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+30
+30
+36
+1C
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1E6E
+ENCODING 7790
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+00
+7E
+00
+00
+ENDCHAR
+STARTCHAR uni1E6F
+ENCODING 7791
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+30
+30
+36
+1C
+00
+7E
+00
+00
+ENDCHAR
+STARTCHAR uni1E70
+ENCODING 7792
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+18
+18
+18
+18
+18
+3C
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E71
+ENCODING 7793
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+30
+30
+FC
+30
+30
+30
+30
+36
+1C
+08
+1C
+36
+00
+ENDCHAR
+STARTCHAR uni1E72
+ENCODING 7794
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+6C
+6C
+00
+ENDCHAR
+STARTCHAR uni1E73
+ENCODING 7795
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+6C
+6C
+00
+ENDCHAR
+STARTCHAR uni1E74
+ENCODING 7796
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+76
+DC
+00
+ENDCHAR
+STARTCHAR uni1E75
+ENCODING 7797
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+76
+DC
+00
+ENDCHAR
+STARTCHAR uni1E76
+ENCODING 7798
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E77
+ENCODING 7799
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+10
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni1E78
+ENCODING 7800
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+72
+9C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E79
+ENCODING 7801
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+76
+DC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E7A
+ENCODING 7802
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+00
+7C
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E7B
+ENCODING 7803
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+CC
+CC
+00
+FC
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E7C
+ENCODING 7804
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+00
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E7D
+ENCODING 7805
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+66
+66
+66
+66
+66
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E7E
+ENCODING 7806
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+38
+10
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E7F
+ENCODING 7807
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+66
+66
+66
+3C
+18
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+00
+C6
+C6
+C6
+D6
+D6
+D6
+FE
+EE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+C6
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+00
+C6
+C6
+C6
+D6
+D6
+D6
+FE
+EE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+18
+00
+C6
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C6
+C6
+C6
+D6
+D6
+D6
+FE
+EE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+C6
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E86
+ENCODING 7814
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+C6
+C6
+C6
+D6
+D6
+D6
+FE
+EE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E87
+ENCODING 7815
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+C6
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E88
+ENCODING 7816
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+D6
+D6
+D6
+FE
+EE
+6C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E89
+ENCODING 7817
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+D6
+D6
+D6
+FE
+6C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E8A
+ENCODING 7818
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+C6
+C6
+6C
+7C
+38
+7C
+6C
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E8B
+ENCODING 7819
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+C6
+6C
+38
+38
+38
+6C
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E8C
+ENCODING 7820
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+C6
+C6
+6C
+7C
+38
+7C
+6C
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E8D
+ENCODING 7821
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+C6
+6C
+38
+38
+38
+6C
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E8E
+ENCODING 7822
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+00
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E8F
+ENCODING 7823
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni1E90
+ENCODING 7824
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+FE
+C6
+8C
+18
+30
+60
+C2
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E91
+ENCODING 7825
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+FE
+CC
+18
+30
+60
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E92
+ENCODING 7826
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+86
+0C
+18
+30
+60
+C2
+C6
+FE
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E93
+ENCODING 7827
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+CC
+18
+30
+60
+C6
+FE
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1E94
+ENCODING 7828
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+86
+0C
+18
+30
+60
+C2
+C6
+FE
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E95
+ENCODING 7829
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+CC
+18
+30
+60
+C6
+FE
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E96
+ENCODING 7830
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+60
+60
+6C
+76
+66
+66
+66
+66
+E6
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni1E97
+ENCODING 7831
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+6C
+00
+10
+30
+FC
+30
+30
+30
+30
+36
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E98
+ENCODING 7832
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+6C
+38
+00
+C6
+C6
+D6
+D6
+D6
+FE
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E99
+ENCODING 7833
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+6C
+38
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni1E9A
+ENCODING 7834
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+0C
+18
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1E9B
+ENCODING 7835
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+00
+38
+6C
+64
+60
+60
+60
+60
+60
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EA0
+ENCODING 7840
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+C6
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EA1
+ENCODING 7841
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EA2
+ENCODING 7842
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+0C
+18
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EA3
+ENCODING 7843
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+0C
+18
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EA4
+ENCODING 7844
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+16
+38
+6C
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EA5
+ENCODING 7845
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+16
+38
+6C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EA6
+ENCODING 7846
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C0
+68
+1C
+36
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EA7
+ENCODING 7847
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C0
+68
+1C
+36
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EA8
+ENCODING 7848
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0E
+13
+3A
+6C
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EA9
+ENCODING 7849
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0E
+13
+3A
+6C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EAA
+ENCODING 7850
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+10
+28
+54
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EAB
+ENCODING 7851
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+10
+38
+44
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EAC
+ENCODING 7852
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+6C
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EAD
+ENCODING 7853
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EAE
+ENCODING 7854
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+44
+38
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EAF
+ENCODING 7855
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+18
+44
+38
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EB0
+ENCODING 7856
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+44
+38
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EB1
+ENCODING 7857
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+30
+44
+38
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EB2
+ENCODING 7858
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+08
+54
+38
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EB3
+ENCODING 7859
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+08
+54
+38
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EB4
+ENCODING 7860
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+72
+9C
+44
+38
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EB5
+ENCODING 7861
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+72
+9C
+44
+38
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EB6
+ENCODING 7862
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+6C
+38
+00
+10
+38
+6C
+C6
+C6
+FE
+C6
+C6
+C6
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EB7
+ENCODING 7863
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+38
+00
+78
+0C
+7C
+CC
+CC
+CC
+76
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EB8
+ENCODING 7864
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+66
+62
+68
+78
+68
+60
+62
+66
+FE
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1EB9
+ENCODING 7865
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EBA
+ENCODING 7866
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+0C
+18
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EBB
+ENCODING 7867
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+0C
+18
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EBC
+ENCODING 7868
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+00
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EBD
+ENCODING 7869
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EBE
+ENCODING 7870
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+23
+76
+88
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EBF
+ENCODING 7871
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+26
+70
+D8
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EC0
+ENCODING 7872
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C4
+6E
+11
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EC1
+ENCODING 7873
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C0
+64
+0E
+1B
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EC2
+ENCODING 7874
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0E
+13
+3A
+6C
+00
+FE
+62
+68
+78
+68
+62
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EC3
+ENCODING 7875
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0E
+13
+3A
+6C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EC4
+ENCODING 7876
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+10
+38
+44
+FE
+62
+68
+78
+68
+62
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EC5
+ENCODING 7877
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+10
+38
+44
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EC6
+ENCODING 7878
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+FE
+66
+62
+68
+78
+68
+62
+66
+FE
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1EC7
+ENCODING 7879
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+7C
+C6
+FE
+C0
+C0
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EC8
+ENCODING 7880
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+0C
+18
+3C
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EC9
+ENCODING 7881
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+0C
+18
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ECA
+ENCODING 7882
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1ECB
+ENCODING 7883
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+38
+18
+18
+18
+18
+18
+3C
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1ECC
+ENCODING 7884
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1ECD
+ENCODING 7885
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1ECE
+ENCODING 7886
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+0C
+18
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ECF
+ENCODING 7887
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+0C
+18
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED0
+ENCODING 7888
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+23
+76
+88
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED1
+ENCODING 7889
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+26
+70
+D8
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED2
+ENCODING 7890
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C4
+6E
+11
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED3
+ENCODING 7891
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C0
+64
+0E
+1B
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED4
+ENCODING 7892
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0E
+13
+3A
+44
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED5
+ENCODING 7893
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0E
+13
+3A
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED6
+ENCODING 7894
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+10
+28
+44
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED7
+ENCODING 7895
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+76
+DC
+10
+38
+44
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1ED8
+ENCODING 7896
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+38
+44
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1ED9
+ENCODING 7897
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+38
+6C
+00
+7C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EDA
+ENCODING 7898
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+33
+03
+7A
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EDB
+ENCODING 7899
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1B
+33
+06
+78
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EDC
+ENCODING 7900
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+33
+03
+7A
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EDD
+ENCODING 7901
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+63
+33
+06
+78
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EDE
+ENCODING 7902
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+70
+1B
+33
+7A
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EDF
+ENCODING 7903
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+1B
+33
+06
+78
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EE0
+ENCODING 7904
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+68
+B3
+03
+7A
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EE1
+ENCODING 7905
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+68
+B3
+03
+06
+78
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EE2
+ENCODING 7906
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+03
+7A
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EE3
+ENCODING 7907
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+06
+78
+CC
+CC
+CC
+CC
+CC
+78
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EE4
+ENCODING 7908
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EE5
+ENCODING 7909
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EE6
+ENCODING 7910
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+0C
+18
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EE7
+ENCODING 7911
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+18
+30
+00
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EE8
+ENCODING 7912
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+33
+03
+CE
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EE9
+ENCODING 7913
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1B
+33
+06
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EEA
+ENCODING 7914
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+33
+03
+CE
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EEB
+ENCODING 7915
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+63
+33
+06
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EEC
+ENCODING 7916
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+70
+1B
+33
+CE
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EED
+ENCODING 7917
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+1B
+33
+06
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EEE
+ENCODING 7918
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+68
+B3
+03
+CE
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EEF
+ENCODING 7919
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+68
+B3
+03
+06
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EF0
+ENCODING 7920
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+03
+CE
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+CC
+78
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR uni1EF1
+ENCODING 7921
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+06
+CC
+CC
+CC
+CC
+CC
+CC
+76
+00
+30
+30
+00
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+18
+00
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+30
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni1EF4
+ENCODING 7924
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+18
+18
+00
+ENDCHAR
+STARTCHAR uni1EF5
+ENCODING 7925
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+C6
+C6
+C6
+C6
+7E
+0C
+18
+F6
+06
+00
+ENDCHAR
+STARTCHAR uni1EF6
+ENCODING 7926
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+0C
+18
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EF7
+ENCODING 7927
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+0C
+18
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni1EF8
+ENCODING 7928
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+3A
+5C
+00
+66
+66
+66
+3C
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1EF9
+ENCODING 7929
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+76
+DC
+00
+C6
+C6
+C6
+C6
+C6
+C6
+7E
+06
+0C
+F8
+00
+ENDCHAR
+STARTCHAR uni1F00
+ENCODING 7936
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+18
+30
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1F01
+ENCODING 7937
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+30
+18
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1F02
+ENCODING 7938
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+60
+6C
+C6
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1F03
+ENCODING 7939
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+CC
+66
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1F04
+ENCODING 7940
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+60
+66
+CC
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1F05
+ENCODING 7941
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C6
+6C
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1F06
+ENCODING 7942
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+34
+58
+0C
+18
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni1F07
+ENCODING 7943
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+34
+58
+30
+18
+00
+76
+CC
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8192
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+A4
+AA
+EA
+EA
+A6
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8193
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+A4
+EA
+AA
+AA
+A6
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8194
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+EA
+8A
+CE
+8E
+EA
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8195
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+EA
+8E
+CA
+8A
+EA
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8196
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+CA
+2E
+4A
+2A
+CA
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8197
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+AA
+AE
+EA
+2A
+2A
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8198
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+6A
+8E
+CA
+AA
+4A
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8199
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+38
+20
+30
+20
+20
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8200
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+30
+28
+30
+20
+20
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8201
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+EA
+4A
+4E
+4A
+4A
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8202
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+28
+28
+38
+28
+28
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8203
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+EA
+2A
+4E
+8E
+EE
+00
+6C
+8A
+4C
+28
+C8
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8204
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+EA
+2A
+4E
+8E
+EE
+00
+A2
+A2
+E2
+EA
+A4
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8205
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+EA
+2A
+4E
+8E
+EE
+00
+08
+08
+08
+28
+10
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8206
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+80
+80
+80
+F0
+28
+30
+28
+0A
+0E
+0E
+0A
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 8207
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+00
+C0
+A0
+C0
+A0
+20
+20
+38
+0A
+0E
+0E
+0A
+00
+FE
+00
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+9C
+D2
+BC
+92
+9C
+00
+3C
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2016
+ENCODING 8214
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscoredbl
+ENCODING 8215
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FE
+00
+FE
+00
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+30
+30
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+18
+18
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+18
+18
+30
+00
+00
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+30
+30
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+66
+CC
+CC
+CC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+66
+66
+66
+CC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING 8222
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+66
+66
+66
+CC
+00
+00
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+CC
+CC
+CC
+66
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+7E
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+7E
+18
+18
+7E
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+18
+3C
+3C
+18
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2023
+ENCODING 8227
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+20
+30
+38
+3C
+38
+30
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR onedotenleader
+ENCODING 8228
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR twodotenleader
+ENCODING 8229
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+DB
+DB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2027
+ENCODING 8231
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C0
+C6
+0C
+18
+30
+60
+C0
+36
+36
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2031
+ENCODING 8241
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C0
+C6
+0C
+18
+30
+60
+C0
+6B
+6B
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR minute
+ENCODING 8242
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR second
+ENCODING 8243
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+48
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2034
+ENCODING 8244
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+92
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2035
+ENCODING 8245
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2036
+ENCODING 8246
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+24
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2037
+ENCODING 8247
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+49
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2038
+ENCODING 8248
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+38
+6C
+C6
+00
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0C
+18
+30
+60
+30
+18
+0C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+60
+30
+18
+0C
+18
+30
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni203B
+ENCODING 8251
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+92
+44
+28
+92
+28
+44
+92
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdbl
+ENCODING 8252
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+66
+66
+66
+66
+66
+00
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni203D
+ENCODING 8253
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+C3
+DB
+1B
+1E
+1C
+18
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni203E
+ENCODING 8254
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni203F
+ENCODING 8255
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+82
+7C
+00
+00
+ENDCHAR
+STARTCHAR uni2040
+ENCODING 8256
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+7C
+82
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2041
+ENCODING 8257
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+06
+0C
+18
+38
+6C
+00
+ENDCHAR
+STARTCHAR uni2042
+ENCODING 8258
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+38
+28
+00
+00
+44
+EE
+AA
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2043
+ENCODING 8259
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+3C
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8260
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+06
+0C
+0C
+18
+18
+30
+30
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2045
+ENCODING 8261
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+30
+30
+30
+3C
+30
+30
+30
+30
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2046
+ENCODING 8262
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+0C
+0C
+0C
+3C
+0C
+0C
+0C
+0C
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2048
+ENCODING 8264
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7B
+CF
+CF
+1B
+33
+33
+33
+00
+33
+33
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2049
+ENCODING 8265
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DE
+F3
+F3
+C6
+CC
+CC
+CC
+00
+CC
+CC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni204A
+ENCODING 8266
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7E
+7E
+06
+06
+0C
+0C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni204B
+ENCODING 8267
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+DB
+DB
+DB
+DE
+D8
+D8
+D8
+D8
+D8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni204C
+ENCODING 8268
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+3E
+72
+F2
+F2
+F2
+72
+3E
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni204D
+ENCODING 8269
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+F8
+9C
+9E
+9E
+9E
+9C
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zerosuperior
+ENCODING 8304
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+D8
+D8
+D8
+D8
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR foursuperior
+ENCODING 8308
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+38
+78
+D8
+FC
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR fivesuperior
+ENCODING 8309
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+F8
+C0
+F0
+18
+D8
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sixsuperior
+ENCODING 8310
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+78
+C0
+F0
+D8
+D8
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sevensuperior
+ENCODING 8311
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+F8
+D8
+30
+30
+60
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR eightsuperior
+ENCODING 8312
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+D8
+70
+D8
+D8
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ninesuperior
+ENCODING 8313
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+D8
+D8
+78
+18
+F0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni207A
+ENCODING 8314
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+30
+FC
+30
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni207B
+ENCODING 8315
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni207C
+ENCODING 8316
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+00
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleftsuperior
+ENCODING 8317
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+60
+60
+60
+60
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenrightsuperior
+ENCODING 8318
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+60
+30
+30
+30
+30
+60
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nsuperior
+ENCODING 8319
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+B0
+D8
+D8
+D8
+D8
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zeroinferior
+ENCODING 8320
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+70
+D8
+D8
+D8
+D8
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR oneinferior
+ENCODING 8321
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+70
+30
+30
+30
+78
+00
+00
+00
+ENDCHAR
+STARTCHAR twoinferior
+ENCODING 8322
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+70
+D8
+30
+60
+C8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR threeinferior
+ENCODING 8323
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+70
+D8
+30
+18
+D8
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR fourinferior
+ENCODING 8324
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+18
+38
+78
+D8
+FC
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR fiveinferior
+ENCODING 8325
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F8
+C0
+F0
+18
+D8
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR sixinferior
+ENCODING 8326
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+78
+C0
+F0
+D8
+D8
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR seveninferior
+ENCODING 8327
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F8
+D8
+30
+30
+60
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR eightinferior
+ENCODING 8328
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+70
+D8
+70
+D8
+D8
+70
+00
+00
+00
+ENDCHAR
+STARTCHAR nineinferior
+ENCODING 8329
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+70
+D8
+D8
+78
+18
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni208A
+ENCODING 8330
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+30
+FC
+30
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni208B
+ENCODING 8331
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni208C
+ENCODING 8332
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+FC
+00
+FC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleftinferior
+ENCODING 8333
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+30
+60
+60
+60
+60
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR parenrightinferior
+ENCODING 8334
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+60
+30
+30
+30
+30
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni208F
+ENCODING 8335
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+B0
+D8
+D8
+D8
+D8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20A0
+ENCODING 8352
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+C0
+CF
+CC
+CC
+7F
+0C
+0C
+0F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR colonmonetary
+ENCODING 8353
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+04
+7C
+CE
+C8
+C8
+D0
+D0
+D0
+E0
+E6
+7C
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR uni20A2
+ENCODING 8354
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C0
+C0
+D6
+D8
+D8
+D8
+DE
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR franc
+ENCODING 8355
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+C0
+C0
+C0
+F0
+CD
+CE
+CC
+CC
+CC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR lira
+ENCODING 8356
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+60
+F8
+60
+F8
+60
+60
+E6
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20A5
+ENCODING 8357
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+02
+EC
+D6
+DE
+D6
+D6
+F6
+D6
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20A6
+ENCODING 8358
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+66
+76
+FF
+76
+6E
+FF
+6E
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR peseta
+ENCODING 8359
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+7C
+62
+66
+6F
+66
+66
+F3
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20A8
+ENCODING 8360
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+CC
+CC
+CC
+F8
+E0
+F3
+D6
+DB
+CE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20A9
+ENCODING 8361
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+81
+81
+81
+5A
+FF
+5A
+FF
+24
+24
+24
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57636
+ENCODING 8362
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+F2
+8A
+AA
+AA
+AA
+AA
+A2
+BC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dong
+ENCODING 8363
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+3E
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+7C
+00
+00
+ENDCHAR
+STARTCHAR Euro
+ENCODING 8364
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+36
+60
+FC
+60
+F8
+60
+60
+36
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20AD
+ENCODING 8365
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+6C
+78
+FE
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20AE
+ENCODING 8366
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+7E
+5A
+18
+1E
+78
+1E
+78
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni20AF
+ENCODING 8367
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+7C
+B6
+36
+33
+33
+33
+63
+66
+F6
+DC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2100
+ENCODING 8448
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+D0
+D2
+D6
+7C
+18
+30
+6E
+D8
+98
+18
+0E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2101
+ENCODING 8449
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+D0
+D2
+D6
+7C
+18
+30
+6E
+D8
+8C
+06
+1C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2102
+ENCODING 8450
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+62
+A0
+A0
+A0
+A0
+A0
+A0
+62
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2103
+ENCODING 8451
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+4E
+B9
+58
+18
+18
+18
+18
+18
+19
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2104
+ENCODING 8452
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+7C
+DA
+D8
+D8
+DA
+7C
+19
+3F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii61248
+ENCODING 8453
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+C0
+C2
+C6
+7C
+18
+30
+6E
+DB
+9B
+1B
+0E
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2106
+ENCODING 8454
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+70
+C0
+C2
+C6
+7C
+18
+30
+7B
+DB
+9B
+1B
+0D
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2107
+ENCODING 8455
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C2
+C0
+78
+C0
+C0
+C2
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2108
+ENCODING 8456
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+86
+26
+3E
+26
+06
+86
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2109
+ENCODING 8457
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7F
+B9
+58
+1A
+1E
+1A
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni210A
+ENCODING 8458
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+1A
+66
+46
+87
+8C
+8C
+7C
+98
+98
+70
+00
+ENDCHAR
+STARTCHAR uni210B
+ENCODING 8459
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+52
+B5
+15
+16
+2C
+34
+68
+A9
+AA
+4C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni210C
+ENCODING 8460
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+48
+B0
+80
+48
+7C
+66
+26
+26
+A6
+46
+06
+34
+48
+00
+ENDCHAR
+STARTCHAR uni210D
+ENCODING 8461
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E2
+A2
+A2
+A2
+BE
+A2
+A2
+A2
+A2
+E2
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni210E
+ENCODING 8462
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+36
+3B
+3B
+33
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni210F
+ENCODING 8463
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+1E
+18
+76
+3B
+3B
+33
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2110
+ENCODING 8464
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+33
+4E
+06
+06
+0C
+0C
+1F
+6C
+88
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ifraktur
+ENCODING 8465
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+71
+8E
+04
+0C
+06
+03
+63
+C3
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2112
+ENCODING 8466
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+46
+49
+39
+1E
+18
+30
+70
+B1
+BA
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii61289
+ENCODING 8467
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+19
+31
+32
+64
+68
+70
+E1
+66
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2114
+ENCODING 8468
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D8
+FF
+D8
+DE
+DB
+DB
+DB
+DB
+DB
+DE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2115
+ENCODING 8469
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E2
+A2
+B2
+B2
+AA
+AA
+A6
+A6
+A2
+E2
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR afii61352
+ENCODING 8470
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+CC
+CF
+ED
+FF
+FC
+DF
+CC
+CC
+CC
+CC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2117
+ENCODING 8471
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+B9
+A5
+A5
+B9
+A1
+A1
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR weierstrass
+ENCODING 8472
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+40
+8E
+93
+A3
+63
+4B
+6A
+A4
+B0
+B0
+60
+00
+ENDCHAR
+STARTCHAR uni2119
+ENCODING 8473
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+A2
+A2
+A2
+A2
+BC
+A0
+A0
+A0
+E0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni211A
+ENCODING 8474
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+A2
+A2
+A2
+A2
+A2
+A2
+AA
+A6
+7E
+01
+00
+00
+00
+ENDCHAR
+STARTCHAR uni211B
+ENCODING 8475
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+4D
+4D
+19
+1E
+1C
+34
+34
+B5
+62
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Rfraktur
+ENCODING 8476
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+58
+A6
+A3
+6C
+B8
+26
+26
+26
+A7
+C2
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni211D
+ENCODING 8477
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+A2
+A2
+A2
+A2
+BC
+B0
+A8
+A4
+E2
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR prescription
+ENCODING 8478
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FC
+66
+66
+66
+7C
+6C
+6D
+67
+66
+EE
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uni211F
+ENCODING 8479
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+0C
+FC
+C6
+C6
+C6
+FC
+D8
+DC
+DC
+E6
+E6
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2120
+ENCODING 8480
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+71
+DB
+35
+D1
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2121
+ENCODING 8481
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FE
+52
+5A
+52
+5F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F1
+5B
+55
+51
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2123
+ENCODING 8483
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+18
+CE
+D6
+D6
+D6
+D6
+D6
+E6
+6C
+38
+50
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2124
+ENCODING 8484
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+0A
+14
+14
+28
+28
+50
+50
+A0
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2125
+ENCODING 8485
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+9C
+30
+FE
+0C
+18
+38
+0C
+06
+06
+C6
+C6
+7C
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 8486
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+6C
+6C
+6C
+EE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2127
+ENCODING 8487
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+EE
+6C
+6C
+6C
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2128
+ENCODING 8488
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+26
+03
+13
+0C
+13
+03
+03
+66
+98
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2129
+ENCODING 8489
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+18
+18
+18
+18
+1C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni212A
+ENCODING 8490
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E6
+66
+66
+6C
+78
+78
+6C
+66
+66
+E6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni212B
+ENCODING 8491
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+6C
+38
+10
+38
+38
+6C
+6C
+C6
+FE
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni212C
+ENCODING 8492
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+2D
+2D
+1A
+1E
+1B
+31
+31
+B2
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni212D
+ENCODING 8493
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+14
+6B
+C8
+CC
+C6
+C6
+CC
+C0
+63
+1C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR estimated
+ENCODING 8494
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+66
+E7
+FF
+E0
+67
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni212F
+ENCODING 8495
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+1C
+26
+44
+F8
+C0
+C8
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2130
+ENCODING 8496
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+4C
+52
+3C
+10
+3C
+60
+C0
+C3
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2131
+ENCODING 8497
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+73
+CE
+18
+3A
+5C
+18
+30
+30
+B0
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2132
+ENCODING 8498
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+0C
+0C
+0C
+2C
+3C
+2C
+8C
+CC
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2133
+ENCODING 8499
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+12
+12
+12
+16
+36
+3E
+3A
+5A
+52
+91
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2134
+ENCODING 8500
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+1C
+26
+46
+C6
+C4
+C8
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR aleph
+ENCODING 8501
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+C6
+E7
+7A
+38
+5C
+CE
+E7
+63
+E2
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2136
+ENCODING 8502
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+80
+FC
+7E
+06
+06
+06
+06
+0C
+7E
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2137
+ENCODING 8503
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+40
+78
+3C
+0C
+0C
+0C
+0C
+1E
+7E
+F2
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2138
+ENCODING 8504
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+80
+FE
+7E
+0C
+0C
+0C
+0C
+0C
+1C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2139
+ENCODING 8505
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+38
+00
+78
+38
+38
+38
+38
+38
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni213A
+ENCODING 8506
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7D
+FF
+83
+86
+82
+FE
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR onethird
+ENCODING 8531
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+C2
+C6
+CC
+18
+30
+60
+DC
+86
+1C
+06
+1C
+00
+00
+ENDCHAR
+STARTCHAR twothirds
+ENCODING 8532
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+E0
+30
+62
+C6
+FC
+18
+30
+60
+DC
+86
+1C
+06
+1C
+00
+00
+ENDCHAR
+STARTCHAR uni2155
+ENCODING 8533
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+C2
+C6
+CC
+18
+30
+60
+DE
+98
+1C
+06
+1C
+00
+00
+ENDCHAR
+STARTCHAR uni2156
+ENCODING 8534
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+E0
+30
+62
+C6
+FC
+18
+30
+60
+DE
+98
+1C
+06
+1C
+00
+00
+ENDCHAR
+STARTCHAR uni2157
+ENCODING 8535
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+E0
+30
+62
+36
+EC
+18
+30
+60
+DE
+98
+1C
+06
+1C
+00
+00
+ENDCHAR
+STARTCHAR uni2158
+ENCODING 8536
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+70
+B2
+F6
+3C
+18
+30
+60
+DE
+98
+1C
+06
+1C
+00
+00
+ENDCHAR
+STARTCHAR uni2159
+ENCODING 8537
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+C2
+C6
+CC
+18
+30
+60
+DC
+B0
+3C
+36
+1C
+00
+00
+ENDCHAR
+STARTCHAR uni215A
+ENCODING 8538
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+F0
+C0
+E2
+36
+EC
+18
+30
+60
+DC
+B0
+3C
+36
+1C
+00
+00
+ENDCHAR
+STARTCHAR oneeighth
+ENCODING 8539
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+C2
+C6
+CC
+18
+30
+60
+DC
+B6
+1C
+36
+1C
+00
+00
+ENDCHAR
+STARTCHAR threeeighths
+ENCODING 8540
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+E0
+30
+62
+36
+EC
+18
+30
+60
+DC
+B6
+1C
+36
+1C
+00
+00
+ENDCHAR
+STARTCHAR fiveeighths
+ENCODING 8541
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+F0
+80
+E2
+36
+EC
+18
+30
+60
+DC
+B6
+1C
+36
+1C
+00
+00
+ENDCHAR
+STARTCHAR seveneighths
+ENCODING 8542
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+F0
+30
+62
+66
+6C
+18
+30
+60
+DC
+B6
+1C
+36
+1C
+00
+00
+ENDCHAR
+STARTCHAR uni215F
+ENCODING 8543
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+C2
+C6
+CC
+18
+30
+60
+C0
+80
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2160
+ENCODING 8544
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2161
+ENCODING 8545
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2162
+ENCODING 8546
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2163
+ENCODING 8547
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+CE
+CE
+C4
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2164
+ENCODING 8548
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2165
+ENCODING 8549
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+73
+73
+23
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2166
+ENCODING 8550
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+95
+95
+95
+95
+95
+95
+95
+65
+65
+65
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2167
+ENCODING 8551
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+B5
+B5
+B5
+B5
+B5
+B5
+55
+55
+55
+55
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2168
+ENCODING 8552
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+DB
+CE
+CE
+CE
+DB
+DB
+DB
+DB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2169
+ENCODING 8553
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+6C
+7C
+38
+38
+7C
+6C
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni216A
+ENCODING 8554
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+DB
+73
+73
+73
+DB
+DB
+DB
+DB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni216B
+ENCODING 8555
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+95
+95
+95
+65
+65
+65
+95
+95
+95
+95
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni216C
+ENCODING 8556
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+60
+60
+60
+60
+60
+60
+62
+66
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni216D
+ENCODING 8557
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+C2
+C0
+C0
+C0
+C0
+C2
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni216E
+ENCODING 8558
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+6C
+66
+66
+66
+66
+66
+66
+6C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni216F
+ENCODING 8559
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+EE
+FE
+FE
+D6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2170
+ENCODING 8560
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2171
+ENCODING 8561
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+00
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2172
+ENCODING 8562
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+DB
+DB
+00
+DB
+DB
+DB
+DB
+DB
+DB
+DB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2173
+ENCODING 8563
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+00
+DB
+DB
+DB
+DB
+DB
+CE
+C4
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2174
+ENCODING 8564
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+66
+66
+66
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2175
+ENCODING 8565
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+00
+DB
+DB
+DB
+DB
+DB
+73
+23
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2176
+ENCODING 8566
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+05
+05
+00
+95
+95
+95
+95
+95
+65
+65
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2177
+ENCODING 8567
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+15
+15
+00
+B5
+B5
+B5
+B5
+55
+55
+55
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2178
+ENCODING 8568
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+00
+DB
+DB
+CE
+CE
+CE
+DB
+DB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2179
+ENCODING 8569
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+6C
+38
+38
+38
+6C
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni217A
+ENCODING 8570
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+00
+DB
+DB
+73
+73
+73
+DB
+DB
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni217B
+ENCODING 8571
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+05
+05
+00
+95
+95
+65
+65
+95
+95
+95
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni217C
+ENCODING 8572
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+18
+18
+18
+18
+18
+18
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni217D
+ENCODING 8573
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+C6
+C0
+C0
+C0
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni217E
+ENCODING 8574
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+0C
+0C
+3C
+6C
+CC
+CC
+CC
+CC
+76
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni217F
+ENCODING 8575
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+EC
+FE
+D6
+D6
+D6
+D6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2180
+ENCODING 8576
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+5A
+DB
+DB
+DB
+DB
+DB
+DB
+5A
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2181
+ENCODING 8577
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+CC
+E6
+D6
+D6
+D6
+D6
+E6
+CC
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2182
+ENCODING 8578
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+5A
+99
+BD
+DB
+DB
+BD
+99
+5A
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2183
+ENCODING 8579
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+CC
+86
+06
+06
+06
+06
+86
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowleft
+ENCODING 8592
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+30
+60
+FF
+60
+30
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowup
+ENCODING 8593
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+7E
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowright
+ENCODING 8594
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+06
+FF
+06
+0C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdown
+ENCODING 8595
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+18
+18
+18
+7E
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowboth
+ENCODING 8596
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+24
+66
+FF
+66
+24
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowupdn
+ENCODING 8597
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+7E
+18
+18
+18
+7E
+3C
+18
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2196
+ENCODING 8598
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+F0
+E0
+B0
+18
+0C
+06
+03
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2197
+ENCODING 8599
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+0F
+07
+0D
+18
+30
+60
+C0
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2198
+ENCODING 8600
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C0
+60
+30
+18
+0D
+07
+0F
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2199
+ENCODING 8601
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+03
+06
+0C
+18
+B0
+E0
+F0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni219A
+ENCODING 8602
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+32
+62
+FF
+64
+34
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni219B
+ENCODING 8603
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+2C
+26
+FF
+46
+4C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni219C
+ENCODING 8604
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+E0
+CE
+BB
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni219D
+ENCODING 8605
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+07
+73
+DD
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni219E
+ENCODING 8606
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+36
+6C
+FF
+6C
+36
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni219F
+ENCODING 8607
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+7E
+18
+3C
+7E
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A0
+ENCODING 8608
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+36
+FF
+36
+6C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A1
+ENCODING 8609
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+7E
+3C
+18
+7E
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A2
+ENCODING 8610
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+33
+66
+FC
+66
+33
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A3
+ENCODING 8611
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+66
+3F
+66
+CC
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A4
+ENCODING 8612
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+33
+63
+FF
+63
+33
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A5
+ENCODING 8613
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+7E
+18
+18
+18
+18
+18
+18
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A6
+ENCODING 8614
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+CC
+C6
+FF
+C6
+CC
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A7
+ENCODING 8615
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+18
+18
+18
+18
+18
+18
+7E
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowupdnbse
+ENCODING 8616
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+7E
+18
+18
+18
+7E
+3C
+18
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21A9
+ENCODING 8617
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+06
+33
+63
+FE
+60
+30
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21AA
+ENCODING 8618
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+60
+CC
+C6
+7F
+06
+0C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21AB
+ENCODING 8619
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+06
+3B
+6B
+FE
+68
+30
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21AC
+ENCODING 8620
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+60
+DC
+D6
+7F
+16
+0C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21AD
+ENCODING 8621
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+24
+5A
+FF
+66
+24
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21AE
+ENCODING 8622
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+2C
+6E
+FF
+76
+34
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21AF
+ENCODING 8623
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+30
+60
+63
+FF
+C6
+16
+1C
+1C
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B0
+ENCODING 8624
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+30
+60
+FE
+66
+36
+06
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B1
+ENCODING 8625
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+0C
+FE
+CC
+D8
+C0
+C0
+C0
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B2
+ENCODING 8626
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+06
+06
+06
+06
+36
+66
+FE
+60
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B3
+ENCODING 8627
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C0
+C0
+C0
+C0
+D8
+CC
+FE
+0C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B4
+ENCODING 8628
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FC
+0C
+0C
+3F
+1E
+0C
+00
+00
+00
+ENDCHAR
+STARTCHAR carriagereturn
+ENCODING 8629
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+06
+36
+66
+FE
+60
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B6
+ENCODING 8630
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+1E
+33
+33
+33
+30
+FC
+78
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B7
+ENCODING 8631
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+78
+CC
+CC
+CC
+0C
+3F
+1E
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B8
+ENCODING 8632
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+00
+F0
+E0
+B0
+18
+0C
+06
+03
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21B9
+ENCODING 8633
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+98
+B0
+FF
+B0
+98
+19
+0D
+FF
+0D
+19
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21BA
+ENCODING 8634
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+1E
+1C
+16
+03
+C3
+C3
+C3
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21BB
+ENCODING 8635
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+78
+38
+68
+C0
+C3
+C3
+C3
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21BC
+ENCODING 8636
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+30
+60
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21BD
+ENCODING 8637
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+60
+30
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21BE
+ENCODING 8638
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+1C
+1E
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21BF
+ENCODING 8639
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+38
+78
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C0
+ENCODING 8640
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+06
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C1
+ENCODING 8641
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+06
+0C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C2
+ENCODING 8642
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+18
+18
+18
+1E
+1C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C3
+ENCODING 8643
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+18
+18
+18
+78
+38
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C4
+ENCODING 8644
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+06
+FF
+06
+0C
+30
+60
+FF
+60
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C5
+ENCODING 8645
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+2E
+3F
+24
+24
+24
+24
+FC
+74
+24
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C6
+ENCODING 8646
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+60
+FF
+60
+30
+0C
+06
+FF
+06
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C7
+ENCODING 8647
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+60
+FE
+60
+30
+00
+30
+60
+FE
+60
+30
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C8
+ENCODING 8648
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+7E
+FF
+24
+24
+24
+24
+24
+24
+24
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21C9
+ENCODING 8649
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+0C
+FE
+0C
+18
+00
+18
+0C
+FE
+0C
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21CA
+ENCODING 8650
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+24
+24
+24
+24
+24
+24
+FF
+7E
+24
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21CB
+ENCODING 8651
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+30
+60
+FF
+00
+FF
+06
+0C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21CC
+ENCODING 8652
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0C
+06
+FF
+00
+FF
+60
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21CD
+ENCODING 8653
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+22
+7F
+C4
+7F
+24
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21CE
+ENCODING 8654
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+2C
+7E
+CB
+7E
+34
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21CF
+ENCODING 8655
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+24
+FE
+23
+FE
+44
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdblleft
+ENCODING 8656
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+20
+7F
+C0
+7F
+20
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdblup
+ENCODING 8657
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+7C
+EE
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdblright
+ENCODING 8658
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+04
+FE
+03
+FE
+04
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdbldown
+ENCODING 8659
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+EE
+7C
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdblboth
+ENCODING 8660
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+24
+7E
+C3
+7E
+24
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21D5
+ENCODING 8661
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+7C
+EE
+6C
+6C
+6C
+6C
+EE
+7C
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21D6
+ENCODING 8662
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+F0
+E0
+B0
+D8
+EC
+B6
+1B
+0C
+04
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21D7
+ENCODING 8663
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+0F
+07
+0D
+1B
+37
+6D
+D8
+30
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21D8
+ENCODING 8664
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+20
+30
+D8
+6D
+37
+1B
+0D
+07
+0F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21D9
+ENCODING 8665
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+0C
+1B
+B6
+EC
+D8
+B0
+E0
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21DA
+ENCODING 8666
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+3F
+60
+FF
+60
+3F
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21DB
+ENCODING 8667
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+FC
+06
+FF
+06
+FC
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21DC
+ENCODING 8668
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+30
+6A
+FF
+65
+30
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21DD
+ENCODING 8669
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+A6
+FF
+56
+0C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21DE
+ENCODING 8670
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+7E
+18
+18
+3C
+18
+3C
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21DF
+ENCODING 8671
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+3C
+18
+3C
+18
+18
+7E
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E0
+ENCODING 8672
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+30
+60
+D5
+60
+30
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E1
+ENCODING 8673
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+66
+18
+00
+18
+00
+18
+00
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E2
+ENCODING 8674
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+06
+AB
+06
+0C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E3
+ENCODING 8675
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+00
+18
+00
+18
+00
+18
+66
+3C
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E4
+ENCODING 8676
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+98
+B0
+FF
+B0
+98
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E5
+ENCODING 8677
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+19
+0D
+FF
+0D
+19
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E6
+ENCODING 8678
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+3F
+41
+81
+41
+3F
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E7
+ENCODING 8679
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+44
+C6
+44
+44
+44
+44
+44
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E8
+ENCODING 8680
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+FC
+82
+81
+82
+FC
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21E9
+ENCODING 8681
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+44
+44
+44
+44
+44
+C6
+44
+28
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21EA
+ENCODING 8682
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+44
+C6
+44
+44
+7C
+00
+7C
+44
+7C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21EB
+ENCODING 8683
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+44
+C6
+44
+44
+44
+C6
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21EC
+ENCODING 8684
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+7C
+C6
+44
+44
+44
+C6
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21ED
+ENCODING 8685
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+54
+D6
+54
+54
+54
+D6
+92
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21EE
+ENCODING 8686
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+28
+54
+EE
+44
+C6
+44
+44
+44
+44
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21EF
+ENCODING 8687
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+28
+54
+EE
+44
+C6
+44
+44
+C6
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21F0
+ENCODING 8688
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+E8
+BC
+82
+81
+82
+BC
+E8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21F1
+ENCODING 8689
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+80
+BC
+B8
+AC
+86
+83
+81
+80
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21F2
+ENCODING 8690
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+01
+81
+C1
+61
+35
+1D
+3D
+01
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni21F3
+ENCODING 8691
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+44
+C6
+44
+44
+44
+C6
+44
+28
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR universal
+ENCODING 8704
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+FE
+C6
+6C
+6C
+38
+38
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2201
+ENCODING 8705
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+66
+60
+60
+60
+60
+60
+66
+3C
+00
+00
+ENDCHAR
+STARTCHAR partialdiff
+ENCODING 8706
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+06
+06
+3E
+66
+C6
+C6
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR existential
+ENCODING 8707
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+06
+06
+06
+7E
+06
+06
+06
+06
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2204
+ENCODING 8708
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+FE
+16
+16
+16
+7E
+16
+26
+26
+26
+FE
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR emptyset
+ENCODING 8709
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+3E
+66
+CF
+DB
+DB
+F3
+66
+7C
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Delta
+ENCODING 8710
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+38
+38
+6C
+6C
+C6
+C6
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR gradient
+ENCODING 8711
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+C6
+C6
+6C
+6C
+38
+38
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR element
+ENCODING 8712
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+3E
+60
+C0
+C0
+FE
+C0
+C0
+60
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR notelement
+ENCODING 8713
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+3E
+64
+C8
+C8
+FE
+C8
+D0
+70
+3E
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni220A
+ENCODING 8714
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+3E
+60
+C0
+FE
+C0
+60
+3E
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR suchthat
+ENCODING 8715
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+F8
+0C
+06
+06
+FE
+06
+06
+0C
+F8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni220C
+ENCODING 8716
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+F8
+1C
+16
+26
+FE
+26
+26
+4C
+F8
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR uni220D
+ENCODING 8717
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+F8
+0C
+06
+FE
+06
+0C
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni220E
+ENCODING 8718
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+7E
+7E
+7E
+7E
+7E
+7E
+7E
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR product
+ENCODING 8719
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+66
+66
+66
+66
+66
+66
+66
+66
+66
+66
+E7
+00
+00
+ENDCHAR
+STARTCHAR uni2210
+ENCODING 8720
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E7
+66
+66
+66
+66
+66
+66
+66
+66
+66
+66
+FF
+00
+00
+ENDCHAR
+STARTCHAR summation
+ENCODING 8721
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+C1
+60
+30
+18
+0C
+0C
+18
+30
+60
+C1
+FF
+00
+00
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2213
+ENCODING 8723
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+7E
+00
+18
+18
+7E
+18
+18
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2214
+ENCODING 8724
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+18
+00
+18
+18
+7E
+18
+18
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+06
+06
+0C
+0C
+18
+18
+30
+30
+60
+60
+C0
+C0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2216
+ENCODING 8726
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+C0
+60
+60
+30
+30
+18
+18
+0C
+0C
+06
+06
+00
+00
+00
+ENDCHAR
+STARTCHAR asteriskmath
+ENCODING 8727
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+24
+18
+7E
+18
+24
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2218
+ENCODING 8728
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+24
+24
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+3C
+3C
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR radical
+ENCODING 8730
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+06
+06
+06
+0C
+CC
+6C
+38
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni221B
+ENCODING 8731
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E3
+33
+66
+36
+E6
+0C
+CC
+6C
+38
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni221C
+ENCODING 8732
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+33
+73
+B6
+F6
+36
+0C
+CC
+6C
+38
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR proportional
+ENCODING 8733
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+D8
+D8
+6E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR infinity
+ENCODING 8734
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+DB
+DB
+6E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR orthogonal
+ENCODING 8735
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+C0
+C0
+C0
+C0
+C0
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR angle
+ENCODING 8736
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+02
+06
+0C
+18
+30
+60
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2221
+ENCODING 8737
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+02
+16
+0C
+1C
+34
+62
+FF
+02
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2222
+ENCODING 8738
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+0E
+38
+E8
+38
+0E
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2223
+ENCODING 8739
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2224
+ENCODING 8740
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+1A
+1C
+38
+58
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2225
+ENCODING 8741
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2226
+ENCODING 8742
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6C
+6C
+6C
+6E
+7C
+EC
+6C
+6C
+6C
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR logicaland
+ENCODING 8743
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+10
+38
+38
+6C
+6C
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR logicalor
+ENCODING 8744
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C6
+C6
+6C
+6C
+38
+38
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR intersection
+ENCODING 8745
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+7C
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR union
+ENCODING 8746
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR integral
+ENCODING 8747
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+1A
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+58
+30
+00
+00
+ENDCHAR
+STARTCHAR uni222C
+ENCODING 8748
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+33
+66
+66
+66
+66
+66
+66
+66
+66
+66
+66
+66
+66
+CC
+00
+00
+ENDCHAR
+STARTCHAR uni222D
+ENCODING 8749
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+2A
+54
+54
+54
+54
+54
+54
+54
+54
+54
+54
+54
+54
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni222E
+ENCODING 8750
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+1A
+18
+18
+3C
+5A
+99
+99
+5A
+3C
+18
+18
+58
+30
+00
+00
+ENDCHAR
+STARTCHAR uni222F
+ENCODING 8751
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+33
+66
+66
+66
+7E
+E7
+E7
+E7
+E7
+7E
+66
+66
+66
+CC
+00
+00
+ENDCHAR
+STARTCHAR uni2230
+ENCODING 8752
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+2A
+54
+54
+54
+7C
+D6
+D6
+D6
+D6
+7C
+54
+54
+54
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni2231
+ENCODING 8753
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+34
+30
+30
+38
+35
+33
+37
+30
+30
+30
+30
+B0
+60
+00
+00
+ENDCHAR
+STARTCHAR uni2232
+ENCODING 8754
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+1A
+18
+18
+3C
+5A
+FA
+5A
+5A
+3C
+18
+18
+58
+30
+00
+00
+ENDCHAR
+STARTCHAR uni2233
+ENCODING 8755
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+1A
+18
+18
+3C
+5A
+5F
+5A
+5A
+3C
+18
+18
+58
+30
+00
+00
+ENDCHAR
+STARTCHAR therefore
+ENCODING 8756
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2235
+ENCODING 8757
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+00
+00
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2236
+ENCODING 8758
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2237
+ENCODING 8759
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+66
+66
+00
+00
+00
+66
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2238
+ENCODING 8760
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+18
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2239
+ENCODING 8761
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+03
+03
+00
+FC
+00
+03
+03
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni223A
+ENCODING 8762
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+66
+66
+00
+7E
+00
+66
+66
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni223B
+ENCODING 8763
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+18
+00
+76
+DC
+00
+30
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR similar
+ENCODING 8764
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+76
+DC
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni223D
+ENCODING 8765
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+DC
+76
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni223E
+ENCODING 8766
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+72
+DB
+DB
+4E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni223F
+ENCODING 8767
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+D8
+DB
+DB
+1B
+0E
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2240
+ENCODING 8768
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+1C
+30
+30
+30
+18
+0C
+0C
+0C
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2241
+ENCODING 8769
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+08
+10
+76
+DC
+10
+20
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2242
+ENCODING 8770
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+00
+76
+DC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2243
+ENCODING 8771
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+DC
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2244
+ENCODING 8772
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+08
+76
+DC
+10
+FE
+20
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR congruent
+ENCODING 8773
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+76
+DC
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2246
+ENCODING 8774
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+76
+DC
+08
+FE
+10
+FE
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2247
+ENCODING 8775
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+08
+76
+DC
+10
+FE
+20
+FE
+40
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR approxequal
+ENCODING 8776
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+76
+DC
+00
+76
+DC
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2249
+ENCODING 8777
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+08
+76
+DC
+10
+76
+DC
+20
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni224A
+ENCODING 8778
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+76
+DC
+00
+76
+DC
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni224B
+ENCODING 8779
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+76
+DC
+00
+76
+DC
+00
+76
+DC
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni224C
+ENCODING 8780
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+DC
+76
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni224D
+ENCODING 8781
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C6
+7C
+00
+7C
+C6
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni224E
+ENCODING 8782
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+66
+00
+00
+66
+18
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni224F
+ENCODING 8783
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+66
+00
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2250
+ENCODING 8784
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+7E
+00
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2251
+ENCODING 8785
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+7E
+00
+00
+7E
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2252
+ENCODING 8786
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+60
+00
+7E
+00
+00
+7E
+00
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2253
+ENCODING 8787
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+06
+00
+7E
+00
+00
+7E
+00
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2254
+ENCODING 8788
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C0
+DF
+00
+00
+DF
+C0
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2255
+ENCODING 8789
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+03
+FB
+00
+00
+FB
+03
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2256
+ENCODING 8790
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FE
+28
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2257
+ENCODING 8791
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+10
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2258
+ENCODING 8792
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+38
+44
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+44
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni225A
+ENCODING 8794
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+44
+28
+10
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni225B
+ENCODING 8795
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+10
+7C
+28
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni225C
+ENCODING 8796
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+28
+44
+7C
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni225D
+ENCODING 8797
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+26
+7C
+B4
+6C
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni225E
+ENCODING 8798
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+68
+54
+54
+00
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni225F
+ENCODING 8799
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+08
+10
+00
+10
+FE
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+08
+7E
+08
+10
+7E
+10
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+00
+00
+FE
+00
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+08
+FE
+08
+10
+FE
+10
+20
+FE
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2263
+ENCODING 8803
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+00
+00
+FE
+00
+00
+FE
+00
+00
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0E
+38
+E0
+38
+0E
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+E0
+38
+0E
+38
+E0
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2266
+ENCODING 8806
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+0E
+38
+E0
+38
+0E
+00
+FE
+00
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2267
+ENCODING 8807
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+E0
+38
+0E
+38
+E0
+00
+FE
+00
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2268
+ENCODING 8808
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+0E
+38
+E0
+38
+0E
+08
+FE
+10
+FE
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2269
+ENCODING 8809
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+E0
+38
+0E
+38
+E0
+08
+FE
+10
+FE
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni226A
+ENCODING 8810
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+1B
+36
+6C
+D8
+6C
+36
+1B
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni226B
+ENCODING 8811
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+D8
+6C
+36
+1B
+36
+6C
+D8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni226C
+ENCODING 8812
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+66
+18
+3C
+66
+66
+66
+66
+3C
+18
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni226D
+ENCODING 8813
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+CE
+7C
+10
+7C
+E6
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni226E
+ENCODING 8814
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+04
+0E
+38
+E8
+38
+0E
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni226F
+ENCODING 8815
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+E0
+38
+2E
+38
+E0
+40
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2270
+ENCODING 8816
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+04
+0E
+38
+E8
+38
+0E
+10
+FE
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2271
+ENCODING 8817
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+E0
+38
+2E
+38
+E0
+40
+FE
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2272
+ENCODING 8818
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0E
+38
+E0
+38
+0E
+00
+76
+DC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2273
+ENCODING 8819
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+E0
+38
+0E
+38
+E0
+00
+76
+DC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2274
+ENCODING 8820
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+04
+0E
+38
+E8
+38
+0E
+10
+76
+DC
+20
+20
+00
+00
+ENDCHAR
+STARTCHAR uni2275
+ENCODING 8821
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+E0
+38
+2E
+38
+E0
+40
+76
+DC
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2276
+ENCODING 8822
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+38
+E0
+38
+0E
+E0
+38
+0E
+38
+E0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2277
+ENCODING 8823
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+E0
+38
+0E
+38
+E0
+0E
+38
+E0
+38
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2278
+ENCODING 8824
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+0E
+38
+E8
+38
+1E
+F0
+38
+2E
+38
+E0
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2279
+ENCODING 8825
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+E8
+38
+0E
+38
+F0
+1E
+38
+E0
+38
+2E
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR uni227A
+ENCODING 8826
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+02
+06
+1C
+F0
+1C
+06
+02
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni227B
+ENCODING 8827
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+80
+C0
+70
+1E
+70
+C0
+80
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni227C
+ENCODING 8828
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+02
+06
+1C
+F0
+1C
+06
+F2
+1C
+06
+02
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni227D
+ENCODING 8829
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+80
+C0
+70
+1E
+70
+C0
+9E
+70
+C0
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni227E
+ENCODING 8830
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+02
+06
+1C
+F0
+1C
+06
+02
+00
+76
+DC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni227F
+ENCODING 8831
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+80
+C0
+70
+1E
+70
+C0
+80
+00
+76
+DC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2280
+ENCODING 8832
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+06
+0C
+38
+E8
+38
+1C
+16
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2281
+ENCODING 8833
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+D0
+70
+38
+2E
+38
+60
+C0
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR propersubset
+ENCODING 8834
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+7E
+C0
+C0
+C0
+C0
+7E
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR propersuperset
+ENCODING 8835
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FC
+06
+06
+06
+06
+FC
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR notsubset
+ENCODING 8836
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+7E
+C8
+C8
+D0
+D0
+7E
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2285
+ENCODING 8837
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+FC
+16
+16
+26
+26
+FC
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR reflexsubset
+ENCODING 8838
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7E
+C0
+C0
+C0
+C0
+7E
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR reflexsuperset
+ENCODING 8839
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FC
+06
+06
+06
+06
+FC
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2288
+ENCODING 8840
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+7E
+C8
+C8
+D0
+D0
+7E
+20
+FE
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2289
+ENCODING 8841
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+FC
+16
+16
+26
+26
+FC
+40
+FE
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni228A
+ENCODING 8842
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7E
+C0
+C0
+C0
+C0
+7E
+08
+FE
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni228B
+ENCODING 8843
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FC
+06
+06
+06
+06
+FC
+10
+FE
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni228C
+ENCODING 8844
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+82
+92
+A2
+FA
+A2
+92
+44
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni228D
+ENCODING 8845
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+82
+82
+92
+BA
+BA
+92
+44
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni228E
+ENCODING 8846
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+82
+82
+92
+BA
+92
+82
+44
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni228F
+ENCODING 8847
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+C0
+C0
+C0
+C0
+FE
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2290
+ENCODING 8848
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+06
+06
+06
+06
+FE
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2291
+ENCODING 8849
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+C0
+C0
+C0
+C0
+FE
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2292
+ENCODING 8850
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+06
+06
+06
+06
+FE
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2293
+ENCODING 8851
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2294
+ENCODING 8852
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+C6
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR circleplus
+ENCODING 8853
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+54
+92
+FE
+92
+54
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2296
+ENCODING 8854
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+44
+82
+FE
+82
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR circlemultiply
+ENCODING 8855
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+44
+AA
+92
+AA
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2298
+ENCODING 8856
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+44
+8A
+92
+A2
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2299
+ENCODING 8857
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+44
+92
+BA
+92
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni229A
+ENCODING 8858
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+44
+92
+AA
+92
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni229B
+ENCODING 8859
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+54
+D6
+BA
+D6
+54
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni229C
+ENCODING 8860
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+44
+BA
+82
+BA
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni229D
+ENCODING 8861
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+44
+82
+BA
+82
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni229E
+ENCODING 8862
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+92
+92
+FE
+92
+92
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni229F
+ENCODING 8863
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+82
+82
+FE
+82
+82
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A0
+ENCODING 8864
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+C6
+AA
+92
+AA
+C6
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A1
+ENCODING 8865
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+82
+92
+BA
+92
+82
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A2
+ENCODING 8866
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C0
+C0
+C0
+C0
+FF
+C0
+C0
+C0
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A3
+ENCODING 8867
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+03
+03
+03
+03
+FF
+03
+03
+03
+03
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A4
+ENCODING 8868
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR perpendicular
+ENCODING 8869
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+18
+18
+18
+18
+18
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A6
+ENCODING 8870
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+60
+60
+60
+60
+7E
+60
+60
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A7
+ENCODING 8871
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+60
+60
+60
+7E
+60
+7E
+60
+60
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A8
+ENCODING 8872
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C0
+C0
+C0
+FF
+C0
+FF
+C0
+C0
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22A9
+ENCODING 8873
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+D8
+D8
+D8
+D8
+DF
+D8
+D8
+D8
+D8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22AA
+ENCODING 8874
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+A8
+A8
+A8
+A8
+AF
+A8
+A8
+A8
+A8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22AB
+ENCODING 8875
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+D8
+D8
+D8
+DF
+D8
+DF
+D8
+D8
+D8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22AC
+ENCODING 8876
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C0
+C2
+C4
+C4
+FF
+C8
+C8
+D0
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22AD
+ENCODING 8877
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C0
+C4
+C4
+FF
+C8
+FF
+D0
+D0
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22AE
+ENCODING 8878
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+D8
+D9
+DA
+DA
+DF
+DA
+DA
+DC
+D8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22AF
+ENCODING 8879
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+D8
+D9
+DA
+DF
+DA
+DF
+DA
+DC
+D8
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B0
+ENCODING 8880
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+0C
+06
+1C
+F0
+1C
+06
+0C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B1
+ENCODING 8881
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+60
+C0
+70
+1E
+70
+C0
+60
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B2
+ENCODING 8882
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+06
+1E
+76
+C6
+76
+1E
+06
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B3
+ENCODING 8883
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C0
+F0
+DC
+C6
+DC
+F0
+C0
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B4
+ENCODING 8884
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+1E
+76
+C6
+76
+1E
+06
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B5
+ENCODING 8885
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+F0
+DC
+C6
+DC
+F0
+C0
+00
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B6
+ENCODING 8886
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+42
+BF
+42
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B7
+ENCODING 8887
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+42
+FD
+42
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B8
+ENCODING 8888
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+02
+7D
+02
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22B9
+ENCODING 8889
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+10
+00
+C6
+00
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22BA
+ENCODING 8890
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+18
+18
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22BB
+ENCODING 8891
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C6
+C6
+6C
+6C
+38
+38
+10
+10
+00
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22BC
+ENCODING 8892
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+00
+10
+10
+38
+38
+6C
+6C
+C6
+C6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22BD
+ENCODING 8893
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+00
+C6
+C6
+6C
+6C
+38
+38
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22BE
+ENCODING 8894
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C0
+C0
+C0
+F0
+C8
+C4
+C4
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22BF
+ENCODING 8895
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+03
+07
+0B
+13
+23
+43
+83
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C0
+ENCODING 8896
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+38
+38
+6C
+6C
+C6
+C6
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C1
+ENCODING 8897
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C6
+C6
+6C
+6C
+38
+38
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C2
+ENCODING 8898
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+38
+6C
+C6
+C6
+C6
+C6
+C6
+C6
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C3
+ENCODING 8899
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C6
+C6
+C6
+C6
+C6
+C6
+6C
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C4
+ENCODING 8900
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+38
+6C
+38
+10
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotmath
+ENCODING 8901
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C6
+ENCODING 8902
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+10
+7C
+38
+28
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C7
+ENCODING 8903
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+92
+44
+28
+92
+28
+44
+92
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C8
+ENCODING 8904
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+82
+C6
+AA
+92
+AA
+C6
+82
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22C9
+ENCODING 8905
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+82
+C4
+A8
+90
+A8
+C4
+82
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22CA
+ENCODING 8906
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+82
+46
+2A
+12
+2A
+46
+82
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22CB
+ENCODING 8907
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+80
+40
+20
+10
+28
+44
+82
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22CC
+ENCODING 8908
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+02
+04
+08
+10
+28
+44
+82
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22CD
+ENCODING 8909
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+DC
+76
+00
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22CE
+ENCODING 8910
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+10
+38
+38
+6C
+6C
+C6
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22CF
+ENCODING 8911
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C6
+6C
+6C
+38
+38
+10
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D0
+ENCODING 8912
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+3E
+60
+CE
+D8
+D8
+CE
+60
+3E
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D1
+ENCODING 8913
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+F8
+0C
+E6
+36
+36
+E6
+0C
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D2
+ENCODING 8914
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+38
+44
+92
+AA
+AA
+AA
+AA
+AA
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D3
+ENCODING 8915
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+AA
+AA
+AA
+AA
+AA
+92
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D4
+ENCODING 8916
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+38
+54
+92
+92
+92
+92
+92
+92
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D5
+ENCODING 8917
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+7E
+18
+18
+7E
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D6
+ENCODING 8918
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+30
+64
+CE
+64
+30
+18
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D7
+ENCODING 8919
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+30
+18
+4C
+E6
+4C
+18
+30
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D8
+ENCODING 8920
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+15
+2A
+54
+A8
+54
+2A
+15
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22D9
+ENCODING 8921
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+A8
+54
+2A
+15
+2A
+54
+A8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22DA
+ENCODING 8922
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+0E
+38
+E0
+38
+0E
+00
+FE
+00
+E0
+38
+0E
+38
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni22DB
+ENCODING 8923
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+E0
+38
+0E
+38
+E0
+00
+FE
+00
+0E
+38
+E0
+38
+0E
+00
+00
+ENDCHAR
+STARTCHAR uni22DC
+ENCODING 8924
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+00
+0E
+38
+E0
+38
+0E
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22DD
+ENCODING 8925
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+00
+E0
+38
+0E
+38
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22DE
+ENCODING 8926
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+02
+06
+1C
+F2
+06
+1C
+F0
+1C
+06
+02
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22DF
+ENCODING 8927
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+80
+C0
+70
+9E
+C0
+70
+1E
+70
+C0
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E0
+ENCODING 8928
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0A
+0E
+1C
+F0
+1C
+16
+F2
+1C
+26
+22
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E1
+ENCODING 8929
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+88
+C8
+70
+1E
+70
+D0
+9E
+70
+E0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E2
+ENCODING 8930
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+FE
+C8
+C8
+D0
+D0
+FE
+20
+FE
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E3
+ENCODING 8931
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+FE
+16
+16
+26
+26
+FE
+40
+FE
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E4
+ENCODING 8932
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+C0
+C0
+C0
+C0
+FE
+08
+FE
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E5
+ENCODING 8933
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+06
+06
+06
+06
+FE
+10
+FE
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E6
+ENCODING 8934
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0E
+38
+E0
+38
+0E
+10
+76
+DC
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E7
+ENCODING 8935
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+E0
+38
+0E
+38
+E0
+10
+76
+DC
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E8
+ENCODING 8936
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+02
+06
+1C
+F0
+1C
+06
+02
+10
+76
+DC
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22E9
+ENCODING 8937
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+80
+C0
+70
+1E
+70
+C0
+80
+10
+76
+DC
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22EA
+ENCODING 8938
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+0E
+1E
+76
+D6
+76
+1E
+26
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22EB
+ENCODING 8939
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+C8
+F0
+DC
+D6
+DC
+F0
+E0
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22EC
+ENCODING 8940
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+0E
+1E
+76
+D6
+76
+1E
+26
+20
+FE
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22ED
+ENCODING 8941
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+C8
+F0
+DC
+D6
+DC
+F0
+E0
+20
+FE
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22EE
+ENCODING 8942
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+00
+00
+18
+18
+00
+00
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22EF
+ENCODING 8943
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+DB
+DB
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22F0
+ENCODING 8944
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+03
+03
+00
+00
+18
+18
+00
+00
+C0
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni22F1
+ENCODING 8945
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+00
+00
+18
+18
+00
+00
+03
+03
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR emptyset
+ENCODING 8960
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+3D
+66
+C7
+CB
+D3
+E3
+66
+BC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR house
+ENCODING 8962
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+38
+6C
+C6
+C6
+C6
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2308
+ENCODING 8968
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2309
+ENCODING 8969
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni230A
+ENCODING 8970
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni230B
+ENCODING 8971
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR revlogicalnot
+ENCODING 8976
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FE
+C0
+C0
+C0
+C0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2318
+ENCODING 8984
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+42
+A5
+7E
+24
+24
+7E
+A5
+42
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR circleplus
+ENCODING 8986
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+38
+38
+54
+8A
+F6
+82
+54
+38
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 8987
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+FE
+FE
+44
+44
+28
+10
+28
+44
+44
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR integraltp
+ENCODING 8992
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+1B
+1B
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR integralbt
+ENCODING 8993
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+D8
+D8
+D8
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR angleleft
+ENCODING 9001
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0C
+18
+18
+30
+30
+60
+60
+30
+30
+18
+18
+0C
+0C
+00
+00
+ENDCHAR
+STARTCHAR angleright
+ENCODING 9002
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+60
+30
+30
+18
+18
+0C
+0C
+18
+18
+30
+30
+60
+60
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9115
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+03
+06
+0C
+0C
+18
+18
+18
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9116
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9117
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+30
+30
+30
+30
+30
+18
+18
+18
+0C
+0C
+06
+03
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9118
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+C0
+60
+30
+30
+18
+18
+18
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9119
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9120
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+18
+18
+18
+30
+30
+60
+C0
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9121
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+3F
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9122
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9123
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+3F
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9124
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+FC
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9125
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9126
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+0C
+FC
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9127
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+07
+0C
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9128
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+30
+E0
+30
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9129
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+0C
+07
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9130
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9131
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+E0
+30
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9132
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+0C
+07
+0C
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9133
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+30
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9134
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9135
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9136
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+07
+0C
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+30
+E0
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9137
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+E0
+30
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+0C
+07
+ENDCHAR
+STARTCHAR summation
+ENCODING 9138
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+C1
+C0
+60
+60
+60
+60
+30
+30
+30
+30
+18
+18
+18
+ENDCHAR
+STARTCHAR summation
+ENCODING 9139
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+30
+30
+30
+30
+60
+60
+60
+60
+C0
+C1
+FF
+00
+00
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9140
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+C3
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9141
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+C3
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9142
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+C3
+FF
+00
+FF
+C3
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9143
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+D8
+D8
+78
+78
+38
+38
+18
+18
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9144
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9145
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+03
+03
+03
+03
+03
+03
+03
+03
+03
+03
+03
+03
+03
+03
+03
+03
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9146
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9147
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9148
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9149
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR carriagereturn
+ENCODING 9166
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+07
+05
+05
+05
+05
+25
+79
+C2
+7C
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 9225
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D8
+D8
+F8
+D8
+D8
+0F
+06
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 9226
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+C0
+C0
+F0
+0F
+0C
+0E
+0C
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 9227
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D8
+D8
+F8
+70
+20
+0F
+06
+06
+06
+06
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 9228
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+C0
+E0
+C0
+C0
+0F
+0C
+0E
+0C
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 9229
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+C0
+C0
+C0
+70
+1E
+1B
+1E
+1B
+1B
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9251
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9252
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+98
+D8
+F8
+D8
+D8
+0C
+0C
+0C
+0C
+0F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 9254
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+FE
+C6
+C6
+60
+30
+30
+00
+30
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9472
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2501
+ENCODING 9473
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9474
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2503
+ENCODING 9475
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2504
+ENCODING 9476
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+6D
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2505
+ENCODING 9477
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+6D
+6D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2506
+ENCODING 9478
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+00
+18
+18
+18
+18
+18
+00
+18
+18
+18
+18
+00
+ENDCHAR
+STARTCHAR uni2507
+ENCODING 9479
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+00
+1C
+1C
+1C
+1C
+1C
+00
+1C
+1C
+1C
+1C
+00
+ENDCHAR
+STARTCHAR uni2508
+ENCODING 9480
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+AA
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2509
+ENCODING 9481
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+AA
+AA
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni250A
+ENCODING 9482
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+00
+18
+18
+18
+00
+18
+18
+18
+00
+18
+18
+18
+00
+ENDCHAR
+STARTCHAR uni250B
+ENCODING 9483
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+00
+1C
+1C
+1C
+00
+1C
+1C
+1C
+00
+1C
+1C
+1C
+00
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 9484
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+1F
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni250D
+ENCODING 9485
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+1F
+1F
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni250E
+ENCODING 9486
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni250F
+ENCODING 9487
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+1F
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 9488
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F8
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2511
+ENCODING 9489
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F8
+F8
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2512
+ENCODING 9490
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2513
+ENCODING 9491
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FC
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 9492
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+1F
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2515
+ENCODING 9493
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+1F
+1F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2516
+ENCODING 9494
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1F
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2517
+ENCODING 9495
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1F
+1F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 9496
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2519
+ENCODING 9497
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+F8
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni251A
+ENCODING 9498
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FC
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni251B
+ENCODING 9499
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FC
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 9500
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+1F
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni251D
+ENCODING 9501
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+1F
+1F
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni251E
+ENCODING 9502
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1F
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni251F
+ENCODING 9503
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2520
+ENCODING 9504
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2521
+ENCODING 9505
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1F
+1F
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2522
+ENCODING 9506
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+1F
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2523
+ENCODING 9507
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1F
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 9508
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+F8
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2525
+ENCODING 9509
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+F8
+F8
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2526
+ENCODING 9510
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FC
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2527
+ENCODING 9511
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2528
+ENCODING 9512
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2529
+ENCODING 9513
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FC
+FC
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni252A
+ENCODING 9514
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FC
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni252B
+ENCODING 9515
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FC
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 9516
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni252D
+ENCODING 9517
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+F8
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni252E
+ENCODING 9518
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+1F
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni252F
+ENCODING 9519
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+FF
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2530
+ENCODING 9520
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2531
+ENCODING 9521
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2532
+ENCODING 9522
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2533
+ENCODING 9523
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+FF
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 9524
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2535
+ENCODING 9525
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2536
+ENCODING 9526
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+1F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2537
+ENCODING 9527
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2538
+ENCODING 9528
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2539
+ENCODING 9529
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni253A
+ENCODING 9530
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+1F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni253B
+ENCODING 9531
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 9532
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni253D
+ENCODING 9533
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+F8
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni253E
+ENCODING 9534
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+1F
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni253F
+ENCODING 9535
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+FF
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2540
+ENCODING 9536
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2541
+ENCODING 9537
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2542
+ENCODING 9538
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2543
+ENCODING 9539
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+FC
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2544
+ENCODING 9540
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+1F
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2545
+ENCODING 9541
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2546
+ENCODING 9542
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2547
+ENCODING 9543
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+FF
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2548
+ENCODING 9544
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+FF
+FF
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni2549
+ENCODING 9545
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+FC
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni254A
+ENCODING 9546
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+1F
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni254B
+ENCODING 9547
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+FF
+FF
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni254C
+ENCODING 9548
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+EE
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni254D
+ENCODING 9549
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+EE
+EE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni254E
+ENCODING 9550
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+00
+18
+18
+18
+18
+18
+18
+18
+00
+ENDCHAR
+STARTCHAR uni254F
+ENCODING 9551
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+00
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+00
+ENDCHAR
+STARTCHAR SF430000
+ENCODING 9552
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF240000
+ENCODING 9553
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+36
+36
+36
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF510000
+ENCODING 9554
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+1F
+18
+1F
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF520000
+ENCODING 9555
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+3F
+36
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF390000
+ENCODING 9556
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+3F
+30
+37
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF220000
+ENCODING 9557
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+F8
+18
+F8
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF210000
+ENCODING 9558
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FE
+36
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF250000
+ENCODING 9559
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FE
+06
+F6
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF500000
+ENCODING 9560
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+1F
+18
+1F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF490000
+ENCODING 9561
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+36
+3F
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF380000
+ENCODING 9562
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+37
+30
+3F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF280000
+ENCODING 9563
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+F8
+18
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF270000
+ENCODING 9564
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+36
+FE
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF260000
+ENCODING 9565
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+F6
+06
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF360000
+ENCODING 9566
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+1F
+18
+1F
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF370000
+ENCODING 9567
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+36
+37
+36
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF420000
+ENCODING 9568
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+37
+30
+37
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF190000
+ENCODING 9569
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+F8
+18
+F8
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF200000
+ENCODING 9570
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+36
+F6
+36
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF230000
+ENCODING 9571
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+F6
+06
+F6
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF470000
+ENCODING 9572
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+00
+FF
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF480000
+ENCODING 9573
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+36
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF410000
+ENCODING 9574
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+00
+F7
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF450000
+ENCODING 9575
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+FF
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF460000
+ENCODING 9576
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+36
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF400000
+ENCODING 9577
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+F7
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF540000
+ENCODING 9578
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+FF
+18
+FF
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR SF530000
+ENCODING 9579
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+36
+FF
+36
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR SF440000
+ENCODING 9580
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+36
+36
+36
+36
+36
+36
+F7
+00
+F7
+36
+36
+36
+36
+36
+36
+36
+ENDCHAR
+STARTCHAR uni256D
+ENCODING 9581
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+03
+0E
+0C
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni256E
+ENCODING 9582
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+C0
+70
+30
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni256F
+ENCODING 9583
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+30
+70
+C0
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2570
+ENCODING 9584
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+0C
+0E
+03
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2571
+ENCODING 9585
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+01
+01
+02
+02
+04
+04
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR uni2572
+ENCODING 9586
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+80
+80
+40
+40
+20
+20
+10
+10
+08
+08
+04
+04
+02
+02
+01
+01
+ENDCHAR
+STARTCHAR uni2573
+ENCODING 9587
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+81
+81
+42
+42
+24
+24
+18
+18
+18
+18
+24
+24
+42
+42
+81
+81
+ENDCHAR
+STARTCHAR uni2574
+ENCODING 9588
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2575
+ENCODING 9589
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2576
+ENCODING 9590
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+1F
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2577
+ENCODING 9591
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR uni2578
+ENCODING 9592
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FC
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2579
+ENCODING 9593
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni257A
+ENCODING 9594
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+1F
+1F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni257B
+ENCODING 9595
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni257C
+ENCODING 9596
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+1F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni257D
+ENCODING 9597
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+ENDCHAR
+STARTCHAR uni257E
+ENCODING 9598
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni257F
+ENCODING 9599
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+1C
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR upblock
+ENCODING 9600
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2581
+ENCODING 9601
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+FF
+ENDCHAR
+STARTCHAR uni2582
+ENCODING 9602
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR uni2583
+ENCODING 9603
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR dnblock
+ENCODING 9604
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR uni2585
+ENCODING 9605
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR uni2586
+ENCODING 9606
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR uni2587
+ENCODING 9607
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR block
+ENCODING 9608
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR uni2589
+ENCODING 9609
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+ENDCHAR
+STARTCHAR uni258A
+ENCODING 9610
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+FC
+ENDCHAR
+STARTCHAR uni258B
+ENCODING 9611
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR lfblock
+ENCODING 9612
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+ENDCHAR
+STARTCHAR uni258D
+ENCODING 9613
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni258E
+ENCODING 9614
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258F
+ENCODING 9615
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR rtblock
+ENCODING 9616
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+ENDCHAR
+STARTCHAR ltshade
+ENCODING 9617
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+11
+44
+11
+44
+11
+44
+11
+44
+11
+44
+11
+44
+11
+44
+11
+44
+ENDCHAR
+STARTCHAR shade
+ENCODING 9618
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+ENDCHAR
+STARTCHAR dkshade
+ENCODING 9619
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+DD
+77
+DD
+77
+DD
+77
+DD
+77
+DD
+77
+DD
+77
+DD
+77
+DD
+77
+ENDCHAR
+STARTCHAR uni2594
+ENCODING 9620
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2595
+ENCODING 9621
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+01
+01
+01
+01
+01
+01
+01
+01
+01
+01
+01
+01
+01
+01
+01
+01
+ENDCHAR
+STARTCHAR filledbox
+ENCODING 9632
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR H22073
+ENCODING 9633
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+82
+82
+82
+82
+82
+82
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25A2
+ENCODING 9634
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+7C
+82
+82
+82
+82
+82
+82
+82
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25A3
+ENCODING 9635
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+82
+BA
+BA
+BA
+BA
+BA
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25A4
+ENCODING 9636
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+82
+FE
+82
+FE
+82
+FE
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25A5
+ENCODING 9637
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+AA
+AA
+AA
+AA
+AA
+AA
+AA
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25A6
+ENCODING 9638
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+AA
+FE
+AA
+FE
+AA
+FE
+AA
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25A7
+ENCODING 9639
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+8A
+C6
+A2
+92
+8A
+C6
+A2
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25A8
+ENCODING 9640
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+A2
+C6
+8A
+92
+A2
+C6
+8A
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25A9
+ENCODING 9641
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+AA
+C6
+AA
+92
+AA
+C6
+AA
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR H18543
+ENCODING 9642
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7C
+7C
+7C
+7C
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR H18551
+ENCODING 9643
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7C
+44
+44
+44
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR filledrect
+ENCODING 9644
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FE
+FE
+FE
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25AD
+ENCODING 9645
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FE
+82
+82
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25AE
+ENCODING 9646
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+FE
+00
+00
+ENDCHAR
+STARTCHAR uni25AF
+ENCODING 9647
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+82
+82
+82
+82
+82
+82
+82
+82
+82
+82
+FE
+00
+00
+ENDCHAR
+STARTCHAR uni25B0
+ENCODING 9648
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+7E
+7E
+7E
+FC
+FC
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B1
+ENCODING 9649
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+7E
+42
+42
+84
+84
+FC
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR triagup
+ENCODING 9650
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+38
+38
+7C
+7C
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B3
+ENCODING 9651
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+28
+28
+44
+44
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B4
+ENCODING 9652
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+10
+38
+38
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B5
+ENCODING 9653
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+10
+28
+28
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B6
+ENCODING 9654
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+80
+C0
+E0
+F0
+F8
+FC
+F8
+F0
+E0
+C0
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B7
+ENCODING 9655
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+80
+C0
+A0
+90
+88
+84
+88
+90
+A0
+C0
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B8
+ENCODING 9656
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+40
+70
+78
+70
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B9
+ENCODING 9657
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+40
+70
+48
+70
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR triagrt
+ENCODING 9658
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+80
+E0
+F8
+FE
+F8
+E0
+80
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25BB
+ENCODING 9659
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+80
+E0
+98
+86
+98
+E0
+80
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR triagdn
+ENCODING 9660
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+FE
+7C
+7C
+38
+38
+10
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25BD
+ENCODING 9661
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+82
+44
+44
+28
+28
+10
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25BE
+ENCODING 9662
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+7C
+38
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25BF
+ENCODING 9663
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+7C
+28
+28
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C0
+ENCODING 9664
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+02
+06
+0E
+1E
+3E
+7E
+3E
+1E
+0E
+06
+02
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C1
+ENCODING 9665
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+02
+06
+0A
+12
+22
+42
+22
+12
+0A
+06
+02
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C2
+ENCODING 9666
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+08
+38
+78
+38
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C3
+ENCODING 9667
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+08
+38
+48
+38
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR triaglf
+ENCODING 9668
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+02
+0E
+3E
+FE
+3E
+0E
+02
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C5
+ENCODING 9669
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+02
+0E
+32
+C2
+32
+0E
+02
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 9670
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+7C
+7C
+FE
+FE
+7C
+7C
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C7
+ENCODING 9671
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+44
+44
+82
+82
+44
+44
+28
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C8
+ENCODING 9672
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+44
+54
+BA
+BA
+54
+44
+28
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C9
+ENCODING 9673
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+99
+BD
+BD
+BD
+BD
+99
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR lozenge
+ENCODING 9674
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+28
+28
+44
+82
+82
+44
+28
+28
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR circle
+ENCODING 9675
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+81
+81
+81
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25CC
+ENCODING 9676
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+14
+40
+01
+80
+01
+80
+01
+80
+02
+28
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25CD
+ENCODING 9677
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+A5
+A5
+A5
+A5
+A5
+A5
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25CE
+ENCODING 9678
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+99
+A5
+A5
+A5
+A5
+99
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR H18533
+ENCODING 9679
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+7E
+FF
+FF
+FF
+FF
+FF
+FF
+7E
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25D0
+ENCODING 9680
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+72
+F1
+F1
+F1
+F1
+F1
+F1
+72
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25D1
+ENCODING 9681
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+4E
+8F
+8F
+8F
+8F
+8F
+8F
+4E
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25D2
+ENCODING 9682
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+81
+81
+81
+FF
+FF
+FF
+7E
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25D3
+ENCODING 9683
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+7E
+FF
+FF
+FF
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25D4
+ENCODING 9684
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+4E
+8F
+8F
+8F
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25D5
+ENCODING 9685
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+4E
+8F
+8F
+8F
+FF
+FF
+FF
+7E
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25D6
+ENCODING 9686
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+70
+F0
+F0
+F0
+F0
+F0
+F0
+70
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25D7
+ENCODING 9687
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+0E
+0F
+0F
+0F
+0F
+0F
+0F
+0E
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR invbullet
+ENCODING 9688
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+FF
+FF
+FF
+FF
+E7
+C3
+C3
+E7
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR invcircle
+ENCODING 9689
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+C3
+BD
+7E
+7E
+7E
+7E
+7E
+7E
+BD
+C3
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR uni25DA
+ENCODING 9690
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+C3
+BD
+7E
+7E
+7E
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25DB
+ENCODING 9691
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7E
+7E
+7E
+BD
+C3
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR uni25DC
+ENCODING 9692
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+40
+80
+80
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25DD
+ENCODING 9693
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+02
+01
+01
+01
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25DE
+ENCODING 9694
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+01
+01
+01
+02
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25DF
+ENCODING 9695
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+80
+80
+80
+40
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25E0
+ENCODING 9696
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+81
+81
+81
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25E1
+ENCODING 9697
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25E2
+ENCODING 9698
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+01
+01
+03
+03
+07
+07
+0F
+0F
+1F
+1F
+3F
+3F
+7F
+7F
+FF
+FF
+ENDCHAR
+STARTCHAR uni25E3
+ENCODING 9699
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+80
+80
+C0
+C0
+E0
+E0
+F0
+F0
+F8
+F8
+FC
+FC
+FE
+FE
+FF
+FF
+ENDCHAR
+STARTCHAR uni25E4
+ENCODING 9700
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+FE
+FE
+FC
+FC
+F8
+F8
+F0
+F0
+E0
+E0
+C0
+C0
+80
+80
+ENDCHAR
+STARTCHAR uni25E5
+ENCODING 9701
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+7F
+7F
+3F
+3F
+1F
+1F
+0F
+0F
+07
+07
+03
+03
+01
+01
+ENDCHAR
+STARTCHAR openbullet
+ENCODING 9702
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+66
+42
+42
+66
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25E7
+ENCODING 9703
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+F1
+F1
+F1
+F1
+F1
+F1
+F1
+F1
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25E8
+ENCODING 9704
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+8F
+8F
+8F
+8F
+8F
+8F
+8F
+8F
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25E9
+ENCODING 9705
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+FF
+FD
+F9
+F1
+F1
+E1
+C1
+81
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25EA
+ENCODING 9706
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+81
+83
+87
+8F
+8F
+9F
+BF
+FF
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25EB
+ENCODING 9707
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FF
+99
+99
+99
+99
+99
+99
+99
+99
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25EC
+ENCODING 9708
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+28
+28
+44
+44
+92
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25ED
+ENCODING 9709
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+38
+38
+74
+74
+F2
+F2
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25EE
+ENCODING 9710
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+38
+38
+5C
+5C
+9E
+9E
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25EF
+ENCODING 9711
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+81
+81
+81
+81
+81
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25F0
+ENCODING 9712
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+92
+92
+92
+F2
+82
+82
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25F1
+ENCODING 9713
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+82
+82
+82
+F2
+92
+92
+92
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25F2
+ENCODING 9714
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+82
+82
+82
+9E
+92
+92
+92
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25F3
+ENCODING 9715
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+FE
+92
+92
+92
+9E
+82
+82
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25F4
+ENCODING 9716
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+4A
+89
+89
+89
+F9
+81
+81
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25F5
+ENCODING 9717
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+81
+81
+F9
+89
+89
+89
+4A
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25F6
+ENCODING 9718
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+81
+81
+9F
+91
+91
+91
+52
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25F7
+ENCODING 9719
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+52
+91
+91
+91
+9F
+81
+81
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2600
+ENCODING 9728
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+54
+38
+FE
+38
+54
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2602
+ENCODING 9729
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+30
+7C
+FE
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2601
+ENCODING 9730
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+38
+7C
+FE
+10
+10
+10
+10
+14
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2605
+ENCODING 9733
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+38
+FE
+7C
+38
+6C
+44
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2606
+ENCODING 9734
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+28
+EE
+44
+54
+6C
+44
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2607
+ENCODING 9735
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+18
+30
+60
+C0
+60
+34
+1C
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2608
+ENCODING 9736
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+C6
+CC
+D8
+F0
+D8
+CD
+C7
+CF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2609
+ENCODING 9737
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+38
+44
+82
+92
+82
+44
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni260A
+ENCODING 9738
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+24
+42
+42
+42
+A5
+A5
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni260B
+ENCODING 9739
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+42
+A5
+A5
+42
+42
+42
+24
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni260C
+ENCODING 9740
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+06
+0C
+78
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni260D
+ENCODING 9741
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+36
+36
+1C
+18
+30
+70
+D8
+D8
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2610
+ENCODING 9744
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+82
+82
+82
+82
+82
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2611
+ENCODING 9745
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+82
+86
+8A
+BA
+92
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2612
+ENCODING 9746
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+82
+EE
+BA
+BA
+EE
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2613
+ENCODING 9747
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+82
+C6
+6C
+7C
+38
+7C
+6C
+C6
+82
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2620
+ENCODING 9760
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+7C
+82
+AA
+82
+44
+7C
+44
+38
+00
+44
+C6
+38
+C6
+44
+00
+ENDCHAR
+STARTCHAR uni2622
+ENCODING 9762
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+38
+44
+EE
+FE
+92
+BA
+7C
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2626
+ENCODING 9766
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+7E
+18
+18
+FF
+18
+1E
+78
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2628
+ENCODING 9768
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+7E
+18
+18
+FF
+18
+18
+18
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2629
+ENCODING 9769
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+38
+10
+10
+92
+FE
+92
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni262A
+ENCODING 9770
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+72
+E0
+C4
+DF
+CE
+CA
+E0
+72
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni262B
+ENCODING 9771
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+54
+28
+54
+AA
+AA
+AA
+AA
+54
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni262E
+ENCODING 9774
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+5A
+99
+99
+99
+BD
+FF
+DB
+5A
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni262F
+ENCODING 9775
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+81
+85
+B1
+F9
+FF
+DF
+7E
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2630
+ENCODING 9776
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+FE
+00
+00
+FE
+FE
+00
+00
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2631
+ENCODING 9777
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+EE
+EE
+00
+00
+FE
+FE
+00
+00
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2632
+ENCODING 9778
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+FE
+00
+00
+EE
+EE
+00
+00
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2633
+ENCODING 9779
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+EE
+EE
+00
+00
+EE
+EE
+00
+00
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2634
+ENCODING 9780
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+FE
+00
+00
+FE
+FE
+00
+00
+EE
+EE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2635
+ENCODING 9781
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+EE
+EE
+00
+00
+FE
+FE
+00
+00
+EE
+EE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2636
+ENCODING 9782
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+FE
+00
+00
+EE
+EE
+00
+00
+EE
+EE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2637
+ENCODING 9783
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+EE
+EE
+00
+00
+EE
+EE
+00
+00
+EE
+EE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2639
+ENCODING 9785
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+81
+A5
+81
+81
+81
+99
+A5
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR smileface
+ENCODING 9786
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+81
+A5
+81
+81
+A5
+99
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR invsmileface
+ENCODING 9787
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+FF
+DB
+FF
+FF
+DB
+E7
+FF
+FF
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sun
+ENCODING 9788
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+54
+28
+C6
+28
+54
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni263D
+ENCODING 9789
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+14
+0A
+0A
+0A
+0A
+0A
+0A
+14
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni263E
+ENCODING 9790
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+28
+50
+50
+50
+50
+50
+50
+28
+1E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni263F
+ENCODING 9791
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+66
+66
+3C
+66
+66
+66
+66
+3C
+18
+7E
+18
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR female
+ENCODING 9792
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+66
+3C
+18
+7E
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2641
+ENCODING 9793
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+7E
+18
+3C
+66
+66
+66
+66
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR male
+ENCODING 9794
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+06
+0E
+1A
+78
+CC
+CC
+CC
+CC
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2643
+ENCODING 9795
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+03
+03
+7B
+CF
+CF
+CF
+0F
+1B
+33
+FF
+03
+03
+03
+00
+00
+ENDCHAR
+STARTCHAR uni2644
+ENCODING 9796
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+60
+F0
+60
+6E
+73
+63
+63
+66
+66
+63
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2645
+ENCODING 9797
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+D6
+54
+54
+7C
+54
+54
+D6
+38
+44
+44
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2646
+ENCODING 9798
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+3C
+DB
+DB
+DB
+DB
+7E
+3C
+18
+3C
+18
+18
+00
+00
+ENDCHAR
+STARTCHAR uni2647
+ENCODING 9799
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F8
+CC
+CC
+CC
+CC
+F8
+C0
+C0
+C0
+C0
+FE
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2648
+ENCODING 9800
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+A5
+A5
+3C
+3C
+18
+18
+18
+18
+18
+18
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2649
+ENCODING 9801
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+C3
+66
+66
+66
+66
+3C
+66
+66
+66
+66
+3C
+00
+00
+ENDCHAR
+STARTCHAR uni264A
+ENCODING 9802
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C3
+7E
+66
+66
+66
+66
+66
+66
+7E
+C3
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni264B
+ENCODING 9803
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+DB
+D8
+70
+00
+00
+0E
+1B
+DB
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni264C
+ENCODING 9804
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+33
+33
+33
+33
+1B
+7B
+DB
+DB
+73
+03
+01
+00
+00
+ENDCHAR
+STARTCHAR uni264D
+ENCODING 9805
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+94
+7C
+55
+57
+55
+55
+55
+55
+55
+55
+06
+0B
+00
+00
+ENDCHAR
+STARTCHAR uni264E
+ENCODING 9806
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+66
+66
+66
+66
+24
+E7
+00
+FF
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni264F
+ENCODING 9807
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+94
+7C
+54
+54
+54
+54
+54
+54
+54
+54
+04
+03
+00
+00
+ENDCHAR
+STARTCHAR uni2650
+ENCODING 9808
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1F
+07
+8F
+DB
+73
+70
+D8
+88
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2651
+ENCODING 9809
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+90
+50
+70
+68
+48
+48
+4E
+49
+09
+0E
+10
+20
+00
+00
+ENDCHAR
+STARTCHAR uni2652
+ENCODING 9810
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+2A
+7E
+AA
+00
+00
+2A
+7E
+AA
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2653
+ENCODING 9811
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C3
+66
+66
+66
+66
+FF
+66
+66
+66
+66
+C3
+00
+00
+00
+ENDCHAR
+STARTCHAR spade
+ENCODING 9824
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+3C
+7E
+FF
+FF
+7E
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2661
+ENCODING 9825
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+6C
+92
+82
+82
+82
+44
+28
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2662
+ENCODING 9826
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+28
+44
+82
+44
+28
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR club
+ENCODING 9827
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+3C
+3C
+E7
+E7
+E7
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2664
+ENCODING 9828
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+24
+42
+81
+81
+66
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR heart
+ENCODING 9829
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+6C
+FE
+FE
+FE
+FE
+7C
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR diamond
+ENCODING 9830
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+38
+7C
+FE
+7C
+38
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2667
+ENCODING 9831
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+18
+24
+3C
+E7
+A5
+E7
+18
+18
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2669
+ENCODING 9833
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+18
+18
+18
+18
+18
+18
+38
+78
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR musicalnote
+ENCODING 9834
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+3C
+3E
+32
+30
+30
+30
+70
+F0
+E0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR musicalnotedbl
+ENCODING 9835
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+7F
+6F
+63
+63
+63
+63
+E3
+E7
+C7
+06
+00
+00
+00
+ENDCHAR
+STARTCHAR uni266C
+ENCODING 9836
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7F
+63
+7F
+63
+63
+63
+63
+63
+E7
+E7
+C6
+00
+00
+00
+ENDCHAR
+STARTCHAR uni266D
+ENCODING 9837
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+C0
+C0
+C0
+C0
+CC
+DE
+E6
+C4
+D8
+E0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni266E
+ENCODING 9838
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+40
+40
+44
+5C
+74
+44
+44
+5C
+74
+44
+04
+04
+00
+00
+ENDCHAR
+STARTCHAR uni266F
+ENCODING 9839
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+04
+46
+5C
+74
+C4
+46
+5C
+74
+C4
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR ff
+ENCODING 64256
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3B
+66
+66
+66
+FF
+66
+66
+66
+66
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR fi
+ENCODING 64257
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+6E
+66
+60
+FE
+66
+66
+66
+66
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR fl
+ENCODING 64258
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+6E
+66
+66
+FE
+66
+66
+66
+66
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ffi
+ENCODING 64259
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6E
+DB
+DB
+D8
+FF
+DB
+DB
+DB
+DB
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ffl
+ENCODING 64260
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+6F
+DB
+DB
+DB
+FF
+DB
+DB
+DB
+DB
+FF
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB05
+ENCODING 64261
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+6C
+6C
+6F
+6C
+6C
+6C
+6C
+6D
+F6
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB50
+ENCODING 64336
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+06
+29
+5E
+00
+04
+04
+04
+04
+04
+04
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB51
+ENCODING 64337
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+06
+29
+5E
+00
+04
+04
+04
+04
+04
+03
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB52
+ENCODING 64338
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+81
+81
+7E
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB53
+ENCODING 64339
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+80
+81
+7E
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB54
+ENCODING 64340
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+04
+F8
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB55
+ENCODING 64341
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+08
+F7
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB56
+ENCODING 64342
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+81
+81
+7E
+00
+14
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB57
+ENCODING 64343
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+80
+81
+7E
+00
+14
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB58
+ENCODING 64344
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+04
+F8
+00
+14
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB59
+ENCODING 64345
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+08
+F7
+00
+14
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB5A
+ENCODING 64346
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+81
+81
+7E
+00
+14
+00
+14
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB5B
+ENCODING 64347
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+80
+81
+7E
+00
+14
+00
+14
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB5C
+ENCODING 64348
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+04
+F8
+00
+14
+00
+14
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB5D
+ENCODING 64349
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+08
+F7
+00
+14
+00
+14
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB5E
+ENCODING 64350
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+08
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB5F
+ENCODING 64351
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+08
+00
+40
+80
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB60
+ENCODING 64352
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+08
+00
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB61
+ENCODING 64353
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+08
+00
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB62
+ENCODING 64354
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+14
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB63
+ENCODING 64355
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+14
+00
+40
+80
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB64
+ENCODING 64356
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+14
+00
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB65
+ENCODING 64357
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+14
+00
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB66
+ENCODING 64358
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB67
+ENCODING 64359
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+40
+80
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB68
+ENCODING 64360
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB69
+ENCODING 64361
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB6A
+ENCODING 64362
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+00
+0A
+00
+06
+49
+85
+83
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB6B
+ENCODING 64363
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+00
+0A
+00
+06
+49
+89
+86
+7D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB6C
+ENCODING 64364
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+0C
+12
+0A
+06
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB6D
+ENCODING 64365
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+0C
+12
+12
+0C
+F3
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB6E
+ENCODING 64366
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0A
+00
+0A
+00
+06
+49
+85
+83
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB6F
+ENCODING 64367
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0A
+00
+0A
+00
+06
+49
+89
+86
+7D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB70
+ENCODING 64368
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+14
+00
+14
+00
+0C
+12
+0A
+06
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB71
+ENCODING 64369
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+14
+00
+14
+00
+0C
+12
+12
+0C
+F3
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB72
+ENCODING 64370
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+88
+80
+88
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB73
+ENCODING 64371
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+41
+88
+80
+88
+40
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFB74
+ENCODING 64372
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+47
+18
+E0
+00
+04
+00
+04
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB75
+ENCODING 64373
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+C1
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB76
+ENCODING 64374
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+80
+94
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB77
+ENCODING 64375
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+41
+80
+94
+80
+40
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFB78
+ENCODING 64376
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+47
+18
+E0
+00
+00
+0A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB79
+ENCODING 64377
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+C1
+00
+00
+14
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB7A
+ENCODING 64378
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+94
+80
+88
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB7B
+ENCODING 64379
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+41
+94
+80
+88
+40
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFB7C
+ENCODING 64380
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+47
+18
+E0
+00
+0A
+00
+04
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB7D
+ENCODING 64381
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+C1
+00
+14
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB7E
+ENCODING 64382
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+94
+80
+94
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB7F
+ENCODING 64383
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+41
+94
+80
+94
+40
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFB80
+ENCODING 64384
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+47
+18
+E0
+00
+0A
+00
+0A
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB81
+ENCODING 64385
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+C1
+00
+14
+00
+14
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB82
+ENCODING 64386
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+04
+02
+42
+3C
+00
+00
+14
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB83
+ENCODING 64387
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+08
+04
+46
+39
+00
+00
+14
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB84
+ENCODING 64388
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+28
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB85
+ENCODING 64389
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+28
+00
+08
+08
+04
+46
+39
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB86
+ENCODING 64390
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+00
+28
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB87
+ENCODING 64391
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+00
+28
+00
+08
+08
+04
+46
+39
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB88
+ENCODING 64392
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+20
+38
+28
+70
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB89
+ENCODING 64393
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+20
+38
+28
+70
+08
+08
+04
+46
+39
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB8A
+ENCODING 64394
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+00
+14
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB8B
+ENCODING 64395
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+14
+00
+00
+04
+07
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB8C
+ENCODING 64396
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB8D
+ENCODING 64397
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+00
+00
+04
+07
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB8E
+ENCODING 64398
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+01
+02
+04
+08
+44
+82
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB8F
+ENCODING 64399
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+01
+02
+04
+08
+48
+84
+82
+7D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB90
+ENCODING 64400
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+18
+20
+10
+08
+08
+F0
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB91
+ENCODING 64401
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+18
+20
+20
+10
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB92
+ENCODING 64402
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+09
+12
+04
+08
+44
+82
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB93
+ENCODING 64403
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+09
+12
+04
+08
+48
+84
+82
+7D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB94
+ENCODING 64404
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+30
+46
+18
+20
+10
+08
+08
+F0
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB95
+ENCODING 64405
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+30
+46
+18
+20
+20
+10
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB96
+ENCODING 64406
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+09
+12
+04
+08
+44
+82
+82
+7C
+00
+10
+00
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB97
+ENCODING 64407
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+09
+12
+04
+08
+48
+84
+82
+7D
+00
+10
+00
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB98
+ENCODING 64408
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+30
+46
+18
+20
+10
+08
+08
+F0
+00
+10
+00
+10
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB99
+ENCODING 64409
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+30
+46
+18
+20
+20
+10
+08
+F7
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB9A
+ENCODING 64410
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+A4
+09
+12
+04
+08
+44
+82
+82
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB9B
+ENCODING 64411
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+A4
+09
+12
+04
+08
+48
+84
+82
+7D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB9C
+ENCODING 64412
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+A2
+0C
+13
+0C
+10
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB9D
+ENCODING 64413
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+A2
+0C
+13
+0C
+10
+10
+08
+04
+FB
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB9E
+ENCODING 64414
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+41
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFB9F
+ENCODING 64415
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+01
+41
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA0
+ENCODING 64416
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+41
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA1
+ENCODING 64417
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+00
+00
+01
+41
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA2
+ENCODING 64418
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA3
+ENCODING 64419
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+1C
+14
+38
+00
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA4
+ENCODING 64420
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+38
+40
+38
+40
+18
+24
+22
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA5
+ENCODING 64421
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+70
+80
+70
+80
+10
+68
+88
+74
+03
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA6
+ENCODING 64422
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+24
+22
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA7
+ENCODING 64423
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+0C
+13
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA8
+ENCODING 64424
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+10
+F0
+10
+14
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBA9
+ENCODING 64425
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+10
+F7
+08
+08
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBAA
+ENCODING 64426
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+38
+4C
+52
+32
+3D
+40
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBAB
+ENCODING 64427
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+38
+4C
+52
+32
+3D
+40
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBAC
+ENCODING 64428
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+38
+4C
+52
+32
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBAD
+ENCODING 64429
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+38
+4C
+52
+32
+FD
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBAE
+ENCODING 64430
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+14
+60
+80
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBAF
+ENCODING 64431
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+07
+18
+20
+3F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBB0
+ENCODING 64432
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+70
+80
+70
+80
+08
+14
+60
+80
+FE
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBB1
+ENCODING 64433
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+20
+1C
+20
+00
+00
+07
+18
+20
+3F
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBD3
+ENCODING 64467
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+00
+29
+01
+19
+21
+19
+A1
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBD4
+ENCODING 64468
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+00
+2A
+02
+32
+42
+32
+C6
+79
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBD5
+ENCODING 64469
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+40
+00
+A3
+0C
+10
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBD6
+ENCODING 64470
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+40
+00
+A3
+0C
+10
+10
+08
+04
+FB
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBD7
+ENCODING 64471
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+28
+18
+10
+20
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBD8
+ENCODING 64472
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+28
+18
+10
+20
+00
+0C
+12
+0F
+02
+04
+18
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBD9
+ENCODING 64473
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+08
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBDA
+ENCODING 64474
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+08
+00
+00
+00
+0C
+12
+0F
+02
+04
+18
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBDB
+ENCODING 64475
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+08
+08
+08
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBDC
+ENCODING 64476
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+08
+08
+08
+00
+00
+0C
+12
+0F
+02
+04
+18
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBDD
+ENCODING 64477
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+23
+54
+33
+24
+40
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBDE
+ENCODING 64478
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBDF
+ENCODING 64479
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+14
+00
+0C
+12
+0F
+02
+04
+18
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBE0
+ENCODING 64480
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+12
+0E
+02
+3C
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBE1
+ENCODING 64481
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+08
+00
+00
+00
+0C
+12
+0F
+02
+3C
+18
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBE2
+ENCODING 64482
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+14
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBE3
+ENCODING 64483
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+14
+00
+00
+00
+0C
+12
+0F
+02
+04
+18
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBE4
+ENCODING 64484
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+81
+7E
+00
+10
+00
+10
+ENDCHAR
+STARTCHAR uniFBE5
+ENCODING 64485
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+07
+88
+87
+81
+7E
+10
+00
+10
+ENDCHAR
+STARTCHAR uniFBE6
+ENCODING 64486
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+04
+F8
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBE7
+ENCODING 64487
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+08
+F7
+00
+08
+00
+08
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBE8
+ENCODING 64488
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBE9
+ENCODING 64489
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBFC
+ENCODING 64508
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+82
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBFD
+ENCODING 64509
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+07
+88
+87
+81
+7E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBFE
+ENCODING 64510
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+04
+F8
+00
+00
+14
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFBFF
+ENCODING 64511
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+08
+F7
+00
+00
+14
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC5B
+ENCODING 64603
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+20
+20
+20
+20
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC5C
+ENCODING 64604
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC5D
+ENCODING 64605
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+00
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC5E
+ENCODING 64606
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+24
+98
+60
+C2
+12
+92
+9C
+60
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC5F
+ENCODING 64607
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+02
+92
+9C
+60
+0E
+70
+0E
+70
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC60
+ENCODING 64608
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+60
+04
+54
+58
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC61
+ENCODING 64609
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+28
+10
+60
+04
+54
+58
+20
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC62
+ENCODING 64610
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+04
+54
+58
+20
+0C
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC63
+ENCODING 64611
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+04
+54
+58
+20
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFC90
+ENCODING 64656
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+00
+00
+00
+00
+07
+88
+87
+81
+7E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFCF2
+ENCODING 64754
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0E
+F0
+02
+92
+9C
+60
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFCF3
+ENCODING 64755
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+24
+18
+60
+02
+92
+9C
+60
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFCF4
+ENCODING 64756
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+02
+12
+9C
+60
+0E
+70
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFD3C
+ENCODING 64828
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+28
+50
+28
+08
+08
+08
+08
+07
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFD3D
+ENCODING 64829
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+14
+28
+14
+04
+04
+04
+04
+04
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFD3E
+ENCODING 64830
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+08
+10
+54
+38
+54
+10
+08
+04
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFD3F
+ENCODING 64831
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+10
+08
+2A
+1C
+2A
+08
+10
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFDF2
+ENCODING 65010
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+2A
+14
+00
+21
+69
+A9
+69
+16
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE50
+ENCODING 65104
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+08
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE51
+ENCODING 65105
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE52
+ENCODING 65106
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE54
+ENCODING 65108
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+00
+00
+08
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE55
+ENCODING 65109
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+10
+00
+00
+10
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE56
+ENCODING 65110
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+24
+08
+10
+00
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE57
+ENCODING 65111
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+10
+10
+10
+00
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE58
+ENCODING 65112
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE59
+ENCODING 65113
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+10
+10
+10
+10
+10
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE5A
+ENCODING 65114
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+08
+08
+08
+08
+08
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE5B
+ENCODING 65115
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+10
+10
+20
+10
+10
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE5C
+ENCODING 65116
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+08
+08
+04
+08
+08
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE5D
+ENCODING 65117
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+10
+10
+10
+10
+10
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE5E
+ENCODING 65118
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+18
+08
+08
+08
+08
+08
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE5F
+ENCODING 65119
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+28
+7C
+28
+7C
+28
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE60
+ENCODING 65120
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+28
+28
+10
+2A
+24
+1A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE61
+ENCODING 65121
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+10
+7C
+38
+38
+44
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE62
+ENCODING 65122
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+10
+10
+7C
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE63
+ENCODING 65123
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE64
+ENCODING 65124
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+10
+20
+10
+08
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE65
+ENCODING 65125
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+20
+10
+08
+10
+20
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE66
+ENCODING 65126
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+3C
+00
+3C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE68
+ENCODING 65128
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+20
+10
+10
+08
+08
+04
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE69
+ENCODING 65129
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+38
+54
+30
+18
+54
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE6A
+ENCODING 65130
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+24
+08
+08
+10
+10
+24
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE6B
+ENCODING 65131
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+44
+54
+58
+40
+38
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE70
+ENCODING 65136
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+30
+0C
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE71
+ENCODING 65137
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+06
+18
+60
+06
+18
+60
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE72
+ENCODING 65138
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+12
+CA
+2C
+70
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE74
+ENCODING 65140
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0C
+30
+0C
+30
+00
+00
+ENDCHAR
+STARTCHAR uniFE76
+ENCODING 65142
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+30
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE77
+ENCODING 65143
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+06
+18
+60
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE78
+ENCODING 65144
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+14
+0C
+08
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE79
+ENCODING 65145
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+24
+14
+18
+60
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE7A
+ENCODING 65146
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+0C
+30
+00
+00
+ENDCHAR
+STARTCHAR uniFE7B
+ENCODING 65147
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+06
+18
+60
+00
+00
+ENDCHAR
+STARTCHAR uniFE7C
+ENCODING 65148
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0A
+2A
+2C
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE7D
+ENCODING 65149
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+02
+12
+92
+9C
+60
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE7E
+ENCODING 65150
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+24
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE7F
+ENCODING 65151
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+24
+24
+18
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE80
+ENCODING 65152
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+24
+20
+1E
+20
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE81
+ENCODING 65153
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+02
+3C
+40
+10
+10
+10
+10
+10
+10
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE82
+ENCODING 65154
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+01
+3E
+40
+08
+08
+08
+08
+08
+07
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE83
+ENCODING 65155
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+20
+1C
+20
+08
+08
+08
+08
+08
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE84
+ENCODING 65156
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0C
+10
+0E
+10
+04
+04
+04
+04
+03
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE85
+ENCODING 65157
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+1C
+20
+1C
+20
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE86
+ENCODING 65158
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+1C
+20
+1C
+20
+00
+0C
+12
+0F
+02
+04
+18
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE87
+ENCODING 65159
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+04
+04
+04
+04
+04
+00
+0C
+10
+0E
+10
+00
+00
+ENDCHAR
+STARTCHAR uniFE88
+ENCODING 65160
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+04
+04
+04
+04
+03
+00
+0C
+10
+0E
+10
+00
+00
+ENDCHAR
+STARTCHAR uniFE89
+ENCODING 65161
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+40
+38
+40
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE8A
+ENCODING 65162
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+30
+40
+38
+40
+00
+00
+00
+07
+88
+87
+81
+7E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE8B
+ENCODING 65163
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+1C
+20
+1C
+20
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE8C
+ENCODING 65164
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+1C
+20
+1C
+20
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE8D
+ENCODING 65165
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+08
+08
+08
+08
+08
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE8E
+ENCODING 65166
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+08
+08
+08
+08
+07
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE8F
+ENCODING 65167
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+81
+81
+7E
+00
+00
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE90
+ENCODING 65168
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+40
+80
+81
+7E
+00
+00
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE91
+ENCODING 65169
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+04
+F8
+00
+00
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE92
+ENCODING 65170
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+08
+F7
+00
+00
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE93
+ENCODING 65171
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+28
+00
+00
+18
+24
+22
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE94
+ENCODING 65172
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+50
+00
+10
+10
+68
+88
+74
+03
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE95
+ENCODING 65173
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+14
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE96
+ENCODING 65174
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+14
+00
+40
+80
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE97
+ENCODING 65175
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+14
+00
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE98
+ENCODING 65176
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+14
+00
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE99
+ENCODING 65177
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+40
+81
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE9A
+ENCODING 65178
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+40
+80
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE9B
+ENCODING 65179
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE9C
+ENCODING 65180
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE9D
+ENCODING 65181
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+80
+88
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFE9E
+ENCODING 65182
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+41
+80
+88
+80
+40
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFE9F
+ENCODING 65183
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+47
+18
+E0
+00
+00
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEA0
+ENCODING 65184
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+C1
+00
+00
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEA1
+ENCODING 65185
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+8F
+30
+40
+80
+80
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEA2
+ENCODING 65186
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+41
+80
+80
+80
+40
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFEA3
+ENCODING 65187
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+38
+47
+18
+E0
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEA4
+ENCODING 65188
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+70
+8F
+32
+C1
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEA5
+ENCODING 65189
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+20
+00
+00
+70
+8F
+30
+40
+80
+80
+80
+41
+3E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEA6
+ENCODING 65190
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+00
+00
+70
+8F
+32
+41
+80
+80
+80
+40
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFEA7
+ENCODING 65191
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+00
+38
+47
+18
+E0
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEA8
+ENCODING 65192
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+00
+00
+70
+8F
+32
+C1
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEA9
+ENCODING 65193
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEAA
+ENCODING 65194
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+08
+04
+46
+39
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEAB
+ENCODING 65195
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+00
+08
+04
+02
+42
+3C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEAC
+ENCODING 65196
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+00
+08
+08
+04
+46
+39
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEAD
+ENCODING 65197
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEAE
+ENCODING 65198
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+04
+07
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEAF
+ENCODING 65199
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+00
+04
+02
+02
+04
+18
+60
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB0
+ENCODING 65200
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+00
+00
+04
+07
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB1
+ENCODING 65201
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+01
+15
+88
+84
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB2
+ENCODING 65202
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+01
+15
+88
+84
+84
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB3
+ENCODING 65203
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+01
+15
+EA
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB4
+ENCODING 65204
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+2A
+D5
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB5
+ENCODING 65205
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+01
+15
+88
+84
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB6
+ENCODING 65206
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+14
+00
+01
+15
+88
+84
+84
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB7
+ENCODING 65207
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+04
+00
+0A
+00
+00
+01
+15
+EA
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB8
+ENCODING 65208
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+14
+00
+00
+00
+2A
+D5
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEB9
+ENCODING 65209
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+06
+09
+31
+9E
+88
+88
+70
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEBA
+ENCODING 65210
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+06
+09
+31
+9E
+88
+88
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEBB
+ENCODING 65211
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+06
+29
+31
+DE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEBC
+ENCODING 65212
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+06
+29
+31
+DE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEBD
+ENCODING 65213
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+06
+09
+31
+9E
+88
+88
+70
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEBE
+ENCODING 65214
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+00
+06
+09
+31
+9E
+88
+88
+70
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEBF
+ENCODING 65215
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+00
+06
+29
+31
+DE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC0
+ENCODING 65216
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+00
+06
+29
+31
+DE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC1
+ENCODING 65217
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+20
+20
+2C
+32
+A2
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC2
+ENCODING 65218
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+20
+20
+2C
+32
+A2
+7D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC3
+ENCODING 65219
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+20
+20
+2C
+32
+22
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC4
+ENCODING 65220
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+20
+20
+2C
+32
+22
+FD
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC5
+ENCODING 65221
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+20
+20
+2C
+32
+A2
+7C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC6
+ENCODING 65222
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+20
+20
+2C
+32
+A2
+7D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC7
+ENCODING 65223
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+20
+20
+2C
+32
+22
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC8
+ENCODING 65224
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+20
+20
+2C
+32
+22
+FD
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEC9
+ENCODING 65225
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+70
+80
+8C
+70
+40
+80
+80
+80
+41
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFECA
+ENCODING 65226
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+1E
+22
+1C
+22
+41
+80
+80
+80
+41
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFECB
+ENCODING 65227
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0E
+10
+10
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFECC
+ENCODING 65228
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+1E
+22
+1C
+E3
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFECD
+ENCODING 65229
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+40
+00
+00
+70
+80
+8C
+70
+40
+80
+80
+80
+41
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFECE
+ENCODING 65230
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+08
+00
+00
+1E
+22
+1C
+22
+41
+80
+80
+80
+41
+3E
+00
+00
+ENDCHAR
+STARTCHAR uniFECF
+ENCODING 65231
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+00
+00
+0E
+10
+10
+FE
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED0
+ENCODING 65232
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+00
+1E
+22
+1C
+E3
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED1
+ENCODING 65233
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+06
+49
+85
+83
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED2
+ENCODING 65234
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+00
+06
+49
+89
+86
+7D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED3
+ENCODING 65235
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+0C
+12
+0A
+06
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED4
+ENCODING 65236
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+0C
+12
+12
+0C
+F3
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED5
+ENCODING 65237
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0A
+00
+06
+09
+09
+47
+81
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED6
+ENCODING 65238
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0A
+00
+00
+06
+09
+49
+87
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED7
+ENCODING 65239
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+00
+0C
+12
+0A
+06
+FC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED8
+ENCODING 65240
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+14
+00
+00
+0C
+12
+12
+0C
+F3
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFED9
+ENCODING 65241
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+19
+21
+19
+21
+01
+81
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEDA
+ENCODING 65242
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+32
+42
+32
+42
+02
+86
+79
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEDB
+ENCODING 65243
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+18
+20
+10
+08
+08
+F0
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEDC
+ENCODING 65244
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+06
+18
+20
+20
+10
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEDD
+ENCODING 65245
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+02
+02
+02
+02
+02
+42
+82
+82
+84
+78
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEDE
+ENCODING 65246
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+02
+02
+02
+02
+02
+03
+42
+82
+82
+84
+78
+00
+00
+ENDCHAR
+STARTCHAR uniFEDF
+ENCODING 65247
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+08
+08
+08
+08
+08
+F0
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEE0
+ENCODING 65248
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+08
+08
+08
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEE1
+ENCODING 65249
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+0C
+12
+12
+3C
+40
+40
+40
+40
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR uniFEE2
+ENCODING 65250
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+3C
+4B
+4A
+44
+40
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR uniFEE3
+ENCODING 65251
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+12
+32
+CC
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEE4
+ENCODING 65252
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+12
+32
+CD
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEE5
+ENCODING 65253
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+00
+00
+41
+81
+81
+81
+42
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEE6
+ENCODING 65254
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+01
+41
+81
+81
+42
+3C
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEE7
+ENCODING 65255
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+00
+08
+04
+04
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEE8
+ENCODING 65256
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+08
+00
+00
+08
+08
+F7
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEE9
+ENCODING 65257
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+18
+24
+22
+22
+1C
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEEA
+ENCODING 65258
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+68
+88
+74
+03
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEEB
+ENCODING 65259
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+40
+30
+4E
+49
+39
+E6
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEEC
+ENCODING 65260
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+08
+14
+24
+28
+F3
+24
+18
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEED
+ENCODING 65261
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+0C
+12
+0E
+02
+04
+18
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEEE
+ENCODING 65262
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+0C
+12
+0F
+02
+04
+18
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEEF
+ENCODING 65263
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEF0
+ENCODING 65264
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+07
+88
+87
+81
+7E
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEF1
+ENCODING 65265
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+07
+08
+88
+86
+81
+81
+7E
+00
+00
+24
+00
+ENDCHAR
+STARTCHAR uniFEF2
+ENCODING 65266
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+07
+88
+87
+81
+7E
+00
+24
+00
+ENDCHAR
+STARTCHAR uniFEF3
+ENCODING 65267
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+04
+F8
+00
+00
+14
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEF4
+ENCODING 65268
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+08
+08
+F7
+00
+00
+14
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEF5
+ENCODING 65269
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+68
+90
+02
+22
+12
+0A
+04
+0C
+12
+3C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEF6
+ENCODING 65270
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+68
+90
+02
+32
+12
+0A
+0A
+0E
+3D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEF7
+ENCODING 65271
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+60
+80
+72
+A2
+12
+0A
+04
+0C
+12
+3C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEF8
+ENCODING 65272
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+30
+40
+3A
+52
+12
+0A
+0A
+0E
+3D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEF9
+ENCODING 65273
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+22
+12
+0A
+04
+0C
+12
+3C
+00
+18
+20
+1C
+20
+00
+ENDCHAR
+STARTCHAR uniFEFA
+ENCODING 65274
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+22
+12
+12
+0A
+0A
+0E
+3D
+00
+00
+18
+20
+1C
+20
+00
+ENDCHAR
+STARTCHAR uniFEFB
+ENCODING 65275
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+22
+12
+0A
+04
+0C
+12
+3C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEFC
+ENCODING 65276
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+22
+12
+12
+0A
+0A
+0E
+3D
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uniFEFF
+ENCODING 65279
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+F1
+35
+55
+8A
+E0
+06
+95
+D6
+B5
+97
+00
+EE
+8A
+EE
+28
+E8
+ENDCHAR
+STARTCHAR uniFFFD
+ENCODING 65533
+SWIDTH 480 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+7C
+7C
+C6
+92
+F2
+E6
+FE
+E6
+7C
+7C
+38
+00
+00
+00
+ENDCHAR
+ENDFONT
Index: contrib/tools/gen_vga323.c
===================================================================
--- contrib/tools/gen_vga323.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ contrib/tools/gen_vga323.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,5 +33,6 @@
 #define BLUE(i)   ((i) & ((1 << 3) - 1))
 
-int main(int argc, char *argv[]) {
+int main(int argc, char *argv[])
+{
 	unsigned int i;
 	
Index: defaults/amd64/Makefile.config
===================================================================
--- defaults/amd64/Makefile.config	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ defaults/amd64/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -65,2 +65,4 @@
 CONFIG_MOUNT_DATA = n
 
+# OHCI root hub power switch, ganged is enough
+OHCI_POWER_SWITCH = ganged
Index: defaults/arm32/gta02/Makefile.config
===================================================================
--- defaults/arm32/gta02/Makefile.config	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ defaults/arm32/gta02/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -4,11 +4,2 @@
 # RAM disk format
 RDFMT = tmpfs
-
-# Support for userspace debuggers
-CONFIG_UDEBUG = n
-
-# Compile kernel tests
-CONFIG_TEST = n
-
-# Barebone build with essential binaries only
-CONFIG_BAREBONE = y
Index: defaults/ia32/Makefile.config
===================================================================
--- defaults/ia32/Makefile.config	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ defaults/ia32/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -71,2 +71,4 @@
 CONFIG_MOUNT_DATA = n
 
+# OHCI root hub power switch, ganged is enough
+OHCI_POWER_SWITCH = ganged
Index: defaults/mips64/Makefile.config
===================================================================
--- defaults/mips64/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ defaults/mips64/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+# Platform
+PLATFORM = mips64
+
+# Ramdisk format
+RDFMT = fat
+
+# Compiler
+COMPILER = gcc_cross
+
+# Debug build
+CONFIG_DEBUG = y
+
+# Deadlock detection support for spinlocks
+CONFIG_DEBUG_SPINLOCK = y
+
+# Support for SMP
+CONFIG_SMP = y
+
+# Support for userspace debuggers
+CONFIG_UDEBUG = y
+
+# Kernel console support
+CONFIG_KCONSOLE = y
+
+# Kernel symbol information
+CONFIG_SYMTAB = y
+
+# Detailed kernel logging
+CONFIG_LOG = n
+
+# Kernel function tracing
+CONFIG_TRACE = n
+
+# Compile kernel tests
+CONFIG_TEST = y
+
+# Input device class
+CONFIG_HID_IN = generic
+
+# Output device class
+CONFIG_HID_OUT = generic
+
+# Load disk drivers on startup
+CONFIG_START_BD = n
+
+# Mount /data on startup
+CONFIG_MOUNT_DATA = n
+
Index: defaults/mips64/msim/Makefile.config
===================================================================
--- defaults/mips64/msim/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ defaults/mips64/msim/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,2 @@
+# Machine type
+MACHINE = msim
Index: defaults/mips64/output
===================================================================
--- defaults/mips64/output	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ defaults/mips64/output	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+image.boot
Index: defaults/ppc32/Makefile.config
===================================================================
--- defaults/ppc32/Makefile.config	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ defaults/ppc32/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,7 +38,4 @@
 CONFIG_FB = y
 
-# Use Block Address Translation by the loader
-CONFIG_BAT = y
-
 # Load disk drivers on startup
 CONFIG_START_BD = n
Index: defaults/sparc64/Makefile.config
===================================================================
--- defaults/sparc64/Makefile.config	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ defaults/sparc64/Makefile.config	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -53,7 +53,4 @@
 CONFIG_AP = y
 
-# Preserve A.OUT header in isofs.b
-CONFIG_AOUT_ISOFS_B = y
-
 # Load disk drivers on startup
 CONFIG_START_BD = n
Index: faults/sparc64/serengeti/Makefile.config
===================================================================
--- defaults/sparc64/serengeti/Makefile.config	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,11 +1,0 @@
-# Machine type
-MACHINE = serengeti
-RDFMT = tmpfs
-CONFIG_SMP = n
-CONFIG_DEBUG = n
-CONFIG_UDEBUG = n
-CONFIG_SYMTAB = n
-CONFIG_TEST = n
-CONFIG_STRIP_BINARIES = y
-CONFIG_OPTIMIZE_FOR_SIZE = y
-CONFIG_BAREBONE = y
Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -59,4 +59,5 @@
 REAL_MAP = generic/src/debug/real_map
 
+ABI_INCLUDE = generic/include/abi
 ARCH_INCLUDE = generic/include/arch
 GENARCH_INCLUDE = generic/include/genarch
@@ -75,5 +76,5 @@
 
 clean:
-	rm -f $(DEPEND) $(DEPEND_PREV) $(RAW) $(BIN) $(MAP) $(JOB) $(MAP_PREV) $(DISASM) $(DUMP) $(REAL_MAP).* $(ARCH_INCLUDE) $(GENARCH_INCLUDE) arch/*/_link.ld arch/*/include/common.h
+	rm -f $(DEPEND) $(DEPEND_PREV) $(RAW) $(BIN) $(MAP) $(JOB) $(MAP_PREV) $(DISASM) $(DUMP) $(REAL_MAP).* $(ABI_INCLUDE) $(ARCH_INCLUDE) $(GENARCH_INCLUDE) arch/*/_link.ld arch/*/include/common.h
 	find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.o' -follow -exec rm \{\} \;
 
@@ -94,5 +95,5 @@
 	-fexec-charset=UTF-8 -fwide-exec-charset=UTF-32$(ENDIANESS) \
 	-finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
-	-Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
+	-std=gnu99 -Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes \
 	-Werror-implicit-function-declaration -Wwrite-strings \
 	-pipe
@@ -134,5 +135,5 @@
 #
 AFLAGS =
-LFLAGS = -N -T $(LINK) -M
+LFLAGS = -n -T $(LINK) -M
 
 #
@@ -226,7 +227,7 @@
 	generic/src/proc/task.c \
 	generic/src/proc/the.c \
-	generic/src/proc/tasklet.c \
 	generic/src/syscall/syscall.c \
 	generic/src/syscall/copy.c \
+	generic/src/mm/reserve.c \
 	generic/src/mm/buddy.c \
 	generic/src/mm/frame.c \
@@ -240,4 +241,5 @@
 	generic/src/lib/func.c \
 	generic/src/lib/memstr.c \
+	generic/src/lib/memfnc.c \
 	generic/src/lib/sort.c \
 	generic/src/lib/str.c \
@@ -328,43 +330,4 @@
 	endif
 	
-	ifeq ($(CONFIG_FPU),y)
-		ifeq ($(KARCH),ia32)
-			TEST_FPU1 = y
-			TEST_SSE1 = y
-			GENERIC_SOURCES += test/fpu/fpu1_x86.c
-		endif
-		
-		ifeq ($(KARCH),amd64)
-			TEST_FPU1 = y
-			TEST_SSE1 = y
-			GENERIC_SOURCES += test/fpu/fpu1_x86.c
-		endif
-		
-		ifeq ($(KARCH),ia64)
-			TEST_FPU1 = y
-			GENERIC_SOURCES += test/fpu/fpu1_ia64.c
-		endif
-		
-		ifeq ($(KARCH),mips32)
-			TEST_MIPS2 = y
-		endif
-	endif
-	
-	ifneq ($(TEST_FPU1),y)
-		GENERIC_SOURCES += test/fpu/fpu1_skip.c
-	endif
-	
-	ifeq ($(TEST_SSE1),y)
-		GENERIC_SOURCES += test/fpu/sse1.c
-	else
-		GENERIC_SOURCES += test/fpu/sse1_skip.c
-	endif
-	
-	ifeq ($(TEST_MIPS2),y)
-		GENERIC_SOURCES += test/fpu/mips2.c
-	else
-		GENERIC_SOURCES += test/fpu/mips2_skip.c
-	endif
-	
 endif
 
@@ -381,5 +344,4 @@
 		generic/src/main/kinit.c \
 		generic/src/proc/the.c \
-		generic/src/proc/tasklet.c \
 		generic/src/mm/frame.c \
 		generic/src/mm/page.c \
@@ -439,19 +401,4 @@
 	$(JOBFILE) $(JOB) $< $@ as asm $(DEFS) $(CFLAGS) $(EXTRA_FLAGS)
 endif
-
-#
-# The FPU tests are the only objects for which we allow the compiler to generate
-# FPU instructions.
-#
-
-test/fpu/%.o: test/fpu/%.c $(DEPEND)
-	$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) -c -o $@ $<
-ifeq ($(PRECHECK),y)
-	$(JOBFILE) $(JOB) $< $@ cc test $(DEFS) $(CFLAGS) $(EXTRA_FLAGS)
-endif
-
-#
-# Ordinary objects.
-#
 
 %.o: %.c $(DEPEND)
@@ -486,8 +433,11 @@
 	$(GENMAP) $(MAP_PREV) $(DUMP) $@
 
-$(DEPEND): $(ARCH_INCLUDE) $(GENARCH_INCLUDE) $(COMMON_HEADER_ARCH)
+$(DEPEND): $(ABI_INCLUDE) $(ARCH_INCLUDE) $(GENARCH_INCLUDE) $(COMMON_HEADER_ARCH)
 	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(ARCH_SOURCES) $(GENARCH_SOURCES) $(GENERIC_SOURCES) > $@ 2> /dev/null
 	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
 
+$(ABI_INCLUDE): ../abi/include/
+	ln -sfn ../../$< $@
+
 $(ARCH_INCLUDE): arch/$(KARCH)/include/
 	ln -sfn ../../$< $@
Index: kernel/arch/abs32le/include/istate.h
===================================================================
--- kernel/arch/abs32le/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/abs32le/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,15 +36,12 @@
 #define KERN_abs32le_ISTATE_H_
 
+#include <trace.h>
+
 #ifdef KERNEL
 
-#include <typedefs.h>
 #include <verify.h>
-#include <trace.h>
 
 #else /* KERNEL */
 
-#include <sys/types.h>
-
-#define NO_TRACE
 #define REQUIRES_EXTENT_MUTABLE(arg)
 #define WRITES(arg)
Index: rnel/arch/abs32le/include/memstr.h
===================================================================
--- kernel/arch/abs32le/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2010 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.
- */
-
-/** @addtogroup abs32le
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_abs32le_MEMSTR_H_
-#define KERN_abs32le_MEMSTR_H_
-
-#define memcpy(dst, src, cnt)   _memcpy((dst), (src), (cnt))
-#define memsetb(dst, cnt, val)  _memsetb((dst), (cnt), (val))
-#define memsetw(dst, cnt, val)  _memsetw((dst), (cnt), (val))
-
-#endif
-
-/** @}
- */
Index: kernel/arch/abs32le/include/mm/as.h
===================================================================
--- kernel/arch/abs32le/include/mm/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/abs32le/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,6 +43,4 @@
 #define USER_ADDRESS_SPACE_END_ARCH      UINT32_C(0x7fffffff)
 
-#define USTACK_ADDRESS_ARCH  (USER_ADDRESS_SPACE_END_ARCH - (PAGE_SIZE - 1))
-
 typedef struct {
 } as_arch_t;
Index: kernel/arch/abs32le/include/mm/frame.h
===================================================================
--- kernel/arch/abs32le/include/mm/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/abs32le/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,6 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
-
 #include <typedefs.h>
 
@@ -46,6 +44,4 @@
 extern void physmem_print(void);
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/abs32le/include/mm/page.h
===================================================================
--- kernel/arch/abs32le/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/abs32le/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,6 +41,4 @@
 #define PAGE_WIDTH  FRAME_WIDTH
 #define PAGE_SIZE   FRAME_SIZE
-
-#ifdef KERNEL
 
 #define KA2PA(x)  (((uintptr_t) (x)) - UINT32_C(0x80000000))
@@ -178,6 +176,4 @@
 extern void page_fault(unsigned int, istate_t *);
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/abs32le/include/types.h
===================================================================
--- kernel/arch/abs32le/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/abs32le/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,4 +40,5 @@
 
 typedef uint32_t size_t;
+typedef int32_t ssize_t;
 
 typedef uint32_t uintptr_t;
Index: kernel/arch/abs32le/src/userspace.c
===================================================================
--- kernel/arch/abs32le/src/userspace.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/abs32le/src/userspace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,7 +36,6 @@
 #include <typedefs.h>
 #include <arch.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <mm/as.h>
-
 
 void userspace(uspace_arg_t *kernel_uarg)
Index: kernel/arch/amd64/Makefile.inc
===================================================================
--- kernel/arch/amd64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,5 +33,24 @@
 
 FPU_NO_CFLAGS = -mno-sse -mno-sse2
-CMN1 = -m64 -mcmodel=large -mno-red-zone -fno-unwind-tables -fno-omit-frame-pointer
+
+#
+# FIXME:
+#
+# The -fno-optimize-sibling-calls should be removed as soon as a bug
+# in GCC concerning the "large" memory model and tail call optimization
+# is fixed.
+#
+# When GCC generates a code for tail call, instead of generating ..
+#
+#   jmp *fnc
+#
+# it generates an assembly code with an illegal immediate prefix:
+#
+#   jmp *$fnc
+#
+# See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48385 for reference.
+#
+
+CMN1 = -m64 -mcmodel=large -mno-red-zone -fno-unwind-tables -fno-omit-frame-pointer -fno-optimize-sibling-calls
 GCC_CFLAGS += $(CMN1)
 ICC_CFLAGS += $(CMN1)
Index: kernel/arch/amd64/_link.ld.in
===================================================================
--- kernel/arch/amd64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -26,10 +26,10 @@
 	.mapped (PA2KA(BOOT_OFFSET)+SIZEOF(.unmapped)) : AT (SIZEOF(.unmapped)) {
 		ktext_start = .;
-		*(.text);
+		*(.text .text.*);
 		ktext_end = .;
 		
 		kdata_start = .;
-		*(.data);       /* initialized data */
-		*(.rodata*);    /* string literals */
+		*(.data);              /* initialized data */
+		*(.rodata .rodata.*);  /* string literals */
 		hardcoded_load_address = .;
 		QUAD(PA2KA(BOOT_OFFSET));
Index: kernel/arch/amd64/include/asm.h
===================================================================
--- kernel/arch/amd64/include/asm.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/include/asm.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -89,5 +89,5 @@
 NO_TRACE static inline uint8_t pio_read_8(ioport8_t *port)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
 		uint8_t val;
 		asm volatile (
@@ -112,5 +112,5 @@
 NO_TRACE static inline uint16_t pio_read_16(ioport16_t *port)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
 		uint16_t val;
 		asm volatile (
@@ -135,5 +135,5 @@
 NO_TRACE static inline uint32_t pio_read_32(ioport32_t *port)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
 		uint32_t val;
 		asm volatile (
@@ -158,5 +158,5 @@
 NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outb %b[val], %w[port]\n"
@@ -164,5 +164,5 @@
 		);	
 	} else {
-		*((uint8_t *) port) = val;
+		*port = val;
 	}
 }
@@ -178,5 +178,5 @@
 NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outw %w[val], %w[port]\n"
@@ -184,5 +184,5 @@
 		);
 	} else {
-		*((uint16_t *) port) = val;
+		*port = val;
 	}
 }
@@ -198,5 +198,5 @@
 NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outl %[val], %w[port]\n"
@@ -204,5 +204,5 @@
 		);
 	} else {
-		*((uint32_t *) port) = val;
+		*port = val;
 	}
 }
Index: kernel/arch/amd64/include/context.h
===================================================================
--- kernel/arch/amd64/include/context.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/include/context.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,4 @@
 #define KERN_amd64_CONTEXT_H_
 
-#ifdef KERNEL
-
 #include <typedefs.h>
 
@@ -52,6 +50,4 @@
 		(c)->rbp = 0; \
 	} while (0)
-
-#endif /* KERNEL */
 
 /* We include only registers that must be preserved
Index: kernel/arch/amd64/include/istate.h
===================================================================
--- kernel/arch/amd64/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,16 +36,5 @@
 #define KERN_amd64_ISTATE_H_
 
-#ifdef KERNEL
-
-#include <typedefs.h>
 #include <trace.h>
-
-#else /* KERNEL */
-
-#include <sys/types.h>
-
-#define NO_TRACE
-
-#endif /* KERNEL */
 
 /** This is passed to interrupt handlers */
Index: rnel/arch/amd64/include/memstr.h
===================================================================
--- kernel/arch/amd64/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2005 Sergey Bondari
- * 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 amd64
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_amd64_MEMSTR_H_
-#define KERN_amd64_MEMSTR_H_
-
-#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
-
-extern void memsetw(void *, size_t, uint16_t);
-extern void memsetb(void *, size_t, uint8_t);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/amd64/include/mm/as.h
===================================================================
--- kernel/arch/amd64/include/mm/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,9 +43,6 @@
 #define KERNEL_ADDRESS_SPACE_START_ARCH  UINT64_C(0xffff800000000000)
 #define KERNEL_ADDRESS_SPACE_END_ARCH    UINT64_C(0xffffffffffffffff)
-
-#define USER_ADDRESS_SPACE_START_ARCH  UINT64_C(0x0000000000000000)
-#define USER_ADDRESS_SPACE_END_ARCH    UINT64_C(0x00007fffffffffff)
-
-#define USTACK_ADDRESS_ARCH  (USER_ADDRESS_SPACE_END_ARCH - (PAGE_SIZE - 1))
+#define USER_ADDRESS_SPACE_START_ARCH    UINT64_C(0x0000000000000000)
+#define USER_ADDRESS_SPACE_END_ARCH      UINT64_C(0x00007fffffffffff)
 
 #define as_constructor_arch(as, flags)  (as != as)
Index: kernel/arch/amd64/include/mm/frame.h
===================================================================
--- kernel/arch/amd64/include/mm/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -49,5 +48,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/amd64/include/mm/page.h
===================================================================
--- kernel/arch/amd64/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -50,6 +50,4 @@
 #define PAGE_WIDTH  FRAME_WIDTH
 #define PAGE_SIZE   FRAME_SIZE
-
-#ifdef KERNEL
 
 #ifndef __ASM__
@@ -231,6 +229,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/amd64/include/types.h
===================================================================
--- kernel/arch/amd64/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
 
 typedef uint64_t size_t;
+typedef int64_t ssize_t;
 
 typedef uint64_t uintptr_t;
Index: kernel/arch/amd64/src/asm.S
===================================================================
--- kernel/arch/amd64/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,7 +37,4 @@
 .global read_efer_flag
 .global set_efer_flag
-.global memsetb
-.global memsetw
-.global memcpy
 .global memcpy_from_uspace
 .global memcpy_to_uspace
@@ -46,12 +43,4 @@
 .global early_putchar
 
-/* Wrapper for generic memsetb */
-memsetb:
-	jmp _memsetb
-
-/* Wrapper for generic memsetw */
-memsetw:
-	jmp _memsetw
-
 #define MEMCPY_DST   %rdi
 #define MEMCPY_SRC   %rsi
@@ -74,5 +63,4 @@
  *
  */
-memcpy:
 memcpy_from_uspace:
 memcpy_to_uspace:
Index: kernel/arch/amd64/src/interrupt.c
===================================================================
--- kernel/arch/amd64/src/interrupt.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/src/interrupt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -66,28 +66,27 @@
 void istate_decode(istate_t *istate)
 {
-	printf("cs =%#0" PRIx64 "\trip=%p\t"
-	    "rfl=%#0" PRIx64 "\terr=%#0" PRIx64 "\n",
-	    istate->cs, (void *) istate->rip,
-	    istate->rflags, istate->error_word);
+	printf("cs =%0#18" PRIx64 "\trip=%0#18" PRIx64 "\t"
+	    "rfl=%0#18" PRIx64 "\terr=%0#18" PRIx64 "\n",
+	    istate->cs, istate->rip, istate->rflags, istate->error_word);
 	
 	if (istate_from_uspace(istate))
-		printf("ss =%#0" PRIx64 "\n", istate->ss);
-	
-	printf("rax=%#0" PRIx64 "\trbx=%#0" PRIx64 "\t"
-	    "rcx=%#0" PRIx64 "\trdx=%#0" PRIx64 "\n",
+		printf("ss =%0#18" PRIx64 "\n", istate->ss);
+	
+	printf("rax=%0#18" PRIx64 "\trbx=%0#18" PRIx64 "\t"
+	    "rcx=%0#18" PRIx64 "\trdx=%0#18" PRIx64 "\n",
 	    istate->rax, istate->rbx, istate->rcx, istate->rdx);
 	
-	printf("rsi=%p\trdi=%p\trbp=%p\trsp=%p\n",
-	    (void *) istate->rsi, (void *) istate->rdi,
-	    (void *) istate->rbp,
-	    istate_from_uspace(istate) ? ((void *) istate->rsp) :
-	    &istate->rsp);
-	
-	printf("r8 =%#0" PRIx64 "\tr9 =%#0" PRIx64 "\t"
-	    "r10=%#0" PRIx64 "\tr11=%#0" PRIx64 "\n",
+	printf("rsi=%0#18" PRIx64 "\trdi=%0#18" PRIx64 "\t"
+	    "rbp=%0#18" PRIx64 "\trsp=%0#18" PRIx64 "\n",
+	    istate->rsi, istate->rdi, istate->rbp,
+	    istate_from_uspace(istate) ? istate->rsp :
+	    (uintptr_t) &istate->rsp);
+	
+	printf("r8 =%0#18" PRIx64 "\tr9 =%0#18" PRIx64 "\t"
+	    "r10=%0#18" PRIx64 "\tr11=%0#18" PRIx64 "\n",
 	    istate->r8, istate->r9, istate->r10, istate->r11);
 	
-	printf("r12=%#0" PRIx64 "\tr13=%#0" PRIx64 "\t"
-	    "r14=%#0" PRIx64 "\tr15=%#0" PRIx64 "\n",
+	printf("r12=%0#18" PRIx64 "\tr13=%0#18" PRIx64 "\t"
+	    "r14=%0#18" PRIx64 "\tr15=%0#18" PRIx64 "\n",
 	    istate->r12, istate->r13, istate->r14, istate->r15);
 }
Index: kernel/arch/amd64/src/proc/scheduler.c
===================================================================
--- kernel/arch/amd64/src/proc/scheduler.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/src/proc/scheduler.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -56,5 +56,5 @@
 {
 	CPU->arch.tss->rsp0 =
-	    (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE];
+	    (uintptr_t) &THREAD->kstack[STACK_SIZE];
 	
 	/*
Index: kernel/arch/amd64/src/userspace.c
===================================================================
--- kernel/arch/amd64/src/userspace.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/amd64/src/userspace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,7 +38,6 @@
 #include <typedefs.h>
 #include <arch.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <mm/as.h>
-
 
 /** Enter userspace
@@ -66,5 +65,5 @@
 		"iretq\n"
 		:: [udata_des] "i" (GDT_SELECTOR(UDATA_DES) | PL_USER),
-		   [stack_size] "r" (kernel_uarg->uspace_stack + THREAD_STACK_SIZE),
+		   [stack_size] "r" (kernel_uarg->uspace_stack + STACK_SIZE),
 		   [ipl] "r" (ipl),
 		   [utext_des] "i" (GDT_SELECTOR(UTEXT_DES) | PL_USER),
Index: kernel/arch/arm32/include/istate.h
===================================================================
--- kernel/arch/arm32/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,13 +35,15 @@
 #define KERN_arm32_ISTATE_H_
 
+#include <trace.h>
+
+#ifdef KERNEL
+
 #include <arch/regutils.h>
 
-#ifdef KERNEL
-#include <typedefs.h>
-#include <trace.h>
-#else
-#include <sys/types.h>
-#define NO_TRACE
-#endif
+#else /* KERNEL */
+
+#include <libarch/regutils.h>
+
+#endif /* KERNEL */
 
 /** Struct representing CPU state saved when an exception occurs. */
Index: rnel/arch/arm32/include/memstr.h
===================================================================
--- kernel/arch/arm32/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2005 Sergey Bondari
- * 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 arm32
- * @{
- */
-/** @file
- *  @brief Memory manipulating functions declarations.
- */
-
-#ifndef KERN_arm32_MEMSTR_H_
-#define KERN_arm32_MEMSTR_H_
-
-#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
-
-extern void memsetw(void *, size_t, uint16_t);
-extern void memsetb(void *, size_t, uint8_t);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/arm32/include/mm/as.h
===================================================================
--- kernel/arch/arm32/include/mm/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,12 +37,10 @@
 #define KERN_arm32_AS_H_
 
-#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH	0
+#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  0
 
-#define KERNEL_ADDRESS_SPACE_START_ARCH     (unsigned long) 0x80000000
-#define KERNEL_ADDRESS_SPACE_END_ARCH       (unsigned long) 0xffffffff
-#define USER_ADDRESS_SPACE_START_ARCH       (unsigned long) 0x00000000
-#define USER_ADDRESS_SPACE_END_ARCH         (unsigned long) 0x7fffffff
-
-#define USTACK_ADDRESS_ARCH	(0x80000000 - PAGE_SIZE)
+#define KERNEL_ADDRESS_SPACE_START_ARCH  UINT32_C(0x80000000)
+#define KERNEL_ADDRESS_SPACE_END_ARCH    UINT32_C(0xffffffff)
+#define USER_ADDRESS_SPACE_START_ARCH    UINT32_C(0x00000000)
+#define USER_ADDRESS_SPACE_END_ARCH      UINT32_C(0x7fffffff)
 
 typedef struct {
Index: kernel/arch/arm32/include/mm/frame.h
===================================================================
--- kernel/arch/arm32/include/mm/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,5 +40,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -69,5 +68,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/arm32/include/mm/page.h
===================================================================
--- kernel/arch/arm32/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,6 +52,4 @@
 #	define PA2KA(x)	((x) + 0x80000000)
 #endif
-
-#ifdef KERNEL
 
 /* Number of entries in each level. */
@@ -320,6 +318,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/arm32/include/regutils.h
===================================================================
--- kernel/arch/arm32/include/regutils.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/include/regutils.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,5 +30,5 @@
  * @{
  */
-/** 
+/**
  * @file
  * @brief Utilities for convenient manipulation with ARM registers.
@@ -38,52 +38,49 @@
 #define KERN_arm32_REGUTILS_H_
 
-#define STATUS_REG_IRQ_DISABLED_BIT (1 << 7)
-#define STATUS_REG_MODE_MASK        0x1f
+#define STATUS_REG_IRQ_DISABLED_BIT  (1 << 7)
+#define STATUS_REG_MODE_MASK         0x1f
 
-#define CP15_R1_HIGH_VECTORS_BIT    (1 << 13)
-
+#define CP15_R1_HIGH_VECTORS_BIT     (1 << 13)
 
 /* ARM Processor Operation Modes */
-#define USER_MODE         0x10
-#define FIQ_MODE          0x11
-#define	IRQ_MODE          0x12
-#define	SUPERVISOR_MODE   0x13
-#define	ABORT_MODE        0x17
-#define	UNDEFINED_MODE    0x1b
-#define	SYSTEM_MODE       0x1f
+#define USER_MODE        0x10
+#define FIQ_MODE         0x11
+#define IRQ_MODE         0x12
+#define SUPERVISOR_MODE  0x13
+#define ABORT_MODE       0x17
+#define UNDEFINED_MODE   0x1b
+#define SYSTEM_MODE      0x1f
 
 /* [CS]PRS manipulation macros */
-#define GEN_STATUS_READ(nm,reg) \
-static inline uint32_t nm## _status_reg_read(void) \
-{ \
-	uint32_t retval; \
-	asm volatile( \
-		"mrs %[retval], " #reg \
-		: [retval] "=r" (retval) \
-	); \
-	return retval; \
-}
+#define GEN_STATUS_READ(nm, reg) \
+	static inline uint32_t nm## _status_reg_read(void) \
+	{ \
+		uint32_t retval; \
+		\
+		asm volatile ( \
+			"mrs %[retval], " #reg \
+			: [retval] "=r" (retval) \
+		); \
+		\
+		return retval; \
+	}
 
-#define GEN_STATUS_WRITE(nm,reg,fieldname, field) \
-static inline void nm## _status_reg_ ##fieldname## _write(uint32_t value) \
-{ \
-	asm volatile( \
-		"msr " #reg "_" #field ", %[value]" \
-		:: [value] "r" (value) \
-	); \
-}
+#define GEN_STATUS_WRITE(nm, reg, fieldname, field) \
+	static inline void nm## _status_reg_ ##fieldname## _write(uint32_t value) \
+	{ \
+		asm volatile ( \
+			"msr " #reg "_" #field ", %[value]" \
+			:: [value] "r" (value) \
+		); \
+	}
 
+/** Return the value of CPSR (Current Program Status Register). */
+GEN_STATUS_READ(current, cpsr);
 
-/** Returns the value of CPSR (Current Program Status Register). */
-GEN_STATUS_READ(current, cpsr)
-
-
-/** Sets control bits of CPSR. */
+/** Set control bits of CPSR. */
 GEN_STATUS_WRITE(current, cpsr, control, c);
 
-
-/** Returns the value of SPSR (Saved Program Status Register). */
-GEN_STATUS_READ(saved, spsr)
-
+/** Return the value of SPSR (Saved Program Status Register). */
+GEN_STATUS_READ(saved, spsr);
 
 #endif
Index: kernel/arch/arm32/include/types.h
===================================================================
--- kernel/arch/arm32/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,4 +44,5 @@
 
 typedef uint32_t size_t;
+typedef int32_t ssize_t;
 
 typedef uint32_t uintptr_t;
Index: kernel/arch/arm32/src/arm32.c
===================================================================
--- kernel/arch/arm32/src/arm32.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/src/arm32.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 #include <config.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <sysinfo/sysinfo.h>
 #include <console/console.h>
@@ -134,5 +134,5 @@
 	uint8_t *stck;
 	
-	stck = &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA];
+	stck = &THREAD->kstack[STACK_SIZE - SP_DELTA];
 	supervisor_sp = (uintptr_t) stck;
 }
Index: kernel/arch/arm32/src/asm.S
===================================================================
--- kernel/arch/arm32/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,7 +29,4 @@
 .text
 
-.global memsetb
-.global memsetw
-.global memcpy
 .global memcpy_from_uspace
 .global memcpy_to_uspace
@@ -38,11 +35,4 @@
 .global early_putchar
 
-memsetb:
-	b _memsetb
-
-memsetw:
-	b _memsetw
-
-memcpy:
 memcpy_from_uspace:
 memcpy_to_uspace:
Index: kernel/arch/arm32/src/exception.c
===================================================================
--- kernel/arch/arm32/src/exception.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/src/exception.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,4 @@
 
 #include <arch/exception.h>
-#include <arch/memstr.h>
 #include <arch/regutils.h>
 #include <arch/machine_func.h>
@@ -175,17 +174,16 @@
 void istate_decode(istate_t *istate)
 {
-	printf("r0 =%#0" PRIx32 "\tr1 =%#0" PRIx32 "\t"
-	    "r2 =%#0" PRIx32 "\tr3 =%#0" PRIx32 "\n",
+	printf("r0 =%0#10" PRIx32 "\tr1 =%0#10" PRIx32 "\t"
+	    "r2 =%0#10" PRIx32 "\tr3 =%0#10" PRIx32 "\n",
 	    istate->r0, istate->r1, istate->r2, istate->r3);
-	printf("r4 =%#" PRIx32 "\tr5 =%#0" PRIx32 "\t"
-	    "r6 =%#0" PRIx32 "\tr7 =%#0" PRIx32 "\n",
+	printf("r4 =%0#10" PRIx32 "\tr5 =%0#10" PRIx32 "\t"
+	    "r6 =%0#10" PRIx32 "\tr7 =%0#10" PRIx32 "\n",
 	    istate->r4, istate->r5, istate->r6, istate->r7);
-	printf("r8 =%#0" PRIx32 "\tr9 =%#0" PRIx32 "\t"
-	    "r10=%#0" PRIx32 "\tfp =%p\n",
-	    istate->r8, istate->r9, istate->r10,
-	    (void *) istate->fp);
-	printf("r12=%#0" PRIx32 "\tsp =%p\tlr =%p\tspsr=%p\n",
-	    istate->r12, (void *) istate->sp,
-	    (void *) istate->lr, (void *) istate->spsr);
+	printf("r8 =%0#10" PRIx32 "\tr9 =%0#10" PRIx32 "\t"
+	    "r10=%0#10" PRIx32 "\tfp =%0#10" PRIx32 "\n",
+	    istate->r8, istate->r9, istate->r10, istate->fp);
+	printf("r12=%0#10" PRIx32 "\tsp =%0#10" PRIx32 "\t"
+	    "lr =%0#10" PRIx32 "\tspsr=%0#10" PRIx32 "\n",
+	    istate->r12, istate->sp, istate->lr, istate->spsr);
 }
 
Index: kernel/arch/arm32/src/mach/gta02/gta02.c
===================================================================
--- kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/src/mach/gta02/gta02.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,5 @@
 #include <mm/page.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/drivers/s3c24xx_uart/s3c24xx_uart.h>
 #include <genarch/drivers/s3c24xx_irqc/s3c24xx_irqc.h>
@@ -158,6 +158,4 @@
 {
 #ifdef CONFIG_FB
-	parea_t fb_parea;
-
 	fb_properties_t prop = {
 		.addr = GTA02_FB_BASE,
@@ -170,18 +168,11 @@
 
 	outdev_t *fb_dev = fb_init(&prop);
-	if (fb_dev) {
+	if (fb_dev)
 		stdout_wire(fb_dev);
-		fb_parea.pbase = GTA02_FB_BASE;
-		fb_parea.frames = 150;
-		fb_parea.unpriv = false;
-		ddi_parea_register(&fb_parea);
-	}
 #endif
 
 	/* Initialize serial port of the debugging console. */
-	s3c24xx_uart_io_t *scons_io;
-
-	scons_io = (void *) hw_map(GTA02_SCONS_BASE, PAGE_SIZE);
-	gta02_scons_dev = s3c24xx_uart_init(scons_io, S3C24XX_INT_UART2);
+	gta02_scons_dev =
+	    s3c24xx_uart_init(GTA02_SCONS_BASE, S3C24XX_INT_UART2);
 
 	if (gta02_scons_dev) {
Index: kernel/arch/arm32/src/mach/integratorcp/integratorcp.c
===================================================================
--- kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -48,10 +48,9 @@
 #include <arch/mach/integratorcp/integratorcp.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <ddi/ddi.h>
 #include <print.h>
 
 #define SDRAM_SIZE	(sdram[((*(uint32_t *)(ICP_CMCR+ICP_SDRAMCR_OFFSET) & ICP_SDRAM_MASK) >> 2)])
-static parea_t fb_parea;
 static icp_hw_map_t icp_hw_map;
 static irq_t icp_timer_irq;
@@ -292,15 +291,10 @@
 		.y = 480,
 		.scan = 2560,
-		.visual = VISUAL_BGR_0_8_8_8,
+		.visual = VISUAL_RGB_8_8_8_0,
 	};
 	
 	outdev_t *fbdev = fb_init(&prop);
-	if (fbdev) {
+	if (fbdev)
 		stdout_wire(fbdev);
-		fb_parea.pbase = ICP_FB;
-		fb_parea.frames = 300;
-		fb_parea.unpriv = false;
-		ddi_parea_register(&fb_parea);
-	}
 #endif
 }
Index: kernel/arch/arm32/src/mach/testarm/testarm.c
===================================================================
--- kernel/arch/arm32/src/mach/testarm/testarm.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/src/mach/testarm/testarm.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 #include <mm/page.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/drivers/dsrln/dsrlnin.h>
 #include <genarch/drivers/dsrln/dsrlnout.h>
Index: kernel/arch/arm32/src/userspace.c
===================================================================
--- kernel/arch/arm32/src/userspace.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/arm32/src/userspace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 
 /** Struct for holding all general purpose registers.
- *  
+ *
  *  Used to set registers when going to userspace.
  */
@@ -60,8 +60,8 @@
 } ustate_t;
 
-/** Changes processor mode and jumps to the address specified in the first
- * parameter.
+/** Change processor mode
  *
- *  @param kernel_uarg	 Userspace settings (entry point, stack, ...).
+ * @param kernel_uarg Userspace settings (entry point, stack, ...).
+ *
  */
 void userspace(uspace_arg_t *kernel_uarg)
@@ -79,10 +79,18 @@
 
 	/* clear other registers */
-	ustate.r3  = ustate.r4  = ustate.r5 = ustate.r6 = ustate.r7 =
-	    ustate.r8 = ustate.r9 = ustate.r10 = ustate.r11 = ustate.r12 =
-	    ustate.lr = 0;
+	ustate.r3 = 0;
+	ustate.r4 = 0;
+	ustate.r5 = 0;
+	ustate.r6 = 0;
+	ustate.r7 = 0;
+	ustate.r8 = 0;
+	ustate.r9 = 0;
+	ustate.r10 = 0;
+	ustate.r11 = 0;
+	ustate.r12 = 0;
+	ustate.lr = 0;
 
 	/* set user stack */
-	ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + PAGE_SIZE;
+	ustate.sp = ((uint32_t)kernel_uarg->uspace_stack) + STACK_SIZE;
 
 	/* set where uspace execution starts */
Index: kernel/arch/ia32/Makefile.inc
===================================================================
--- kernel/arch/ia32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,5 @@
 ENDIANESS = LE
 
-CMN1 = -m32
+CMN1 = -m32 -fno-omit-frame-pointer
 GCC_CFLAGS += $(CMN1)
 ICC_CFLAGS += $(CMN1)
@@ -43,4 +43,8 @@
 ## Accepted CPUs
 #
+
+ifeq ($(PROCESSOR),i486)
+	CMN2 = -march=i486
+endif
 
 ifeq ($(PROCESSOR),athlon_xp)
Index: kernel/arch/ia32/_link.ld.in
===================================================================
--- kernel/arch/ia32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -25,10 +25,10 @@
 	.mapped (PA2KA(BOOT_OFFSET)+SIZEOF(.unmapped)): AT (SIZEOF(.unmapped)) { 
 		ktext_start = .;
-		*(.text);
+		*(.text .text.*);
 		ktext_end = .;
 		
 		kdata_start = .;
 		*(.data);               /* initialized data */
-		*(.rodata*);            /* string literals */
+		*(.rodata .rodata.*);   /* string literals */
 		*(COMMON);              /* global variables */
 		hardcoded_load_address = .;
Index: kernel/arch/ia32/include/asm.h
===================================================================
--- kernel/arch/ia32/include/asm.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/asm.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -113,5 +113,5 @@
 NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outb %b[val], %w[port]\n"
@@ -119,5 +119,5 @@
 		);	
 	} else {
-		*((uint8_t *) port) = val;
+		*port = val;
 	}
 }
@@ -133,5 +133,5 @@
 NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outw %w[val], %w[port]\n"
@@ -139,5 +139,5 @@
 		);
 	} else {
-		*((uint16_t *) port) = val;
+		*port = val;
 	}
 }
@@ -153,5 +153,5 @@
 NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outl %[val], %w[port]\n"
@@ -159,5 +159,5 @@
 		);
 	} else {
-		*((uint32_t *) port) = val;
+		*port = val;
 	}
 }
@@ -328,4 +328,6 @@
 }
 
+#ifndef PROCESSOR_i486
+
 /** Write to MSR */
 NO_TRACE static inline void write_msr(uint32_t msr, uint64_t value)
@@ -352,4 +354,6 @@
 	return ((uint64_t) dx << 32) | ax;
 }
+
+#endif /* PROCESSOR_i486 */
 
 
Index: kernel/arch/ia32/include/atomic.h
===================================================================
--- kernel/arch/ia32/include/atomic.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/atomic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -121,5 +121,7 @@
 	asm volatile (
 		"0:\n"
+#ifndef PROCESSOR_i486
 		"pause\n"        /* Pentium 4's HT love this instruction */
+#endif
 		"mov %[count], %[tmp]\n"
 		"testl %[tmp], %[tmp]\n"
Index: kernel/arch/ia32/include/barrier.h
===================================================================
--- kernel/arch/ia32/include/barrier.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -54,4 +54,5 @@
 NO_TRACE static inline void cpuid_serialization(void)
 {
+#ifndef __IN_SHARED_LIBC__
 	asm volatile (
 		"xorl %%eax, %%eax\n"
@@ -59,4 +60,14 @@
 		::: "eax", "ebx", "ecx", "edx", "memory"
 	);
+#else
+	/* Must not clobber PIC register ebx */
+	asm volatile (
+		"movl %%ebx, %%esi\n"
+		"xorl %%eax, %%eax\n"
+		"cpuid\n"
+		"movl %%esi, %%ebx\n"
+		::: "eax", "ecx", "edx", "esi", "memory"
+	);
+#endif
 }
 
Index: kernel/arch/ia32/include/boot/boot.h
===================================================================
--- kernel/arch/ia32/include/boot/boot.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/boot/boot.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,4 +43,6 @@
 #define MULTIBOOT_HEADER_FLAGS  0x00010003
 
+#define MULTIBOOT_LOADER_MAGIC  0x2BADB002
+
 #ifndef __ASM__
 
Index: kernel/arch/ia32/include/context.h
===================================================================
--- kernel/arch/ia32/include/context.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/context.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,4 @@
 #define KERN_ia32_CONTEXT_H_
 
-#ifdef KERNEL
-
 #include <typedefs.h>
 
@@ -57,6 +55,4 @@
 	} while (0)
 
-#endif /* KERNEL */
-
 /*
  * Only save registers that must be preserved across
Index: kernel/arch/ia32/include/cycle.h
===================================================================
--- kernel/arch/ia32/include/cycle.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/cycle.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,4 +40,7 @@
 NO_TRACE static inline uint64_t get_cycle(void)
 {
+#ifdef PROCESSOR_i486
+	return 0;
+#else
 	uint64_t v;
 	
@@ -48,4 +51,5 @@
 	
 	return v;
+#endif
 }
 
Index: kernel/arch/ia32/include/elf.h
===================================================================
--- kernel/arch/ia32/include/elf.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ia32	
+/** @addtogroup ia32
  * @{
  */
@@ -36,7 +36,7 @@
 #define KERN_ia32_ELF_H_
 
-#define	ELF_MACHINE		EM_386
-#define ELF_DATA_ENCODING	ELFDATA2LSB
-#define ELF_CLASS		ELFCLASS32
+#define ELF_MACHINE        EM_386
+#define ELF_DATA_ENCODING  ELFDATA2LSB
+#define ELF_CLASS          ELFCLASS32
 
 #endif
Index: kernel/arch/ia32/include/istate.h
===================================================================
--- kernel/arch/ia32/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,16 +36,5 @@
 #define KERN_ia32_ISTATE_H_
 
-#ifdef KERNEL
-
-#include <typedefs.h>
 #include <trace.h>
-
-#else /* KERNEL */
-
-#include <sys/types.h>
-
-#define NO_TRACE
-
-#endif /* KERNEL */
 
 typedef struct istate {
Index: rnel/arch/ia32/include/memstr.h
===================================================================
--- kernel/arch/ia32/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2005 Sergey Bondari
- * 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 ia32
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_ia32_MEMSTR_H_
-#define KERN_ia32_MEMSTR_H_
-
-#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
-
-extern void memsetw(void *, size_t, uint16_t);
-extern void memsetb(void *, size_t, uint8_t);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/ia32/include/mm/as.h
===================================================================
--- kernel/arch/ia32/include/mm/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,6 +43,4 @@
 #define USER_ADDRESS_SPACE_END_ARCH      UINT32_C(0x7fffffff)
 
-#define USTACK_ADDRESS_ARCH  (USER_ADDRESS_SPACE_END_ARCH - (PAGE_SIZE - 1))
-
 typedef struct {
 } as_arch_t;
Index: kernel/arch/ia32/include/mm/frame.h
===================================================================
--- kernel/arch/ia32/include/mm/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -50,5 +49,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/ia32/include/mm/page.h
===================================================================
--- kernel/arch/ia32/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,6 +42,4 @@
 #define PAGE_SIZE   FRAME_SIZE
 
-#ifdef KERNEL
-
 #ifndef __ASM__
 
@@ -201,6 +199,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/ia32/include/types.h
===================================================================
--- kernel/arch/ia32/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
 
 typedef uint32_t size_t;
+typedef int32_t ssize_t;
 
 typedef uint32_t uintptr_t;
Index: kernel/arch/ia32/src/asm.S
===================================================================
--- kernel/arch/ia32/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,7 +38,4 @@
 .global paging_on
 .global enable_l_apic_in_msr
-.global memsetb
-.global memsetw
-.global memcpy
 .global memcpy_from_uspace
 .global memcpy_from_uspace_failover_address
@@ -47,12 +44,4 @@
 .global early_putchar
 
-/* Wrapper for generic memsetb */
-memsetb:
-	jmp _memsetb
-
-/* Wrapper for generic memsetw */
-memsetw:
-	jmp _memsetw
-
 #define MEMCPY_DST   4
 #define MEMCPY_SRC   8
@@ -74,5 +63,4 @@
  *
  */
-memcpy:
 memcpy_from_uspace:
 memcpy_to_uspace:
@@ -417,5 +405,11 @@
 	xorl %eax, %eax
 	cmpl $(GDT_SELECTOR(KTEXT_DES)), ISTATE_OFFSET_CS(%esp)
+#ifdef PROCESSOR_i486
+	jz 0f
+		movl %eax, %ebp
+	0:
+#else
 	cmovnzl %eax, %ebp
+#endif
 
 	movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
Index: kernel/arch/ia32/src/boot/boot.S
===================================================================
--- kernel/arch/ia32/src/boot/boot.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/boot/boot.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -97,4 +97,10 @@
 	pm_status $status_prot
 	
+#include "vesa_prot.inc"
+	
+#ifndef PROCESSOR_i486
+	
+	pm_status $status_prot2
+	
 	movl $(INTEL_CPUID_LEVEL), %eax
 	cpuid
@@ -105,16 +111,20 @@
 	cpuid
 	bt $(INTEL_PSE), %edx
-	jc pse_supported
+	jnc pse_unsupported
+		
+		/* Map kernel and turn paging on */
+		pm_status $status_pse
+		call map_kernel_pse
+		jmp stack_init
+	
+#endif /* PROCESSOR_i486 */
 	
 	pse_unsupported:
 		
-		pm_error $err_pse
-	
-	pse_supported:
-	
-#include "vesa_prot.inc"
-	
-	/* Map kernel and turn paging on */
-	call map_kernel
+		/* Map kernel and turn paging on */
+		pm_status $status_non_pse
+		call map_kernel
+	
+	stack_init:
 	
 	/* Create the first stack frame */
@@ -122,5 +132,5 @@
 	movl %esp, %ebp
 	
-	pm2_status $status_prot2
+	pm2_status $status_prot3
 	
 	/* Call arch_pre_main(grub_eax, grub_ebx) */
@@ -140,5 +150,5 @@
 		jmp hlt0
 
-/** Setup mapping for the kernel.
+/** Setup mapping for the kernel (PSE variant)
  *
  * Setup mapping for both the unmapped and mapped sections
@@ -146,6 +156,7 @@
  *
  */
-.global map_kernel
-map_kernel:
+.global map_kernel_pse
+map_kernel_pse:
+	/* Paging features */
 	movl %cr4, %ecx
 	orl $(1 << 4), %ecx      /* PSE on */
@@ -158,5 +169,5 @@
 	xorl %ebx, %ebx
 	
-	floop:
+	floop_pse:
 		movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
 		orl %ebx, %eax
@@ -169,5 +180,5 @@
 		incl %ecx
 		cmpl $512, %ecx
-		jl floop
+		jl floop_pse
 	
 	movl %esi, %cr3
@@ -177,4 +188,179 @@
 	movl %ebx, %cr0
 	ret
+
+/** Setup mapping for the kernel (non-PSE variant).
+ *
+ * Setup mapping for both the unmapped and mapped sections
+ * of the kernel. For simplicity, we map the entire 4G space.
+ *
+ */
+.global map_kernel
+map_kernel:
+	/* Paging features */
+	movl %cr4, %ecx
+	andl $(~(1 << 5)), %ecx  /* PAE off */
+	movl %ecx, %cr4
+	
+	call calc_kernel_end
+	call find_mem_for_pt
+	
+	mov kernel_end, %esi
+	mov free_area, %ecx
+	
+	cmpl %esi, %ecx
+	jbe use_kernel_end
+		
+		mov %ecx, %esi
+		
+		/* Align address down to 4k */
+		andl $(~4095), %esi
+		
+	use_kernel_end:
+		
+		/* Align address to 4k */
+		addl $4095, %esi
+		andl $(~4095), %esi
+		
+		/* Allocate space for page tables */
+		movl %esi, pt_loc
+		movl $ballocs, %edi
+		andl $0x7fffffff, %edi
+		
+		movl %esi, (%edi)
+		addl $4, %edi
+		movl $(2 * 1024 * 1024), (%edi)
+		
+		/* Fill page tables */
+		xorl %ecx, %ecx
+		xorl %ebx, %ebx
+		
+		floop_pt:
+			movl $((1 << 1) | (1 << 0)), %eax
+			orl %ebx, %eax
+			movl %eax, (%esi, %ecx, 4)
+			addl $(4 * 1024), %ebx
+			
+			incl %ecx
+			cmpl $(512 * 1024), %ecx
+			
+			jl floop_pt
+		
+		/* Fill page directory */
+		movl $(page_directory + 0), %esi
+		movl $(page_directory + 2048), %edi
+		xorl %ecx, %ecx
+		movl pt_loc, %ebx
+		
+		floop:
+			movl $((1 << 1) | (1 << 0)), %eax
+			orl %ebx, %eax
+			
+			/* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
+			movl %eax, (%esi, %ecx, 4)
+			
+			/* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
+			movl %eax, (%edi, %ecx, 4)
+			addl $(4 * 1024), %ebx
+			
+			incl %ecx
+			cmpl $512, %ecx
+			
+			jl floop
+		
+		movl %esi, %cr3
+		
+		movl %cr0, %ebx
+		orl $(1 << 31), %ebx  /* paging on */
+		movl %ebx, %cr0
+		
+		ret
+
+/** Calculate unmapped address of the end of the kernel. */
+calc_kernel_end:
+	movl $hardcoded_load_address, %edi
+	andl $0x7fffffff, %edi
+	movl (%edi), %esi
+	andl $0x7fffffff, %esi
+	
+	movl $hardcoded_ktext_size, %edi
+	andl $0x7fffffff, %edi
+	addl (%edi), %esi
+	andl $0x7fffffff, %esi
+	
+	movl $hardcoded_kdata_size, %edi
+	andl $0x7fffffff, %edi
+	addl (%edi), %esi
+	andl $0x7fffffff, %esi
+	movl %esi, kernel_end
+	
+	ret
+
+/** Find free 2M (+4k for alignment) region where to store page tables */
+find_mem_for_pt:
+	/* Check if multiboot info is present */
+	cmpl $MULTIBOOT_LOADER_MAGIC, grub_eax
+	je check_multiboot_map
+		
+		ret
+	
+	check_multiboot_map:
+		
+		/* Copy address of the multiboot info to ebx */
+		movl grub_ebx, %ebx
+		
+		/* Check if memory map flag is present */
+		movl (%ebx), %edx
+		andl $(1 << 6), %edx
+		jnz use_multiboot_map
+			
+			ret
+		
+	use_multiboot_map:
+		
+		/* Copy address of the memory map to edx */
+		movl 48(%ebx), %edx
+		movl %edx, %ecx
+		
+		addl 44(%ebx), %ecx
+		
+		/* Find a free region at least 2M in size */
+		check_memmap_loop:
+			
+			/* Is this a free region? */
+			cmp $1, 20(%edx)
+			jnz next_region
+			
+			/* Check size */
+			cmp $0, 16(%edx)
+			jnz next_region
+			
+			cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
+			jbe next_region
+			
+			cmp $0, 8(%edx)
+			jz found_region
+		
+		next_region:
+			
+			cmp %ecx, %edx
+			jbe next_region_do
+			
+				ret
+		
+		next_region_do:
+			
+			addl (%edx), %edx
+			addl $4, %edx
+			jmp check_memmap_loop
+			
+		found_region:
+			
+			/* Use end of the found region */
+			mov 4(%edx), %ecx
+			add 12(%edx), %ecx
+			sub $(2 * 1024 * 1024), %ecx
+			mov %ecx, free_area
+			
+			ret
 
 /** Print string to EGA display (in light red) and halt.
@@ -521,13 +707,20 @@
 grub_eax:
 	.long 0
-
 grub_ebx:
 	.long 0
 
-err_pse:
-	.asciz "Page Size Extension not supported. System halted."
+pt_loc:
+	.long 0
+kernel_end:
+	.long 0
+free_area:
+	.long 0
 
 status_prot:
 	.asciz "[prot] "
+status_pse:
+	.asciz "[pse] "
+status_non_pse:
+	.asciz "[non_pse] "
 status_vesa_copy:
 	.asciz "[vesa_copy] "
@@ -538,4 +731,6 @@
 status_prot2:
 	.asciz "[prot2] "
+status_prot3:
+	.asciz "[prot3] "
 status_main:
 	.asciz "[main] "
Index: kernel/arch/ia32/src/boot/vesa_real.inc
===================================================================
--- kernel/arch/ia32/src/boot/vesa_real.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/boot/vesa_real.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -154,4 +154,14 @@
 	mov $e_vesa_init - vesa_init, %di
 	push %di
+	/* Write the "VBE2" signature into the info structure in order
+	 * to get proper mode information. The presence of "VBE2"
+	 * indicates two things:
+	 *
+	 *  - VBE controller information structure is expected to be
+	 *    512 bytes long instead of 256 bytes.
+	 *  - The BIOS should report VBE 3.0 information (potentially
+	 *    including non-standard modes in the mode list).
+	 */
+	movl $0x32454256, (%di)
 	int $0x10
 	
Index: kernel/arch/ia32/src/cpu/cpu.c
===================================================================
--- kernel/arch/ia32/src/cpu/cpu.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/cpu/cpu.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -92,5 +92,4 @@
 void cpu_arch_init(void)
 {
-	cpuid_extended_feature_info efi;
 	cpu_info_t info;
 	uint32_t help = 0;
@@ -104,5 +103,4 @@
 	
 	CPU->arch.fi.word = info.cpuid_edx;
-	efi.word = info.cpuid_ecx;
 	
 	if (CPU->arch.fi.bits.fxsr)
@@ -120,9 +118,11 @@
 		);
 	}
-	
+
+#ifndef PROCESSOR_i486
 	if (CPU->arch.fi.bits.sep) {
 		/* Setup fast SYSENTER/SYSEXIT syscalls */
 		syscall_setup_cpu();
 	}
+#endif
 }
 
Index: kernel/arch/ia32/src/drivers/vesa.c
===================================================================
--- kernel/arch/ia32/src/drivers/vesa.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/drivers/vesa.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,4 @@
 
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
 #include <arch/drivers/vesa.h>
 #include <console/chardev.h>
Index: kernel/arch/ia32/src/interrupt.c
===================================================================
--- kernel/arch/ia32/src/interrupt.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/interrupt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -66,25 +66,24 @@
 void istate_decode(istate_t *istate)
 {
-	printf("cs =%#0" PRIx32 "\teip=%p\t"
-	    "efl=%#0" PRIx32 "\terr=%#0" PRIx32 "\n",
-	    istate->cs, (void *) istate->eip,
-	    istate->eflags, istate->error_word);
-	
-	printf("ds =%#0" PRIx32 "\tes =%#0" PRIx32 "\t"
-	    "fs =%#0" PRIx32 "\tgs =%#0" PRIx32 "\n",
+	printf("cs =%0#10" PRIx32 "\teip=%0#10" PRIx32 "\t"
+	    "efl=%0#10" PRIx32 "\terr=%0#10" PRIx32 "\n",
+	    istate->cs, istate->eip, istate->eflags, istate->error_word);
+	
+	printf("ds =%0#10" PRIx32 "\tes =%0#10" PRIx32 "\t"
+	    "fs =%0#10" PRIx32 "\tgs =%0#10" PRIx32 "\n",
 	    istate->ds, istate->es, istate->fs, istate->gs);
 	
 	if (istate_from_uspace(istate))
-		printf("ss =%#0" PRIx32 "\n", istate->ss);
-	
-	printf("eax=%#0" PRIx32 "\tebx=%#0" PRIx32 "\t"
-	    "ecx=%#0" PRIx32 "\tedx=%#0" PRIx32 "\n",
+		printf("ss =%0#10" PRIx32 "\n", istate->ss);
+	
+	printf("eax=%0#10" PRIx32 "\tebx=%0#10" PRIx32 "\t"
+	    "ecx=%0#10" PRIx32 "\tedx=%0#10" PRIx32 "\n",
 	    istate->eax, istate->ebx, istate->ecx, istate->edx);
 	
-	printf("esi=%p\tedi=%p\tebp=%p\tesp=%p\n",
-	    (void *) istate->esi, (void *) istate->edi,
-	    (void *) istate->ebp,
-	    istate_from_uspace(istate) ? ((void *) istate->esp) :
-	    &istate->esp);
+	printf("esi=%0#10" PRIx32 "\tedi=%0#10" PRIx32 "\t"
+	    "ebp=%0#10" PRIx32 "\tesp=%0#10" PRIx32 "\n",
+	    istate->esi, istate->edi, istate->ebp,
+	    istate_from_uspace(istate) ? istate->esp :
+	    (uintptr_t) &istate->esp);
 }
 
Index: kernel/arch/ia32/src/proc/scheduler.c
===================================================================
--- kernel/arch/ia32/src/proc/scheduler.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/proc/scheduler.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -58,10 +58,12 @@
 void before_thread_runs_arch(void)
 {
-	uintptr_t kstk = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE];
+	uintptr_t kstk = (uintptr_t) &THREAD->kstack[STACK_SIZE];
 	
+#ifndef PROCESSOR_i486
 	if (CPU->arch.fi.bits.sep) {
 		/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */
 		write_msr(IA32_MSR_SYSENTER_ESP, kstk - sizeof(istate_t));
 	}
+#endif
 	
 	/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */
Index: kernel/arch/ia32/src/smp/smp.c
===================================================================
--- kernel/arch/ia32/src/smp/smp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/smp/smp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,5 +42,4 @@
 #include <config.h>
 #include <synch/waitq.h>
-#include <synch/synch.h>
 #include <arch/pm.h>
 #include <func.h>
Index: kernel/arch/ia32/src/syscall.c
===================================================================
--- kernel/arch/ia32/src/syscall.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/syscall.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,4 +39,6 @@
 #include <arch/pm.h>
 
+#ifndef PROCESSOR_i486
+
 /** Enable & setup support for SYSENTER/SYSEXIT */
 void syscall_setup_cpu(void)
@@ -50,4 +52,6 @@
 }
 
+#endif /* PROCESSOR_i486 */
+
 /** @}
  */
Index: kernel/arch/ia32/src/userspace.c
===================================================================
--- kernel/arch/ia32/src/userspace.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia32/src/userspace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,7 +37,6 @@
 #include <typedefs.h>
 #include <arch.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <mm/as.h>
-
 
 /** Enter userspace
@@ -76,5 +75,5 @@
 		:
 		: [udata_des] "i" (GDT_SELECTOR(UDATA_DES) | PL_USER),
-		  [stack_size] "r" ((uint8_t *) kernel_uarg->uspace_stack + THREAD_STACK_SIZE),
+		  [stack_size] "r" ((uint8_t *) kernel_uarg->uspace_stack + STACK_SIZE),
 		  [ipl] "r" (ipl),
 		  [utext_des] "i" (GDT_SELECTOR(UTEXT_DES) | PL_USER),
Index: kernel/arch/ia64/_link.ld.in
===================================================================
--- kernel/arch/ia64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -16,5 +16,5 @@
 		ktext_start = .;
 		*(K_TEXT_START);
-		*(.text)
+		*(.text .text.*)
 		ktext_end = .;
 		
@@ -30,4 +30,5 @@
 		hardcoded_kdata_size = .;
 		QUAD(kdata_end - kdata_start);
+		__gp = .;
 		*(.got .got.*)
 		*(.sdata)
@@ -36,15 +37,14 @@
 		*(.bss)
 		*(COMMON);
-
+		
 		. = ALIGN(8);
-                symbol_table = .;
-                *(symtab.*);            /* Symbol table, must be LAST symbol!*/
-
+		symbol_table = .;
+		*(symtab.*);            /* Symbol table, must be LAST symbol!*/
+		
 		kdata_end = .;
 	}
-
+	
 	/DISCARD/ : {
 		*(*);
 	}
-
 }
Index: kernel/arch/ia64/include/arch.h
===================================================================
--- kernel/arch/ia64/include/arch.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/arch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,4 @@
 #define KERN_ia64_ARCH_H_
 
-#define LOADED_PROG_STACK_PAGES_NO 2
-
 #include <arch/drivers/ski.h>
 
Index: kernel/arch/ia64/include/asm.h
===================================================================
--- kernel/arch/ia64/include/asm.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/asm.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -122,38 +122,20 @@
 }
 
-/** Return base address of current stack
- *
- * Return the base address of the current stack.
- * The stack is assumed to be STACK_SIZE long.
- * The stack must start on page boundary.
- *
+/** Return base address of current memory stack.
+ *
+ * The memory stack is assumed to be STACK_SIZE / 2 long. Note that there is
+ * also the RSE stack, which takes up the upper half of STACK_SIZE.
+ * The memory stack must start on page boundary.
  */
 NO_TRACE static inline uintptr_t get_stack_base(void)
 {
-	uint64_t v;
-	
-	/*
-	 * I'm not sure why but this code inlines badly
-	 * in scheduler, resulting in THE shifting about
-	 * 16B and causing kernel panic.
-	 *
-	 * asm volatile (
-	 *     "and %[value] = %[mask], r12"
-	 *     : [value] "=r" (v)
-	 *     : [mask] "r" (~(STACK_SIZE - 1))
-	 * );
-	 * return v;
-	 *
-	 * The following code has the same semantics but
-	 * inlines correctly.
-	 *
-	 */
+	uint64_t value;
 	
 	asm volatile (
 		"mov %[value] = r12"
-		: [value] "=r" (v)
-	);
-	
-	return (v & (~(STACK_SIZE - 1)));
+		: [value] "=r" (value)
+	);
+	
+	return (value & (~(STACK_SIZE / 2 - 1)));
 }
 
Index: kernel/arch/ia64/include/bootinfo.h
===================================================================
--- kernel/arch/ia64/include/bootinfo.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/bootinfo.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,5 +34,5 @@
 #define MEMMAP_ITEMS 128
 
-#define EFI_MEMMAP_FREE_MEM 0
+#define MEMMAP_FREE_MEM 0
 
 /** Size of buffer for storing task name in binit_task_t. */
@@ -54,10 +54,10 @@
 	unsigned long base;
 	unsigned long size;
-} efi_memmap_item_t;
+} memmap_item_t;
 
 typedef struct {
 	binit_t taskmap;
 	
-	efi_memmap_item_t memmap[MEMMAP_ITEMS];
+	memmap_item_t memmap[MEMMAP_ITEMS];
 	unsigned int memmap_items;
 	
@@ -66,5 +66,4 @@
 	unsigned long freq_scale;
 	unsigned int wakeup_intno;
-	int hello_configured;
 } bootinfo_t;
 
Index: kernel/arch/ia64/include/context.h
===================================================================
--- kernel/arch/ia64/include/context.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/context.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -49,11 +49,11 @@
 #define SP_DELTA	(0 + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT))
 
-/* RSE stack starts at the bottom of memory stack. */
+/* RSE stack starts at the bottom of memory stack, hence the division by 2. */
 #define context_set(c, _pc, stack, size)								\
 	do {												\
 		(c)->pc = (uintptr_t) _pc;								\
-		(c)->bsp = ((uintptr_t) stack) + ALIGN_UP((size), REGISTER_STACK_ALIGNMENT);		\
+		(c)->bsp = ((uintptr_t) stack) + ALIGN_UP((size / 2), REGISTER_STACK_ALIGNMENT);	\
 		(c)->ar_pfs &= PFM_MASK; 								\
-		(c)->sp = ((uintptr_t) stack) + ALIGN_UP((size), STACK_ALIGNMENT) - SP_DELTA;		\
+		(c)->sp = ((uintptr_t) stack) + ALIGN_UP((size / 2), STACK_ALIGNMENT) - SP_DELTA;	\
 	} while (0);
 
Index: kernel/arch/ia64/include/elf.h
===================================================================
--- kernel/arch/ia64/include/elf.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ia64	
+/** @addtogroup ia64
  * @{
  */
@@ -36,7 +36,7 @@
 #define KERN_ia64_ELF_H_
 
-#define	ELF_MACHINE		EM_IA_64
-#define ELF_DATA_ENCODING	ELFDATA2LSB
-#define ELF_CLASS		ELFCLASS64
+#define ELF_MACHINE        EM_IA_64
+#define ELF_DATA_ENCODING  ELFDATA2LSB
+#define ELF_CLASS          ELFCLASS64
 
 #endif
Index: kernel/arch/ia64/include/istate.h
===================================================================
--- kernel/arch/ia64/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,13 +36,15 @@
 #define KERN_ia64_ISTATE_H_
 
+#include <trace.h>
+
+#ifdef KERNEL
+
 #include <arch/register.h>
 
-#ifdef KERNEL
-#include <typedefs.h>
-#include <trace.h>
-#else
-#include <sys/types.h>
-#define NO_TRACE
-#endif
+#else /* KERNEL */
+
+#include <libarch/register.h>
+
+#endif /* KERNEL */
 
 typedef struct istate {
Index: rnel/arch/ia64/include/memstr.h
===================================================================
--- kernel/arch/ia64/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2005 Sergey Bondari
- * 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 ia64
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_ia64_MEMSTR_H_
-#define KERN_ia64_MEMSTR_H_
-
-#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
-
-extern void memsetw(void *, size_t, uint16_t);
-extern void memsetb(void *, size_t, uint8_t);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/ia64/include/mm/as.h
===================================================================
--- kernel/arch/ia64/include/mm/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,10 +38,10 @@
 #define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  0
 
-#define KERNEL_ADDRESS_SPACE_START_ARCH  ((unsigned long) 0xe000000000000000ULL)
-#define KERNEL_ADDRESS_SPACE_END_ARCH    ((unsigned long) 0xffffffffffffffffULL)
-#define USER_ADDRESS_SPACE_START_ARCH    ((unsigned long) 0x0000000000000000ULL)
-#define USER_ADDRESS_SPACE_END_ARCH      ((unsigned long) 0xdfffffffffffffffULL)
+#define KERNEL_ADDRESS_SPACE_START_ARCH  UINT64_C(0xe000000000000000)
+#define KERNEL_ADDRESS_SPACE_END_ARCH    UINT64_C(0xffffffffffffffff)
+#define USER_ADDRESS_SPACE_START_ARCH    UINT64_C(0x0000000000000000)
+#define USER_ADDRESS_SPACE_END_ARCH      UINT64_C(0xdfffffffffffffff)
 
-#define USTACK_ADDRESS_ARCH  0x0000000ff0000000ULL
+#define USTACK_ADDRESS_ARCH  UINT64_C(0x0000000ff0000000)
 
 typedef struct {
Index: kernel/arch/ia64/include/mm/frame.h
===================================================================
--- kernel/arch/ia64/include/mm/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -49,8 +48,5 @@
 #define physmem_print()
 
-#define ARCH_STACK_FRAMES TWO_FRAMES
-
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/ia64/include/mm/page.h
===================================================================
--- kernel/arch/ia64/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,6 +41,4 @@
 #define PAGE_SIZE   FRAME_SIZE
 #define PAGE_WIDTH  FRAME_WIDTH
-
-#ifdef KERNEL
 
 /** Bit width of the TLB-locked portion of kernel address space. */
@@ -316,6 +314,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/ia64/include/register.h
===================================================================
--- kernel/arch/ia64/include/register.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/register.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -60,4 +60,7 @@
 #define PSR_CPL_SHIFT         32
 #define PSR_CPL_MASK_SHIFTED  3
+
+#define PSR_RI_SHIFT  41
+#define PSR_RI_LEN    2
 
 #define PFM_MASK  (~0x3fffffffff)
@@ -142,10 +145,4 @@
 #ifndef __ASM__
 
-#ifdef KERNEL
-#include <typedefs.h>
-#else
-#include <sys/types.h>
-#endif
-
 /** Processor Status Register. */
 typedef union {
Index: kernel/arch/ia64/include/types.h
===================================================================
--- kernel/arch/ia64/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
 
 typedef uint64_t size_t;
+typedef int64_t ssize_t;
 
 typedef uint64_t uintptr_t;
Index: kernel/arch/ia64/src/asm.S
===================================================================
--- kernel/arch/ia64/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,5 +30,4 @@
 
 .text
-.global memcpy
 .global memcpy_from_uspace
 .global memcpy_to_uspace
@@ -39,5 +38,6 @@
  *
  * This memcpy() has been taken from the assembler output of
- * the generic _memcpy() and modified to have the failover part.
+ * a plain C implementation of memcpy() modified to have the
+ * failover part.
  *
  * @param in0 Destination address.
@@ -46,5 +46,4 @@
  *
  */
-memcpy:
 memcpy_from_uspace:
 memcpy_to_uspace:
@@ -141,12 +140,4 @@
 	br.ret.sptk.many rp
 
-.global memsetb
-memsetb:
-	br _memsetb
-
-.global memsetw
-memsetw:
-	br _memsetw
-
 .global cpu_halt
 cpu_halt:
Index: kernel/arch/ia64/src/drivers/ski.c
===================================================================
--- kernel/arch/ia64/src/drivers/ski.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/src/drivers/ski.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -57,5 +57,5 @@
 };
 
-static void ski_putchar(outdev_t *, const wchar_t, bool);
+static void ski_putchar(outdev_t *, const wchar_t);
 
 static outdev_operations_t skidev_ops = {
@@ -99,7 +99,4 @@
 static void poll_keyboard(ski_instance_t *instance)
 {
-	if (silent)
-		return;
-	
 	int count = POLL_LIMIT;
 	
@@ -121,5 +118,8 @@
 	
 	while (true) {
-		if (!silent)
+		// TODO FIXME:
+		// This currently breaks the kernel console
+		// before we get the override from uspace.
+		if (console_override)
 			poll_keyboard(instance);
 		
@@ -182,10 +182,12 @@
  * @param dev    Character device.
  * @param ch     Character to be printed.
- * @param silent Whether the output should be silenced.
- *
- */
-static void ski_putchar(outdev_t *dev, const wchar_t ch, bool silent)
-{
-	if (!silent) {
+ *
+ */
+static void ski_putchar(outdev_t *dev, const wchar_t ch)
+{
+	// TODO FIXME:
+	// This currently breaks the kernel console
+	// before we get the override from uspace.
+	if (console_override) {
 		if (ascii_check(ch)) {
 			if (ch == '\n')
@@ -213,5 +215,6 @@
 	if (!fb_exported) {
 		/*
-		 * This is the necessary evil until the userspace driver is entirely
+		 * This is the necessary evil until
+		 * the userspace driver is entirely
 		 * self-sufficient.
 		 */
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/src/ia64.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -50,5 +50,5 @@
 #include <userspace.h>
 #include <console/console.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <syscall/syscall.h>
 #include <ddi/irq.h>
@@ -151,5 +151,5 @@
 	/* Set platform name. */
 #ifdef MACHINE_ski
-	platform = "pc";
+	platform = "ski";
 #endif
 #ifdef MACHINE_i460GX
@@ -249,8 +249,14 @@
 	rsc.mode = 3;			/* eager mode */
 
+	/*
+	 * Switch to userspace.
+	 *
+	 * When calculating stack addresses, mind the stack split between the
+	 * memory stack and the RSE stack. Each occuppies STACK_SIZE / 2 bytes.
+	 */
 	switch_to_userspace((uintptr_t) kernel_uarg->uspace_entry,
-	    ((uintptr_t) kernel_uarg->uspace_stack) + PAGE_SIZE -
+	    ((uintptr_t) kernel_uarg->uspace_stack) + STACK_SIZE / 2 -
 	    ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT),
-	    ((uintptr_t) kernel_uarg->uspace_stack) + PAGE_SIZE,
+	    ((uintptr_t) kernel_uarg->uspace_stack) + STACK_SIZE / 2,
 	    (uintptr_t) kernel_uarg->uspace_uarg, psr.value, rsc.value);
 
Index: kernel/arch/ia64/src/ivt.S
===================================================================
--- kernel/arch/ia64/src/ivt.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/src/ivt.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -50,4 +50,39 @@
 #define R_KSTACK_BSP	r22	/* keep in sync with before_thread_runs_arch() */
 #define R_KSTACK	r23	/* keep in sync with before_thread_runs_arch() */
+
+/* Speculation vector handler */
+.macro SPECULATION_VECTOR_HANDLER offs
+    .org ivt + \offs
+
+    /* 1. Save predicates, IIM, IIP, IPSR and ISR CR's in bank 0 registers. */
+	mov r16 = pr
+	mov r17 = cr.iim
+	mov r18 = cr.iip
+	mov r19 = cr.ipsr
+	mov r20 = cr.isr ;;
+	
+    /* 2. Move IIP to IIPA. */
+	mov cr.iipa = r18
+	
+    /* 3. Sign extend IIM[20:0], shift left by 4 and add to IIP. */
+	shl r17 = r17, 43 ;;	/* shift bit 20 to bit 63 */
+	shr r17 = r17, 39 ;;	/* signed shift right to bit 24 */
+	add r18 = r18, r17 ;;
+	mov cr.iip = r18
+	
+    /* 4. Set IPSR.ri to 0. */
+	dep r19 = 0, r19, PSR_RI_SHIFT, PSR_RI_LEN ;;
+	mov cr.ipsr = r19
+	
+    /* 5. Check whether IPSR.tb or IPSR.ss is set. */
+
+	/* TODO:
+	 * Implement this when Taken Branch and Single Step traps can occur.
+	 */
+    
+    /* 6. Restore predicates and return from interruption. */
+	mov pr = r16 ;;
+	rfi
+.endm
 
 /** Heavyweight interrupt handler
@@ -391,5 +426,5 @@
 
     /* 10. call handler */
-    	movl r1 = kernel_image_start
+    	movl r1 = __gp
     
     	mov b1 = loc2
@@ -541,5 +576,5 @@
 	HEAVYWEIGHT_HANDLER 0x5500 disabled_fp_register
 	HEAVYWEIGHT_HANDLER 0x5600
-	HEAVYWEIGHT_HANDLER 0x5700
+	SPECULATION_VECTOR_HANDLER 0x5700
 	HEAVYWEIGHT_HANDLER 0x5800
 	HEAVYWEIGHT_HANDLER 0x5900
Index: kernel/arch/ia64/src/mm/frame.c
===================================================================
--- kernel/arch/ia64/src/mm/frame.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/src/mm/frame.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -58,5 +58,5 @@
 		unsigned int i;
 		for (i = 0; i < bootinfo->memmap_items; i++) {
-			if (bootinfo->memmap[i].type == EFI_MEMMAP_FREE_MEM) {
+			if (bootinfo->memmap[i].type == MEMMAP_FREE_MEM) {
 				uint64_t base = bootinfo->memmap[i].base;
 				uint64_t size = bootinfo->memmap[i].size;
Index: kernel/arch/ia64/src/mm/tlb.c
===================================================================
--- kernel/arch/ia64/src/mm/tlb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/src/mm/tlb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -475,15 +475,11 @@
 void alternate_instruction_tlb_fault(uint64_t vector, istate_t *istate)
 {
-	region_register_t rr;
-	rid_t rid;
 	uintptr_t va;
 	pte_t *t;
 	
 	va = istate->cr_ifa; /* faulting address */
-	rr.word = rr_read(VA2VRN(va));
-	rid = rr.map.rid;
 	
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 	if (t) {
 		/*
@@ -603,5 +599,5 @@
 	
 	page_table_lock(AS, true);
-	pte_t *entry = page_mapping_find(AS, va);
+	pte_t *entry = page_mapping_find(AS, va, true);
 	if (entry) {
 		/*
@@ -649,15 +645,11 @@
 void data_dirty_bit_fault(uint64_t vector, istate_t *istate)
 {
-	region_register_t rr;
-	rid_t rid;
 	uintptr_t va;
 	pte_t *t;
 	
 	va = istate->cr_ifa;  /* faulting address */
-	rr.word = rr_read(VA2VRN(va));
-	rid = rr.map.rid;
 	
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 	ASSERT((t) && (t->p));
 	if ((t) && (t->p) && (t->w)) {
@@ -686,15 +678,11 @@
 void instruction_access_bit_fault(uint64_t vector, istate_t *istate)
 {
-	region_register_t rr;
-	rid_t rid;
 	uintptr_t va;
 	pte_t *t;
 	
 	va = istate->cr_ifa;  /* faulting address */
-	rr.word = rr_read(VA2VRN(va));
-	rid = rr.map.rid;
 	
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 	ASSERT((t) && (t->p));
 	if ((t) && (t->p) && (t->x)) {
@@ -723,15 +711,11 @@
 void data_access_bit_fault(uint64_t vector, istate_t *istate)
 {
-	region_register_t rr;
-	rid_t rid;
 	uintptr_t va;
 	pte_t *t;
 	
 	va = istate->cr_ifa;  /* faulting address */
-	rr.word = rr_read(VA2VRN(va));
-	rid = rr.map.rid;
 	
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 	ASSERT((t) && (t->p));
 	if ((t) && (t->p)) {
@@ -760,12 +744,8 @@
 void data_access_rights_fault(uint64_t vector, istate_t *istate)
 {
-	region_register_t rr;
-	rid_t rid;
 	uintptr_t va;
 	pte_t *t;
 	
 	va = istate->cr_ifa;  /* faulting address */
-	rr.word = rr_read(VA2VRN(va));
-	rid = rr.map.rid;
 	
 	/*
@@ -773,5 +753,5 @@
 	 */
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 	ASSERT((t) && (t->p));
 	ASSERT(!t->w);
@@ -792,15 +772,11 @@
 void page_not_present(uint64_t vector, istate_t *istate)
 {
-	region_register_t rr;
-	rid_t rid;
 	uintptr_t va;
 	pte_t *t;
 	
 	va = istate->cr_ifa;  /* faulting address */
-	rr.word = rr_read(VA2VRN(va));
-	rid = rr.map.rid;
 	
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 	ASSERT(t);
 	
Index: kernel/arch/ia64/src/proc/scheduler.c
===================================================================
--- kernel/arch/ia64/src/proc/scheduler.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/src/proc/scheduler.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -79,4 +79,7 @@
 	 * Record address of kernel stack to bank 0 r23.
 	 * These values will be found there after switch from userspace.
+	 *
+	 * Mind the 1:1 split of the entire STACK_SIZE long region between the
+	 * memory stack and the RSE stack.
 	 */
 	asm volatile (
@@ -86,6 +89,6 @@
 		"bsw.1\n"
 		:
-		: "r" (&THREAD->kstack[THREAD_STACK_SIZE]),
-		  "r" (&THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA])
+		: "r" (&THREAD->kstack[STACK_SIZE / 2]),
+		  "r" (&THREAD->kstack[STACK_SIZE / 2 - SP_DELTA])
 		);
 }
Index: kernel/arch/ia64/src/start.S
===================================================================
--- kernel/arch/ia64/src/start.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ia64/src/start.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -174,7 +174,7 @@
 	
 	# Initialize gp (Global Pointer) register
-	movl gp = kernel_image_start
+	movl gp = __gp
 	
-	#	
+	#
 	# Initialize bootinfo on BSP.
 	#
Index: kernel/arch/mips32/Makefile.inc
===================================================================
--- kernel/arch/mips32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,5 +29,5 @@
 BFD_ARCH = mips
 BFD = binary
-GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3
+GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=32
 
 BITS = 32
Index: kernel/arch/mips32/include/atomic.h
===================================================================
--- kernel/arch/mips32/include/atomic.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/atomic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -91,4 +91,5 @@
 		"	sc %0, %1\n"
 		"	beqz %0, 1b\n"
+		"	nop\n"
 		"2:\n"
 		: "=&r" (tmp),
Index: kernel/arch/mips32/include/context_offset.h
===================================================================
--- kernel/arch/mips32/include/context_offset.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -63,119 +63,126 @@
 #ifdef __ASM__
 
+#ifdef KERNEL
+
 #include <arch/asm/regname.h>
 
-# ctx: address of the structure with saved context
+#else /* KERNEL */
+
+#include <libarch/regname.h>
+
+#endif /* KERNEL */
+
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_SAVE_ARCH_CORE ctx:req
-	sw $s0,OFFSET_S0(\ctx)
-	sw $s1,OFFSET_S1(\ctx)
-	sw $s2,OFFSET_S2(\ctx)
-	sw $s3,OFFSET_S3(\ctx)
-	sw $s4,OFFSET_S4(\ctx)
-	sw $s5,OFFSET_S5(\ctx)
-	sw $s6,OFFSET_S6(\ctx)
-	sw $s7,OFFSET_S7(\ctx)
-	sw $s8,OFFSET_S8(\ctx)
-	sw $gp,OFFSET_GP(\ctx)
-
+	sw $s0, OFFSET_S0(\ctx)
+	sw $s1, OFFSET_S1(\ctx)
+	sw $s2, OFFSET_S2(\ctx)
+	sw $s3, OFFSET_S3(\ctx)
+	sw $s4, OFFSET_S4(\ctx)
+	sw $s5, OFFSET_S5(\ctx)
+	sw $s6, OFFSET_S6(\ctx)
+	sw $s7, OFFSET_S7(\ctx)
+	sw $s8, OFFSET_S8(\ctx)
+	sw $gp, OFFSET_GP(\ctx)
+	
 #ifndef KERNEL
-	sw $k1,OFFSET_TLS(\ctx)
-
+	sw $k1, OFFSET_TLS(\ctx)
+	
 #ifdef CONFIG_FPU
-	mfc1 $t0,$20
+	mfc1 $t0, $20
 	sw $t0, OFFSET_F20(\ctx)
-
-	mfc1 $t0,$21
+	
+	mfc1 $t0, $21
 	sw $t0, OFFSET_F21(\ctx)
-
-	mfc1 $t0,$22
+	
+	mfc1 $t0, $22
 	sw $t0, OFFSET_F22(\ctx)
-
-	mfc1 $t0,$23
+	
+	mfc1 $t0, $23
 	sw $t0, OFFSET_F23(\ctx)
-
-	mfc1 $t0,$24
+	
+	mfc1 $t0, $24
 	sw $t0, OFFSET_F24(\ctx)
-
-	mfc1 $t0,$25
+	
+	mfc1 $t0, $25
 	sw $t0, OFFSET_F25(\ctx)
-
-	mfc1 $t0,$26
+	
+	mfc1 $t0, $26
 	sw $t0, OFFSET_F26(\ctx)
-
-	mfc1 $t0,$27
+	
+	mfc1 $t0, $27
 	sw $t0, OFFSET_F27(\ctx)
-
-	mfc1 $t0,$28
+	
+	mfc1 $t0, $28
 	sw $t0, OFFSET_F28(\ctx)
-
-	mfc1 $t0,$29
+	
+	mfc1 $t0, $29
 	sw $t0, OFFSET_F29(\ctx)
 	
-	mfc1 $t0,$30
+	mfc1 $t0, $30
 	sw $t0, OFFSET_F30(\ctx)
 #endif /* CONFIG_FPU */
 #endif /* KERNEL */
-
-	sw $ra,OFFSET_PC(\ctx)
-	sw $sp,OFFSET_SP(\ctx)
+	
+	sw $ra, OFFSET_PC(\ctx)
+	sw $sp, OFFSET_SP(\ctx)
 .endm
 
-# ctx: address of the structure with saved context
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_RESTORE_ARCH_CORE ctx:req
-	lw $s0,OFFSET_S0(\ctx)
-	lw $s1,OFFSET_S1(\ctx)
-	lw $s2,OFFSET_S2(\ctx)
-	lw $s3,OFFSET_S3(\ctx)
-	lw $s4,OFFSET_S4(\ctx)
-	lw $s5,OFFSET_S5(\ctx)
-	lw $s6,OFFSET_S6(\ctx)
-	lw $s7,OFFSET_S7(\ctx)
-	lw $s8,OFFSET_S8(\ctx)
-	lw $gp,OFFSET_GP(\ctx)
+	lw $s0, OFFSET_S0(\ctx)
+	lw $s1, OFFSET_S1(\ctx)
+	lw $s2, OFFSET_S2(\ctx)
+	lw $s3, OFFSET_S3(\ctx)
+	lw $s4, OFFSET_S4(\ctx)
+	lw $s5, OFFSET_S5(\ctx)
+	lw $s6, OFFSET_S6(\ctx)
+	lw $s7, OFFSET_S7(\ctx)
+	lw $s8, OFFSET_S8(\ctx)
+	lw $gp, OFFSET_GP(\ctx)
 #ifndef KERNEL
-	lw $k1,OFFSET_TLS(\ctx)
-
+	lw $k1, OFFSET_TLS(\ctx)
+	
 #ifdef CONFIG_FPU
 	lw $t0, OFFSET_F20(\ctx)
-	mtc1 $t0,$20
-
+	mtc1 $t0, $20
+	
 	lw $t0, OFFSET_F21(\ctx)
-	mtc1 $t0,$21
-
+	mtc1 $t0, $21
+	
 	lw $t0, OFFSET_F22(\ctx)
-	mtc1 $t0,$22
-
+	mtc1 $t0, $22
+	
 	lw $t0, OFFSET_F23(\ctx)
-	mtc1 $t0,$23
-
+	mtc1 $t0, $23
+	
 	lw $t0, OFFSET_F24(\ctx)
-	mtc1 $t0,$24
-
+	mtc1 $t0, $24
+	
 	lw $t0, OFFSET_F25(\ctx)
-	mtc1 $t0,$25
-
+	mtc1 $t0, $25
+	
 	lw $t0, OFFSET_F26(\ctx)
-	mtc1 $t0,$26
-
+	mtc1 $t0, $26
+	
 	lw $t0, OFFSET_F27(\ctx)
-	mtc1 $t0,$27
-
+	mtc1 $t0, $27
+	
 	lw $t0, OFFSET_F28(\ctx)
-	mtc1 $t0,$28
-
+	mtc1 $t0, $28
+	
 	lw $t0, OFFSET_F29(\ctx)
-	mtc1 $t0,$29
-
+	mtc1 $t0, $29
+	
 	lw $t0, OFFSET_F30(\ctx)
-	mtc1 $t0,$30
+	mtc1 $t0, $30
 #endif /* CONFIG_FPU */
 #endif /* KERNEL */
-
-	lw $ra,OFFSET_PC(\ctx)
-	lw $sp,OFFSET_SP(\ctx)
+	
+	lw $ra, OFFSET_PC(\ctx)
+	lw $sp, OFFSET_SP(\ctx)
 .endm
 
-#endif
-
+#endif /* __ASM__ */
 
 #endif
Index: kernel/arch/mips32/include/cp0.h
===================================================================
--- kernel/arch/mips32/include/cp0.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,10 +36,4 @@
 #define KERN_mips32_CP0_H_
 
-#ifdef KERNEL
-#include <typedefs.h>
-#else
-#include <sys/types.h>
-#endif
-
 #define cp0_status_ie_enabled_bit     (1 << 0)
 #define cp0_status_exl_exception_bit  (1 << 1)
@@ -49,33 +43,50 @@
 #define cp0_status_fpu_bit            (1 << 29)
 
-#define cp0_status_im_shift		8
-#define cp0_status_im_mask              0xff00
+#define cp0_status_im_shift  8
+#define cp0_status_im_mask   0xff00
 
-#define cp0_cause_excno(cause) ((cause >> 2) & 0x1f)
-#define cp0_cause_coperr(cause) ((cause >> 28) & 0x3)
+#define cp0_cause_excno(cause)   ((cause >> 2) & 0x1f)
+#define cp0_cause_coperr(cause)  ((cause >> 28) & 0x3)
 
-#define fpu_cop_id 1
+#define fpu_cop_id  1
 
 /*
  * Magic value for use in msim.
  */
-#define cp0_compare_value 		100000
+#define cp0_compare_value  100000
 
-#define cp0_mask_all_int() cp0_status_write(cp0_status_read() & ~(cp0_status_im_mask))
-#define cp0_unmask_all_int() cp0_status_write(cp0_status_read() | cp0_status_im_mask)
-#define cp0_mask_int(it) cp0_status_write(cp0_status_read() & ~(1 << (cp0_status_im_shift + (it))))
-#define cp0_unmask_int(it) cp0_status_write(cp0_status_read() | (1 << (cp0_status_im_shift + (it))))
+#define cp0_mask_all_int() \
+	cp0_status_write(cp0_status_read() & ~(cp0_status_im_mask))
 
-#define GEN_READ_CP0(nm,reg) static inline uint32_t cp0_ ##nm##_read(void) \
-  { \
-      uint32_t retval; \
-      asm("mfc0 %0, $" #reg : "=r"(retval)); \
-      return retval; \
-  }
+#define cp0_unmask_all_int() \
+	cp0_status_write(cp0_status_read() | cp0_status_im_mask)
 
-#define GEN_WRITE_CP0(nm,reg) static inline void cp0_ ##nm##_write(uint32_t val) \
- { \
-    asm("mtc0 %0, $" #reg : : "r"(val) ); \
- }
+#define cp0_mask_int(it) \
+	cp0_status_write(cp0_status_read() & ~(1 << (cp0_status_im_shift + (it))))
+
+#define cp0_unmask_int(it) \
+	cp0_status_write(cp0_status_read() | (1 << (cp0_status_im_shift + (it))))
+
+#define GEN_READ_CP0(nm, reg) \
+	static inline uint32_t cp0_ ##nm##_read(void) \
+	{ \
+		uint32_t retval; \
+		\
+		asm volatile ( \
+			"mfc0 %0, $" #reg \
+			: "=r"(retval) \
+		); \
+		\
+		return retval; \
+	}
+
+#define GEN_WRITE_CP0(nm, reg) \
+	static inline void cp0_ ##nm##_write(uint32_t val) \
+	{ \
+		asm volatile ( \
+			"mtc0 %0, $" #reg \
+			:: "r"(val) \
+		); \
+	}
 
 GEN_READ_CP0(index, 0);
Index: kernel/arch/mips32/include/cycle.h
===================================================================
--- kernel/arch/mips32/include/cycle.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/cycle.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup mips2
+/** @addtogroup mips32
  * @{
  */
Index: kernel/arch/mips32/include/debug.h
===================================================================
--- kernel/arch/mips32/include/debug.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/debug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,5 +34,5 @@
 
 #ifndef KERN_mips32_DEBUG_H_
-#define KERN_mips23_DEBUG_H_
+#define KERN_mips32_DEBUG_H_
 
 /** Enter the simulator trace mode */
Index: kernel/arch/mips32/include/istate.h
===================================================================
--- kernel/arch/mips32/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,13 +36,15 @@
 #define KERN_mips32_ISTATE_H_
 
+#include <trace.h>
+
+#ifdef KERNEL
+
 #include <arch/cp0.h>
 
-#ifdef KERNEL
-#include <typedefs.h>
-#include <trace.h>
-#else
-#include <sys/types.h>
-#define NO_TRACE
-#endif
+#else /* KERNEL */
+
+#include <libarch/cp0.h>
+
+#endif /* KERNEL */
 
 typedef struct istate {
Index: rnel/arch/mips32/include/memstr.h
===================================================================
--- kernel/arch/mips32/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2005 Sergey Bondari
- * 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 mips32
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_mips32_MEMSTR_H_
-#define KERN_mips32_MEMSTR_H_
-
-#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
-
-extern void memsetw(void *, size_t, uint16_t);
-extern void memsetb(void *, size_t, uint8_t);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/mips32/include/mm/as.h
===================================================================
--- kernel/arch/mips32/include/mm/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,10 +38,8 @@
 #define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  0
 
-#define KERNEL_ADDRESS_SPACE_START_ARCH		(unsigned long) 0x80000000
-#define KERNEL_ADDRESS_SPACE_END_ARCH		(unsigned long) 0x9fffffff
-#define USER_ADDRESS_SPACE_START_ARCH		(unsigned long) 0x00000000
-#define USER_ADDRESS_SPACE_END_ARCH		(unsigned long) 0x7fffffff
-
-#define USTACK_ADDRESS_ARCH	(0x80000000 - PAGE_SIZE)
+#define KERNEL_ADDRESS_SPACE_START_ARCH  UINT32_C(0x80000000)
+#define KERNEL_ADDRESS_SPACE_END_ARCH    UINT32_C(0x9fffffff)
+#define USER_ADDRESS_SPACE_START_ARCH    UINT32_C(0x00000000)
+#define USER_ADDRESS_SPACE_END_ARCH      UINT32_C(0x7fffffff)
 
 typedef struct {
Index: kernel/arch/mips32/include/mm/frame.h
===================================================================
--- kernel/arch/mips32/include/mm/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,8 +39,5 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
-
-#include <typedefs.h>
 
 extern void frame_arch_init(void);
@@ -48,5 +45,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/mips32/include/mm/page.h
===================================================================
--- kernel/arch/mips32/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -49,6 +49,4 @@
 #	define PA2KA(x)	((x) + 0x80000000)
 #endif
-
-#ifdef KERNEL
 
 /*
@@ -188,6 +186,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/mips32/include/stack.h
===================================================================
--- kernel/arch/mips32/include/stack.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/stack.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,12 +39,4 @@
 #define STACK_ALIGNMENT		8
 
-#define STACK_ARG0		0
-#define STACK_ARG1		4
-#define STACK_ARG2		8
-#define STACK_ARG3		12
-#define STACK_ARG4		16
-#define STACK_ARG5		20
-#define STACK_ARG6		24
-
 #endif
 
Index: kernel/arch/mips32/include/types.h
===================================================================
--- kernel/arch/mips32/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
 
 typedef uint32_t size_t;
+typedef int32_t ssize_t;
 
 typedef uint32_t uintptr_t;
Index: kernel/arch/mips32/src/asm.S
===================================================================
--- kernel/arch/mips32/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -57,20 +57,8 @@
 	nop
 
-.global memsetb
-memsetb:
-	j _memsetb
-	nop
-
-.global memsetw
-memsetw:
-	j _memsetw
-	nop
-
-.global memcpy
 .global memcpy_from_uspace
 .global memcpy_to_uspace
 .global memcpy_from_uspace_failover_address
 .global memcpy_to_uspace_failover_address
-memcpy:
 memcpy_from_uspace:
 memcpy_to_uspace:
Index: kernel/arch/mips32/src/cache.c
===================================================================
--- kernel/arch/mips32/src/cache.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/cache.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup mips32	
+/** @addtogroup mips32
  * @{
  */
Index: kernel/arch/mips32/src/cpu/cpu.c
===================================================================
--- kernel/arch/mips32/src/cpu/cpu.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/cpu/cpu.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 #include <arch.h>
 #include <arch/cp0.h>
-#include <print.h>	
+#include <print.h>
 
 struct data_t {
Index: kernel/arch/mips32/src/debugger.c
===================================================================
--- kernel/arch/mips32/src/debugger.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/debugger.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -79,5 +79,5 @@
 static cmd_info_t addbkpt_info = {
 	.name = "addbkpt",
-	.description = "Add bkpoint (break on J/Branch insts unsupported).",
+	.description = "Add bkpoint (break on j/branch insts unsupported).",
 	.func = cmd_add_breakpoint,
 	.argc = 1,
Index: kernel/arch/mips32/src/exception.c
===================================================================
--- kernel/arch/mips32/src/exception.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/exception.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -74,8 +74,7 @@
 void istate_decode(istate_t *istate)
 {
-	printf("epc=%p\tsta=%#010" PRIx32 "\t"
+	printf("epc=%#010" PRIx32 "\tsta=%#010" PRIx32 "\t"
 	    "lo =%#010" PRIx32 "\thi =%#010" PRIx32 "\n",
-	    (void *) istate->epc, istate->status,
-	    istate->lo, istate->hi);
+	    istate->epc, istate->status, istate->lo, istate->hi);
 	
 	printf("a0 =%#010" PRIx32 "\ta1 =%#010" PRIx32 "\t"
@@ -107,7 +106,7 @@
 	    istate->s8, istate->at, istate->kt0, istate->kt1);
 	
-	printf("sp =%p\tra =%p\tgp =%p\n",
-	    (void *) istate->sp, (void *) istate->ra,
-	    (void *) istate->gp);
+	printf("sp =%#010" PRIx32 "\tra =%#010" PRIx32 "\t"
+	    "gp =%#010" PRIx32 "\n",
+	    istate->sp, istate->ra, istate->gp);
 }
 
Index: kernel/arch/mips32/src/fpu_context.c
===================================================================
--- kernel/arch/mips32/src/fpu_context.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/fpu_context.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup mips32	
+/** @addtogroup mips32
  * @{
  */
@@ -40,5 +40,5 @@
 
 void fpu_disable(void)
-{	
+{
 #ifdef CONFIG_FPU
 	cp0_status_write(cp0_status_read() & ~cp0_status_fpu_bit);
Index: kernel/arch/mips32/src/mips32.c
===================================================================
--- kernel/arch/mips32/src/mips32.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/mips32.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,5 +41,5 @@
 #include <memstr.h>
 #include <proc/thread.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <print.h>
 #include <console/console.h>
@@ -52,5 +52,5 @@
 #include <arch/debugger.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/drivers/dsrln/dsrlnin.h>
 #include <genarch/drivers/dsrln/dsrlnout.h>
@@ -220,5 +220,5 @@
 	    cp0_status_um_bit | cp0_status_ie_enabled_bit));
 	cp0_epc_write((uintptr_t) kernel_uarg->uspace_entry);
-	userspace_asm(((uintptr_t) kernel_uarg->uspace_stack + PAGE_SIZE), 
+	userspace_asm(((uintptr_t) kernel_uarg->uspace_stack + STACK_SIZE),
 	    (uintptr_t) kernel_uarg->uspace_uarg,
 	    (uintptr_t) kernel_uarg->uspace_entry);
@@ -235,6 +235,6 @@
 void before_thread_runs_arch(void)
 {
-	supervisor_sp = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
-	    SP_DELTA];
+	supervisor_sp =
+	    (uintptr_t) &THREAD->kstack[STACK_SIZE - SP_DELTA];
 }
 
Index: kernel/arch/mips32/src/mm/as.c
===================================================================
--- kernel/arch/mips32/src/mm/as.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/mm/as.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -61,9 +61,9 @@
 	/*
 	 * Install ASID.
-	 */	
+	 */
 	hi.value = cp0_entry_hi_read();
 
 	hi.asid = as->asid;
-	cp0_entry_hi_write(hi.value);	
+	cp0_entry_hi_write(hi.value);
 }
 
Index: kernel/arch/mips32/src/mm/frame.c
===================================================================
--- kernel/arch/mips32/src/mm/frame.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/mm/frame.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -88,5 +88,5 @@
 	/* gxemul devices */
 	if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
-	    0x10000000, MB2SIZE(256)))
+	    0x10000000, MiB2SIZE(256)))
 		return false;
 #endif
Index: kernel/arch/mips32/src/mm/tlb.c
===================================================================
--- kernel/arch/mips32/src/mm/tlb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/mm/tlb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -73,5 +73,5 @@
 		tlbwi();
 	}
-		
+	
 	/*
 	 * The kernel is going to make use of some wired
@@ -99,6 +99,4 @@
 	asid = AS->asid;
 	mutex_unlock(&AS->lock);
-	
-	page_table_lock(AS, true);
 	
 	pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc);
@@ -113,5 +111,4 @@
 			 * or copy_to_uspace().
 			 */
-			page_table_unlock(AS, true);
 			return;
 		default:
@@ -144,9 +141,7 @@
 	tlbwr();
 
-	page_table_unlock(AS, true);
 	return;
 	
 fail:
-	page_table_unlock(AS, true);
 	tlb_refill_fail(istate);
 }
@@ -176,6 +171,4 @@
 	index.value = cp0_index_read();
 
-	page_table_lock(AS, true);	
-	
 	/*
 	 * Fail if the entry is not in TLB.
@@ -197,5 +190,4 @@
 			 * or copy_to_uspace().
 			 */
-			page_table_unlock(AS, true);			 
 			return;
 		default:
@@ -227,9 +219,7 @@
 	tlbwi();
 
-	page_table_unlock(AS, true);
 	return;
 	
 fail:
-	page_table_unlock(AS, true);
 	tlb_invalid_fail(istate);
 }
@@ -259,6 +249,4 @@
 	index.value = cp0_index_read();
 
-	page_table_lock(AS, true);	
-	
 	/*
 	 * Fail if the entry is not in TLB.
@@ -280,5 +268,4 @@
 			 * or copy_to_uspace().
 			 */
-			page_table_unlock(AS, true);			 
 			return;
 		default:
@@ -311,9 +298,7 @@
 	tlbwi();
 
-	page_table_unlock(AS, true);
 	return;
 	
 fail:
-	page_table_unlock(AS, true);
 	tlb_modified_fail(istate);
 }
@@ -364,6 +349,4 @@
 	pte_t *pte;
 
-	ASSERT(mutex_locked(&AS->lock));
-
 	hi.value = cp0_entry_hi_read();
 
@@ -379,5 +362,5 @@
 	 * Check if the mapping exists in page tables.
 	 */	
-	pte = page_mapping_find(AS, badvaddr);
+	pte = page_mapping_find(AS, badvaddr, true);
 	if (pte && pte->p && (pte->w || access != PF_ACCESS_WRITE)) {
 		/*
@@ -393,5 +376,4 @@
 		 * Resort to higher-level page fault handler.
 		 */
-		page_table_unlock(AS, true);
 		switch (rc = as_page_fault(badvaddr, access, istate)) {
 		case AS_PF_OK:
@@ -400,20 +382,14 @@
 			 * The mapping ought to be in place.
 			 */
-			page_table_lock(AS, true);
-			pte = page_mapping_find(AS, badvaddr);
+			pte = page_mapping_find(AS, badvaddr, true);
 			ASSERT(pte && pte->p);
 			ASSERT(pte->w || access != PF_ACCESS_WRITE);
 			return pte;
-			break;
 		case AS_PF_DEFER:
-			page_table_lock(AS, true);
 			*pfrc = AS_PF_DEFER;
 			return NULL;
-			break;
 		case AS_PF_FAULT:
-			page_table_lock(AS, true);
 			*pfrc = AS_PF_FAULT;
 			return NULL;
-			break;
 		default:
 			panic("Unexpected rc (%d).", rc);
Index: kernel/arch/mips32/src/start.S
===================================================================
--- kernel/arch/mips32/src/start.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/mips32/src/start.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -222,6 +222,5 @@
 	
 	/* move $k0 pointer to kernel stack */
-	lui $k0, %hi(supervisor_sp)
-	ori $k0, $k0, %lo(supervisor_sp)
+	la $k0, supervisor_sp
 	
 	/* move $k0 (supervisor_sp) */
Index: kernel/arch/mips64/Makefile.inc
===================================================================
--- kernel/arch/mips64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,64 @@
+#
+# Copyright (c) 2005 Martin Decky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+BFD_ARCH = mips:4000
+BFD = binary
+GCC_CFLAGS += -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mips3 -mabi=64
+AFLAGS = -64
+
+BITS = 64
+
+## Accepted MACHINEs
+#
+
+ifeq ($(MACHINE),msim)
+	BFD_NAME = elf64-tradlittlemips
+	ENDIANESS = LE
+	GCC_CFLAGS += -mhard-float
+endif
+
+ARCH_SOURCES = \
+	arch/$(KARCH)/src/start.S \
+	arch/$(KARCH)/src/context.S \
+	arch/$(KARCH)/src/mips64.c \
+	arch/$(KARCH)/src/asm.S \
+	arch/$(KARCH)/src/exception.c \
+	arch/$(KARCH)/src/interrupt.c \
+	arch/$(KARCH)/src/cache.c \
+	arch/$(KARCH)/src/debugger.c \
+	arch/$(KARCH)/src/cpu/cpu.c \
+	arch/$(KARCH)/src/debug/stacktrace.c \
+	arch/$(KARCH)/src/debug/stacktrace_asm.S \
+	arch/$(KARCH)/src/mm/frame.c \
+	arch/$(KARCH)/src/mm/page.c \
+	arch/$(KARCH)/src/mm/tlb.c \
+	arch/$(KARCH)/src/mm/as.c \
+	arch/$(KARCH)/src/fpu_context.c \
+	arch/$(KARCH)/src/ddi/ddi.c \
+	arch/$(KARCH)/src/smp/dorder.c \
+	arch/$(KARCH)/src/smp/smp.c
Index: kernel/arch/mips64/_link.ld.in
===================================================================
--- kernel/arch/mips64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,57 @@
+/*
+ * MIPS64 linker script
+ *
+ *  kernel text
+ *  kernel data
+ *
+ */
+
+#undef mips
+#define mips mips
+
+#define KERNEL_LOAD_ADDRESS 0xffffffff80100000
+
+OUTPUT_ARCH(mips)
+OUTPUT_FORMAT(elf64-tradlittlemips)
+ENTRY(kernel_image_start)
+
+SECTIONS {
+	. = KERNEL_LOAD_ADDRESS;
+	.text : {
+		ktext_start = .;
+		*(.text);
+		ktext_end = .;
+	}
+	.data : {
+		kdata_start = .;
+		*(.data);                       /* initialized data */
+		hardcoded_ktext_size = .;
+		LONG(ktext_end - ktext_start);
+		hardcoded_kdata_size = .;
+		LONG(kdata_end - kdata_start);
+		hardcoded_load_address = .;
+		LONG(KERNEL_LOAD_ADDRESS);
+		*(.rodata*);
+		*(.sdata);
+		*(.reginfo);
+		*(.sbss);
+		*(.scommon);
+		*(.bss);                        /* uninitialized static variables */
+		*(COMMON);                      /* global variables */
+		. = ALIGN(8);
+		symbol_table = .;
+		*(symtab.*);
+	}
+	_gp = . + 0x8000;
+	.lit8 : { *(.lit8) }
+	.lit4 : { *(.lit4) }
+	
+	kdata_end = .;
+	
+	/DISCARD/ : {
+		*(.mdebug*);
+		*(.pdr);
+		*(.comment);
+		*(.note);
+	}
+}
Index: kernel/arch/mips64/include/arch.h
===================================================================
--- kernel/arch/mips64/include/arch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/arch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_ARCH_H_
+#define KERN_mips64_ARCH_H_
+
+#include <typedefs.h>
+
+#define TASKMAP_MAX_RECORDS        32
+#define CPUMAP_MAX_RECORDS         32
+#define BOOTINFO_TASK_NAME_BUFLEN  32
+
+extern size_t cpu_count;
+
+typedef struct {
+	void *addr;
+	size_t size;
+	char name[BOOTINFO_TASK_NAME_BUFLEN];
+} utask_t;
+
+typedef struct {
+	uint32_t cpumap;
+	size_t cnt;
+	utask_t tasks[TASKMAP_MAX_RECORDS];
+} bootinfo_t;
+
+extern void arch_pre_main(void *entry, bootinfo_t *bootinfo);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/asm.h
===================================================================
--- kernel/arch/mips64/include/asm.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/asm.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_ASM_H_
+#define KERN_mips64_ASM_H_
+
+#include <typedefs.h>
+#include <config.h>
+#include <trace.h>
+
+NO_TRACE static inline void cpu_sleep(void)
+{
+	/*
+	 * Unfortunatelly most of the simulators do not support
+	 *
+	 * asm volatile (
+	 *     "wait"
+	 * );
+	 *
+	 */
+}
+
+/** Return base address of current stack
+ *
+ * Return the base address of the current stack.
+ * The stack is assumed to be STACK_SIZE bytes long.
+ * The stack must start on page boundary.
+ *
+ */
+NO_TRACE static inline uintptr_t get_stack_base(void)
+{
+	uintptr_t base;
+	
+	asm volatile (
+		"and %[base], $29, %[mask]\n"
+		: [base] "=r" (base)
+		: [mask] "r" (~(STACK_SIZE - 1))
+	);
+	
+	return base;
+}
+
+NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t v)
+{
+	*port = v;
+}
+
+NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t v)
+{
+	*port = v;
+}
+
+NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t v)
+{
+	*port = v;
+}
+
+NO_TRACE static inline uint8_t pio_read_8(ioport8_t *port)
+{
+	return *port;
+}
+
+NO_TRACE static inline uint16_t pio_read_16(ioport16_t *port)
+{
+	return *port;
+}
+
+NO_TRACE static inline uint32_t pio_read_32(ioport32_t *port)
+{
+	return *port;
+}
+
+extern void cpu_halt(void) __attribute__((noreturn));
+extern void asm_delay_loop(uint32_t);
+extern void userspace_asm(uintptr_t, uintptr_t, uintptr_t);
+
+extern ipl_t interrupts_disable(void);
+extern ipl_t interrupts_enable(void);
+extern void interrupts_restore(ipl_t);
+extern ipl_t interrupts_read(void);
+extern bool interrupts_disabled(void);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/asm/boot.h
===================================================================
--- kernel/arch/mips64/include/asm/boot.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/asm/boot.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_BOOT_H_
+#define KERN_mips64_BOOT_H_
+
+/* Temporary stack size for boot process */
+#define TEMP_STACK_SIZE  0x100
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/asm/regname.h
===================================================================
--- kernel/arch/mips64/include/asm/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/asm/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_REGNAME_H_
+#define KERN_mips64_REGNAME_H_
+
+#define zero    0
+#define at      1
+#define v0      2
+#define v1      3
+#define a0      4
+#define a1      5
+#define a2      6
+#define a3      7
+#define t0      8
+#define t1      9
+#define t2      10
+#define t3      11
+#define t4      12
+#define t5      13
+#define t6      14
+#define t7      15
+#define s0      16
+#define s1      17
+#define s2      18
+#define s3      19
+#define s4      20
+#define s5      21
+#define s6      22
+#define s7      23
+#define t8      24
+#define t9      25
+#define k0      26
+#define k1      27
+#define gp      28
+#define sp      29
+#define s8      30
+#define ra      31
+
+#define rindex    0
+#define rrandom   1
+#define entrylo0  2
+#define entrylo1  3
+#define context   4
+#define pagemask  5
+#define wired     6
+#define badvaddr  8
+#define count     9
+#define entryhi   10
+#define compare   11
+#define status    12
+#define cause     13
+#define epc       14
+#define rconfig   16
+#define lladdr    17
+#define watchlo   18
+#define watchhi   19
+#define xcontext  20
+#define rdebug    23
+#define depc      24
+#define eepc      30
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/atomic.h
===================================================================
--- kernel/arch/mips64/include/atomic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/atomic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_ATOMIC_H_
+#define KERN_mips64_ATOMIC_H_
+
+#include <trace.h>
+
+#define atomic_inc(x)  ((void) atomic_add(x, 1))
+#define atomic_dec(x)  ((void) atomic_add(x, -1))
+
+#define atomic_postinc(x)  (atomic_add(x, 1) - 1)
+#define atomic_postdec(x)  (atomic_add(x, -1) + 1)
+
+#define atomic_preinc(x)  atomic_add(x, 1)
+#define atomic_predec(x)  atomic_add(x, -1)
+
+/* Atomic addition of immediate value.
+ *
+ * @param val Memory location to which will be the immediate value added.
+ * @param i Signed immediate that will be added to *val.
+ *
+ * @return Value after addition.
+ *
+ */
+NO_TRACE static inline atomic_count_t atomic_add(atomic_t *val,
+    atomic_count_t i)
+{
+	atomic_count_t tmp;
+	atomic_count_t v;
+	
+	asm volatile (
+		"1:\n"
+		"	lld %0, %1\n"
+		"	daddu %0, %0, %3\n"  /* same as daddi, but never traps on overflow */
+		"	move %2, %0\n"
+		"	scd %0, %1\n"
+		"	beq %0, %4, 1b\n"   /* if the atomic operation failed, try again */
+		"	nop\n"
+		: "=&r" (tmp),
+		  "+m" (val->count),
+		  "=&r" (v)
+		: "r" (i),
+		  "i" (0)
+	);
+	
+	return v;
+}
+
+NO_TRACE static inline atomic_count_t test_and_set(atomic_t *val)
+{
+	atomic_count_t tmp;
+	atomic_count_t v;
+	
+	asm volatile (
+		"1:\n"
+		"	lld %2, %1\n"
+		"	bnez %2, 2f\n"
+		"	dli %0, %3\n"
+		"	scd %0, %1\n"
+		"	beqz %0, 1b\n"
+		"	nop\n"
+		"2:\n"
+		: "=&r" (tmp),
+		  "+m" (val->count),
+		  "=&r" (v)
+		: "i" (1)
+	);
+	
+	return v;
+}
+
+NO_TRACE static inline void atomic_lock_arch(atomic_t *val)
+{
+	do {
+		while (val->count);
+	} while (test_and_set(val));
+}
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/barrier.h
===================================================================
--- kernel/arch/mips64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_BARRIER_H_
+#define KERN_mips64_BARRIER_H_
+
+/*
+ * TODO: implement true MIPS memory barriers for macros below.
+ */
+#define CS_ENTER_BARRIER()  asm volatile ("" ::: "memory")
+#define CS_LEAVE_BARRIER()  asm volatile ("" ::: "memory")
+
+#define memory_barrier() asm volatile ("" ::: "memory")
+#define read_barrier()   asm volatile ("" ::: "memory")
+#define write_barrier()  asm volatile ("" ::: "memory")
+
+#define smc_coherence(a)
+#define smc_coherence_block(a, l)
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/cache.h
===================================================================
--- kernel/arch/mips64/include/cache.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/cache.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_CACHE_H_
+#define KERN_mips64_CACHE_H_
+
+#include <arch/exception.h>
+
+extern void cache_error(istate_t *);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/context.h
===================================================================
--- kernel/arch/mips64/include/context.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/context.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_CONTEXT_H_
+#define KERN_mips64_CONTEXT_H_
+
+#include <align.h>
+#include <arch/stack.h>
+
+/*
+ * Put one item onto the stack to support get_stack_base() and align it up.
+ */
+#define SP_DELTA  (0 + ALIGN_UP(STACK_ITEM_SIZE, STACK_ALIGNMENT))
+
+#ifndef __ASM__
+
+#include <typedefs.h>
+
+#define context_set(ctx, pc, stack, size) \
+    context_set_generic(ctx, pc, stack, size)
+
+/*
+ * Only save registers that must be preserved across
+ * function calls.
+ */
+typedef struct {
+	uintptr_t sp;
+	uintptr_t pc;
+	
+	uint64_t s0;
+	uint64_t s1;
+	uint64_t s2;
+	uint64_t s3;
+	uint64_t s4;
+	uint64_t s5;
+	uint64_t s6;
+	uint64_t s7;
+	uint64_t s8;
+	uint64_t gp;
+	
+	ipl_t ipl;
+} context_t;
+
+#endif /* __ASM__ */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/context_offset.h
===================================================================
--- kernel/arch/mips64/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef KERN_mips64_CONTEXT_OFFSET_H_
+#define KERN_mips64_CONTEXT_OFFSET_H_
+
+#define OFFSET_SP       0x00
+#define OFFSET_PC       0x08
+#define OFFSET_S0       0x10
+#define OFFSET_S1       0x18
+#define OFFSET_S2       0x20
+#define OFFSET_S3       0x28
+#define OFFSET_S4       0x30
+#define OFFSET_S5       0x38
+#define OFFSET_S6       0x40
+#define OFFSET_S7       0x48
+#define OFFSET_S8       0x50
+#define OFFSET_GP       0x58
+
+#ifdef KERNEL
+	#define OFFSET_IPL  0x60
+#else
+	#define OFFSET_TLS  0x60
+	
+	#define OFFSET_F20  0x68
+	#define OFFSET_F21  0x70
+	#define OFFSET_F22  0x78
+	#define OFFSET_F23  0x80
+	#define OFFSET_F24  0x88
+	#define OFFSET_F25  0x90
+	#define OFFSET_F26  0x98
+	#define OFFSET_F27  0xa0
+	#define OFFSET_F28  0xa8
+	#define OFFSET_F29  0xb0
+	#define OFFSET_F30  0xb8
+#endif /* KERNEL */
+
+#ifdef __ASM__
+
+#ifdef KERNEL
+
+#include <arch/asm/regname.h>
+
+#else /* KERNEL */
+
+#include <libarch/regname.h>
+
+#endif /* KERNEL */
+
+/* ctx: address of the structure with saved context */
+.macro CONTEXT_SAVE_ARCH_CORE ctx:req
+	sd $s0, OFFSET_S0(\ctx)
+	sd $s1, OFFSET_S1(\ctx)
+	sd $s2, OFFSET_S2(\ctx)
+	sd $s3, OFFSET_S3(\ctx)
+	sd $s4, OFFSET_S4(\ctx)
+	sd $s5, OFFSET_S5(\ctx)
+	sd $s6, OFFSET_S6(\ctx)
+	sd $s7, OFFSET_S7(\ctx)
+	sd $s8, OFFSET_S8(\ctx)
+	sd $gp, OFFSET_GP(\ctx)
+	
+#ifndef KERNEL
+	sd $k1, OFFSET_TLS(\ctx)
+	
+#ifdef CONFIG_FPU
+	dmfc1 $t0, $20
+	sd $t0, OFFSET_F20(\ctx)
+	
+	dmfc1 $t0,$21
+	sd $t0, OFFSET_F21(\ctx)
+	
+	dmfc1 $t0,$22
+	sd $t0, OFFSET_F22(\ctx)
+	
+	dmfc1 $t0,$23
+	sd $t0, OFFSET_F23(\ctx)
+	
+	dmfc1 $t0,$24
+	sd $t0, OFFSET_F24(\ctx)
+	
+	dmfc1 $t0,$25
+	sd $t0, OFFSET_F25(\ctx)
+	
+	dmfc1 $t0,$26
+	sd $t0, OFFSET_F26(\ctx)
+	
+	dmfc1 $t0,$27
+	sd $t0, OFFSET_F27(\ctx)
+	
+	dmfc1 $t0,$28
+	sd $t0, OFFSET_F28(\ctx)
+	
+	dmfc1 $t0,$29
+	sd $t0, OFFSET_F29(\ctx)
+	
+	dmfc1 $t0,$30
+	sd $t0, OFFSET_F30(\ctx)
+#endif /* CONFIG_FPU */
+#endif /* KERNEL */
+	
+	sd $ra, OFFSET_PC(\ctx)
+	sd $sp, OFFSET_SP(\ctx)
+.endm
+
+/* ctx: address of the structure with saved context */
+.macro CONTEXT_RESTORE_ARCH_CORE ctx:req
+	ld $s0, OFFSET_S0(\ctx)
+	ld $s1, OFFSET_S1(\ctx)
+	ld $s2, OFFSET_S2(\ctx)
+	ld $s3, OFFSET_S3(\ctx)
+	ld $s4, OFFSET_S4(\ctx)
+	ld $s5, OFFSET_S5(\ctx)
+	ld $s6, OFFSET_S6(\ctx)
+	ld $s7, OFFSET_S7(\ctx)
+	ld $s8, OFFSET_S8(\ctx)
+	ld $gp, OFFSET_GP(\ctx)
+	
+#ifndef KERNEL
+	ld $k1, OFFSET_TLS(\ctx)
+	
+#ifdef CONFIG_FPU
+	ld $t0, OFFSET_F20(\ctx)
+	dmtc1 $t0,$20
+	
+	ld $t0, OFFSET_F21(\ctx)
+	dmtc1 $t0,$21
+	
+	ld $t0, OFFSET_F22(\ctx)
+	dmtc1 $t0,$22
+	
+	ld $t0, OFFSET_F23(\ctx)
+	dmtc1 $t0,$23
+	
+	ld $t0, OFFSET_F24(\ctx)
+	dmtc1 $t0,$24
+	
+	ld $t0, OFFSET_F25(\ctx)
+	dmtc1 $t0,$25
+	
+	ld $t0, OFFSET_F26(\ctx)
+	dmtc1 $t0,$26
+	
+	ld $t0, OFFSET_F27(\ctx)
+	dmtc1 $t0,$27
+	
+	ld $t0, OFFSET_F28(\ctx)
+	dmtc1 $t0,$28
+	
+	ld $t0, OFFSET_F29(\ctx)
+	dmtc1 $t0,$29
+	
+	ld $t0, OFFSET_F30(\ctx)
+	dmtc1 $t0,$30
+#endif /* CONFIG_FPU */
+#endif /* KERNEL */
+	
+	ld $ra, OFFSET_PC(\ctx)
+	ld $sp, OFFSET_SP(\ctx)
+.endm
+
+#endif /* __ASM__ */
+
+#endif
Index: kernel/arch/mips64/include/cp0.h
===================================================================
--- kernel/arch/mips64/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_CP0_H_
+#define KERN_mips64_CP0_H_
+
+#define cp0_status_ie_enabled_bit     (1 << 0)
+#define cp0_status_exl_exception_bit  (1 << 1)
+#define cp0_status_erl_error_bit      (1 << 2)
+#define cp0_status_um_bit             (1 << 4)
+#define cp0_status_bev_bootstrap_bit  (1 << 22)
+#define cp0_status_fpu_bit            (1 << 29)
+
+#define cp0_status_im_shift  8
+#define cp0_status_im_mask   0xff00
+
+#define cp0_cause_excno(cause)   ((cause >> 2) & 0x1f)
+#define cp0_cause_coperr(cause)  ((cause >> 28) & 0x3)
+
+#define fpu_cop_id  1
+
+/*
+ * Magic value for use in msim.
+ */
+#define cp0_compare_value  100000
+
+#define cp0_mask_all_int() \
+	cp0_status_write(cp0_status_read() & ~(cp0_status_im_mask))
+
+#define cp0_unmask_all_int() \
+	cp0_status_write(cp0_status_read() | cp0_status_im_mask)
+
+#define cp0_mask_int(it) \
+	cp0_status_write(cp0_status_read() & ~(1 << (cp0_status_im_shift + (it))))
+
+#define cp0_unmask_int(it) \
+	cp0_status_write(cp0_status_read() | (1 << (cp0_status_im_shift + (it))))
+
+#define GEN_READ_CP0(nm,reg) static inline uint64_t cp0_ ##nm##_read(void) \
+	{ \
+		uint64_t retval; \
+		asm volatile ( \
+			"dmfc0 %0, $" #reg \
+			: "=r" (retval) \
+		); \
+		return retval; \
+	}
+
+#define GEN_WRITE_CP0(nm,reg) static inline void cp0_ ##nm##_write(uint32_t val) \
+	{ \
+		asm volatile ( \
+			"dmtc0 %0, $" #reg \
+			:: "r" (val) \
+		); \
+	}
+
+GEN_READ_CP0(index, 0);
+GEN_WRITE_CP0(index, 0);
+
+GEN_READ_CP0(random, 1);
+
+GEN_READ_CP0(entry_lo0, 2);
+GEN_WRITE_CP0(entry_lo0, 2);
+
+GEN_READ_CP0(entry_lo1, 3);
+GEN_WRITE_CP0(entry_lo1, 3);
+
+GEN_READ_CP0(context, 4);
+GEN_WRITE_CP0(context, 4);
+
+GEN_READ_CP0(pagemask, 5);
+GEN_WRITE_CP0(pagemask, 5);
+
+GEN_READ_CP0(wired, 6);
+GEN_WRITE_CP0(wired, 6);
+
+GEN_READ_CP0(badvaddr, 8);
+
+GEN_READ_CP0(count, 9);
+GEN_WRITE_CP0(count, 9);
+
+GEN_READ_CP0(entry_hi, 10);
+GEN_WRITE_CP0(entry_hi, 10);
+
+GEN_READ_CP0(compare, 11);
+GEN_WRITE_CP0(compare, 11);
+
+GEN_READ_CP0(status, 12);
+GEN_WRITE_CP0(status, 12);
+
+GEN_READ_CP0(cause, 13);
+GEN_WRITE_CP0(cause, 13);
+
+GEN_READ_CP0(epc, 14);
+GEN_WRITE_CP0(epc, 14);
+
+GEN_READ_CP0(prid, 15);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/cpu.h
===================================================================
--- kernel/arch/mips64/include/cpu.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/cpu.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_CPU_H_
+#define KERN_mips64_CPU_H_
+
+#include <typedefs.h>
+#include <arch/asm.h>
+
+typedef struct {
+	uint32_t imp_num;
+	uint32_t rev_num;
+} cpu_arch_t;
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/cycle.h
===================================================================
--- kernel/arch/mips64/include/cycle.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/cycle.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_CYCLE_H_
+#define KERN_mips64_CYCLE_H_
+
+#include <arch/cp0.h>
+#include <arch/interrupt.h>
+#include <trace.h>
+
+NO_TRACE static inline uint64_t get_cycle(void)
+{
+	return ((uint64_t) count_hi << 32) + ((uint64_t) cp0_count_read());
+}
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/debug.h
===================================================================
--- kernel/arch/mips64/include/debug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/debug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_DEBUG_H_
+#define KERN_mips64_DEBUG_H_
+
+/** Enter the simulator trace mode */
+#define ___traceon() \
+	asm volatile ( \
+		"\t.word\t0x39\n" \
+	);
+
+/** Leave the simulator trace mode */
+#define ___traceoff() \
+	asm volatile ( \
+		"\t.word\t0x3d\n" \
+	);
+
+/** Ask the simulator to dump registers */
+#define ___regview() \
+	asm volatile ( \
+		"\t.word\t0x37\n" \
+	);
+
+/** Halt the simulator */
+#define ___halt() \
+	asm volatile ( \
+		"\t.word\t0x28\n" \
+	);
+
+/** Enter the simulator interactive mode */
+#define ___intmode() \
+	asm volatile ( \
+		"\t.word\t0x29\n" \
+	);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/debugger.h
===================================================================
--- kernel/arch/mips64/include/debugger.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/debugger.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_DEBUGGER_H_
+#define KERN_mips64_DEBUGGER_H_
+
+#include <arch/exception.h>
+#include <typedefs.h>
+
+#define BKPOINTS_MAX  10
+
+/** Breakpoint was shot */
+#define BKPOINT_INPROG  (1 << 0)
+
+/** One-time breakpoint, mandatory for j/b instructions */
+#define BKPOINT_ONESHOT  (1 << 1)
+
+/**
+ * Breakpoint is set on the next instruction, so that it
+ * could be reinstalled on the previous one
+ */
+#define BKPOINT_REINST  (1 << 2)
+
+/** Call a predefined function */
+#define BKPOINT_FUNCCALL  (1 << 3)
+
+
+typedef struct  {
+	uintptr_t address;         /**< Breakpoint address */
+	sysarg_t instruction;      /**< Original instruction */
+	sysarg_t nextinstruction;  /**< Original instruction following break */
+	unsigned int flags;        /**< Flags regarding breakpoint */
+	size_t counter;
+	void (*bkfunc)(void *, istate_t *);
+} bpinfo_t;
+
+extern bpinfo_t breakpoints[BKPOINTS_MAX];
+
+extern bool is_jump(sysarg_t);
+
+extern void debugger_init(void);
+extern void debugger_bpoint(istate_t *);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/drivers/msim.h
===================================================================
--- kernel/arch/mips64/include/drivers/msim.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/drivers/msim.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_MSIM_H_
+#define KERN_mips64_MSIM_H_
+
+/** Address of devices. */
+#define MSIM_VIDEORAM     0xffffffff90000000
+#define MSIM_KBD_ADDRESS  0xffffffff90000000
+#define MSIM_KBD_IRQ      2
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/elf.h
===================================================================
--- kernel/arch/mips64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_ELF_H_
+#define KERN_mips64_ELF_H_
+
+#define ELF_MACHINE  EM_MIPS
+
+#ifdef __BE__
+	#define ELF_DATA_ENCODING  ELFDATA2MSB
+#else
+	#define ELF_DATA_ENCODING  ELFDATA2LSB
+#endif
+
+#define ELF_CLASS  ELFCLASS64
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/exception.h
===================================================================
--- kernel/arch/mips64/include/exception.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/exception.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_EXCEPTION_H_
+#define KERN_mips64_EXCEPTION_H_
+
+#include <typedefs.h>
+#include <arch/istate.h>
+
+#define EXC_Int    0
+#define EXC_Mod    1
+#define EXC_TLBL   2
+#define EXC_TLBS   3
+#define EXC_AdEL   4
+#define EXC_AdES   5
+#define EXC_IBE    6
+#define EXC_DBE    7
+#define EXC_Sys    8
+#define EXC_Bp     9
+#define EXC_RI     10
+#define EXC_CpU    11
+#define EXC_Ov     12
+#define EXC_Tr     13
+#define EXC_VCEI   14
+#define EXC_FPE    15
+#define EXC_WATCH  23
+#define EXC_VCED   31
+
+extern void exception(istate_t *istate);
+extern void tlb_refill_entry(void);
+extern void exception_entry(void);
+extern void cache_error_entry(void);
+extern void exception_init(void);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/faddr.h
===================================================================
--- kernel/arch/mips64/include/faddr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/faddr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_FADDR_H_
+#define KERN_mips64_FADDR_H_
+
+#include <typedefs.h>
+
+#define FADDR(fptr)  ((uintptr_t) (fptr))
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/fpu_context.h
===================================================================
--- kernel/arch/mips64/include/fpu_context.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/fpu_context.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 Jakub Vana
+ * 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_FPU_CONTEXT_H_
+#define KERN_mips64_FPU_CONTEXT_H_
+
+#include <typedefs.h>
+
+#define FPU_CONTEXT_ALIGN  sizeof(sysarg_t)
+
+typedef struct {
+	sysarg_t dregs[32];
+	sysarg_t cregs[32];
+} fpu_context_t;
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/interrupt.h
===================================================================
--- kernel/arch/mips64/include/interrupt.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/interrupt.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_INTERRUPT_H_
+#define KERN_mips64_INTERRUPT_H_
+
+#include <typedefs.h>
+#include <arch/exception.h>
+
+#define IVT_ITEMS  32
+#define IVT_FIRST  0
+
+#define VECTOR_TLB_SHOOTDOWN_IPI  EXC_Int
+
+extern function virtual_timer_fnc;
+extern uint32_t count_hi;
+
+extern void interrupt_init(void);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/istate.h
===================================================================
--- kernel/arch/mips64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_ISTATE_H_
+#define KERN_mips64_ISTATE_H_
+
+#include <trace.h>
+
+#ifdef KERNEL
+
+#include <arch/cp0.h>
+
+#else /* KERNEL */
+
+#include <libarch/cp0.h>
+
+#endif /* KERNEL */
+
+typedef struct istate {
+	/*
+	 * The first seven registers are arranged so that the istate structure
+	 * can be used both for exception handlers and for the syscall handler.
+	 */
+	uint64_t a0;      /* arg1 */
+	uint64_t a1;      /* arg2 */
+	uint64_t a2;      /* arg3 */
+	uint64_t a3;      /* arg4 */
+	uint64_t t0;      /* arg5 */
+	uint64_t t1;      /* arg6 */
+	uint64_t v0;      /* arg7 */
+	uint64_t v1;
+	uint64_t at;
+	uint64_t t2;
+	uint64_t t3;
+	uint64_t t4;
+	uint64_t t5;
+	uint64_t t6;
+	uint64_t t7;
+	uint64_t s0;
+	uint64_t s1;
+	uint64_t s2;
+	uint64_t s3;
+	uint64_t s4;
+	uint64_t s5;
+	uint64_t s6;
+	uint64_t s7;
+	uint64_t t8;
+	uint64_t t9;
+	uint64_t kt0;
+	uint64_t kt1;     /* We use it as thread-local pointer */
+	uint64_t gp;
+	uint64_t sp;
+	uint64_t s8;
+	uint64_t ra;
+	
+	uint64_t lo;
+	uint64_t hi;
+	
+	uint64_t status;  /* cp0_status */
+	uint64_t epc;     /* cp0_epc */
+} istate_t;
+
+NO_TRACE static inline void istate_set_retaddr(istate_t *istate,
+    uintptr_t retaddr)
+{
+	istate->epc = retaddr;
+}
+
+/** Return true if exception happened while in userspace */
+NO_TRACE static inline int istate_from_uspace(istate_t *istate)
+{
+	return istate->status & cp0_status_um_bit;
+}
+
+NO_TRACE static inline uintptr_t istate_get_pc(istate_t *istate)
+{
+	return istate->epc;
+}
+
+NO_TRACE static inline uintptr_t istate_get_fp(istate_t *istate)
+{
+	return istate->sp;
+}
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/mm/as.h
===================================================================
--- kernel/arch/mips64/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_AS_H_
+#define KERN_mips64_AS_H_
+
+#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  0
+
+#define KERNEL_ADDRESS_SPACE_START_ARCH  UINT64_C(0xffffffff80000000)
+#define KERNEL_ADDRESS_SPACE_END_ARCH    UINT64_C(0xffffffff9fffffff)
+#define USER_ADDRESS_SPACE_START_ARCH    UINT64_C(0x0000000000000000)
+#define USER_ADDRESS_SPACE_END_ARCH      UINT32_C(0x000000ffffffffff)
+
+typedef struct {
+} as_arch_t;
+
+#include <genarch/mm/as_ht.h>
+
+#define as_constructor_arch(as, flags)  (as != as)
+#define as_destructor_arch(as)          (as != as)
+#define as_create_arch(as, flags)       (as != as)
+#define as_deinstall_arch(as)
+#define as_invalidate_translation_cache(as, page, cnt)
+
+extern void as_arch_init(void);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/mm/asid.h
===================================================================
--- kernel/arch/mips64/include/mm/asid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/mm/asid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_ASID_H_
+#define KERN_mips64_ASID_H_
+
+#include <typedefs.h>
+
+#define ASID_MAX_ARCH  255    /* 2^8 - 1 */
+
+typedef uint8_t asid_t;
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/mm/frame.h
===================================================================
--- kernel/arch/mips64/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_FRAME_H_
+#define KERN_mips64_FRAME_H_
+
+#define FRAME_WIDTH  14  /* 16K */
+#define FRAME_SIZE   (1 << FRAME_WIDTH)
+
+#ifndef __ASM__
+
+extern void frame_arch_init(void);
+extern void physmem_print(void);
+
+#endif /* __ASM__ */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/mm/page.h
===================================================================
--- kernel/arch/mips64/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_PAGE_H_
+#define KERN_mips64_PAGE_H_
+
+#include <arch/mm/frame.h>
+#include <trace.h>
+
+#define PAGE_WIDTH  FRAME_WIDTH
+#define PAGE_SIZE   FRAME_SIZE
+
+#ifndef __ASM__
+	#define KA2PA(addr)  (((uintptr_t) (addr)) - 0xffffffff80000000)
+	#define PA2KA(addr)  (((uintptr_t) (addr)) + 0xffffffff80000000)
+#else
+	#define KA2PA(addr)  ((addr) - 0xffffffff80000000)
+	#define PA2KA(addr)  ((addr) + 0xffffffff80000000)
+#endif
+
+#ifndef __ASM__
+
+extern void page_arch_init(void);
+
+#endif /* __ASM__ */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/mm/tlb.h
===================================================================
--- kernel/arch/mips64/include/mm/tlb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/mm/tlb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_TLB_H_
+#define KERN_mips64_TLB_H_
+
+#include <typedefs.h>
+#include <arch/mm/asid.h>
+#include <arch/exception.h>
+#include <trace.h>
+
+#define TLB_ENTRY_COUNT  48
+
+#define TLB_WIRED               1
+#define TLB_KSTACK_WIRED_INDEX  0
+
+#define TLB_PAGE_MASK_4K    (0x000 << 13)
+#define TLB_PAGE_MASK_16K   (0x003 << 13)
+#define TLB_PAGE_MASK_64K   (0x00f << 13)
+#define TLB_PAGE_MASK_256K  (0x03f << 13)
+#define TLB_PAGE_MASK_1M    (0x0ff << 13)
+#define TLB_PAGE_MASK_4M    (0x3ff << 13)
+#define TLB_PAGE_MASK_16M   (0xfff << 13)
+
+#define PAGE_UNCACHED             2
+#define PAGE_CACHEABLE_EXC_WRITE  5
+
+typedef union {
+	struct {
+#ifdef __BE__
+		unsigned int : 2;       /* zero */
+		unsigned int pfn : 24;  /* frame number */
+		unsigned int c : 3;     /* cache coherency attribute */
+		unsigned int d : 1;     /* dirty/write-protect bit */
+		unsigned int v : 1;     /* valid bit */
+		unsigned int g : 1;     /* global bit */
+#else
+		unsigned int g : 1;     /* global bit */
+		unsigned int v : 1;     /* valid bit */
+		unsigned int d : 1;     /* dirty/write-protect bit */
+		unsigned int c : 3;     /* cache coherency attribute */
+		unsigned int pfn : 24;  /* frame number */
+		unsigned int : 2;       /* zero */
+#endif
+	} __attribute__ ((packed));
+	uint32_t value;
+} entry_lo_t;
+
+typedef union {
+	struct {
+#ifdef __BE__
+		unsigned int vpn2 : 19;
+		unsigned int : 5;
+		unsigned int asid : 8;
+#else
+		unsigned int asid : 8;
+		unsigned int : 5;
+		unsigned int vpn2 : 19;
+#endif
+	} __attribute__ ((packed));
+	uint32_t value;
+} entry_hi_t;
+
+typedef union {
+	struct {
+#ifdef __BE__
+		unsigned int : 7;
+		unsigned int mask : 12;
+		unsigned int : 13;
+#else
+		unsigned int : 13;
+		unsigned int mask : 12;
+		unsigned int : 7;
+#endif
+	} __attribute__ ((packed));
+	uint32_t value;
+} page_mask_t;
+
+typedef union {
+	struct {
+#ifdef __BE__
+		unsigned int p : 1;
+		unsigned int : 27;
+		unsigned int index : 4;
+#else
+		unsigned int index : 4;
+		unsigned int : 27;
+		unsigned int p : 1;
+#endif
+	} __attribute__ ((packed));
+	uint32_t value;
+} tlb_index_t;
+
+/** Probe TLB for Matching Entry
+ *
+ * Probe TLB for Matching Entry.
+ */
+NO_TRACE static inline void tlbp(void)
+{
+	asm volatile (
+		"tlbp\n\t"
+	);
+}
+
+/** Read Indexed TLB Entry
+ *
+ * Read Indexed TLB Entry.
+ */
+NO_TRACE static inline void tlbr(void)
+{
+	asm volatile (
+		"tlbr\n\t"
+	);
+}
+
+/** Write Indexed TLB Entry
+ *
+ * Write Indexed TLB Entry.
+ */
+NO_TRACE static inline void tlbwi(void)
+{
+	asm volatile (
+		"tlbwi\n\t"
+	);
+}
+
+/** Write Random TLB Entry
+ *
+ * Write Random TLB Entry.
+ */
+NO_TRACE static inline void tlbwr(void)
+{
+	asm volatile (
+		"tlbwr\n\t"
+	);
+}
+
+#define tlb_invalidate(asid)  tlb_invalidate_asid(asid)
+
+extern void tlb_invalid(istate_t *);
+extern void tlb_refill(istate_t *);
+extern void tlb_modified(istate_t *);
+extern void tlb_prepare_entry_lo(entry_lo_t *, bool, bool, bool, bool,
+    uintptr_t);
+extern void tlb_prepare_entry_hi(entry_hi_t *, asid_t, uintptr_t);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/proc/task.h
===================================================================
--- kernel/arch/mips64/include/proc/task.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/proc/task.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006 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 mips64proc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_TASK_H_
+#define KERN_mips64_TASK_H_
+
+typedef struct {
+} task_arch_t;
+
+#define task_create_arch(task)
+#define task_destroy_arch(task)
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/proc/thread.h
===================================================================
--- kernel/arch/mips64/include/proc/thread.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/proc/thread.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64proc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_THREAD_H_
+#define KERN_mips64_THREAD_H_
+
+typedef struct {
+} thread_arch_t;
+
+#define thr_constructor_arch(thread)
+#define thr_destructor_arch(thread)
+#define thread_create_arch(thread)
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/smp/dorder.h
===================================================================
--- kernel/arch/mips64/include/smp/dorder.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/smp/dorder.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 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.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_DORDER_H_
+#define KERN_mips64_DORDER_H_
+
+#include <typedefs.h>
+
+extern uint32_t dorder_cpuid(void);
+extern void dorder_ipi_ack(uint32_t);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/stack.h
===================================================================
--- kernel/arch/mips64/include/stack.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/stack.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_STACK_H_
+#define KERN_mips64_STACK_H_
+
+#define STACK_ITEM_SIZE  8
+#define STACK_ALIGNMENT  8
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/types.h
===================================================================
--- kernel/arch/mips64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_mips64_TYPES_H_
+#define KERN_mips64_TYPES_H_
+
+typedef uint64_t size_t;
+typedef int64_t ssize_t;
+
+typedef uint64_t uintptr_t;
+typedef uint64_t pfn_t;
+
+typedef uint64_t ipl_t;
+
+typedef uint64_t sysarg_t;
+typedef int64_t native_t;
+typedef uint64_t atomic_count_t;
+
+typedef struct {
+} fncptr_t;
+
+#define INTN_C(c)   INT64_C(c)
+#define UINTN_C(c)  UINT64_C(c)
+
+#define PRIdn  PRId64  /**< Format for native_t. */
+#define PRIun  PRIu64  /**< Format for sysarg_t. */
+#define PRIxn  PRIx64  /**< Format for hexadecimal sysarg_t. */
+#define PRIua  PRIu64  /**< Format for atomic_count_t. */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/src/asm.S
===================================================================
--- kernel/arch/mips64/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+#include <arch/asm/regname.h>
+
+.text
+
+.macro cp0_read reg
+	dmfc0 $2, \reg
+	j $31
+	nop
+.endm
+
+.macro cp0_write reg
+	dmtc0 $4, \reg
+	j $31
+	nop
+.endm
+
+.set noat
+.set noreorder
+.set nomacro
+
+.global asm_delay_loop
+asm_delay_loop:
+	j $31
+	nop
+
+.global cpu_halt
+cpu_halt:
+	j cpu_halt
+	nop
+
+.global memcpy_from_uspace
+.global memcpy_to_uspace
+.global memcpy_from_uspace_failover_address
+.global memcpy_to_uspace_failover_address
+memcpy_from_uspace:
+memcpy_to_uspace:
+	move $t2, $a0  /* save dst */
+	
+	addiu $v0, $a1, 3
+	li $v1, -4  /* 0xfffffffffffffffc */
+	and $v0, $v0, $v1
+	beq $a1, $v0, 3f
+	move $t0, $a0
+	
+	0:
+		beq $a2, $zero, 2f
+		move $a3, $zero
+	
+	1:
+		addu $v0, $a1, $a3
+		lbu $a0, 0($v0)
+		addu $v1, $t0, $a3
+		addiu $a3, $a3, 1
+		bne $a3, $a2, 1b
+		sb $a0, 0($v1)
+	
+	2:
+		jr $ra
+		move $v0, $t2
+	
+	3:
+		addiu $v0, $a0, 3
+		and $v0, $v0, $v1
+		bne $a0, $v0, 0b
+		srl $t1, $a2, 2
+		
+		beq $t1, $zero, 5f
+		move $a3, $zero
+		
+		move $a3, $zero
+		move $a0, $zero
+	
+	4:
+		addu $v0, $a1, $a0
+		lw $v1, 0($v0)
+		addiu $a3, $a3, 1
+		addu $v0, $t0, $a0
+		sw $v1, 0($v0)
+		bne $a3, $t1, 4b
+		addiu $a0, $a0, 4
+	
+	5:
+		andi $a2, $a2, 0x3
+		beq $a2, $zero, 2b
+		nop
+		
+		sll $v0, $a3, 2
+		addu $t1, $v0, $t0
+		move $a3, $zero
+		addu $t0, $v0, $a1
+	
+	6:
+		addu $v0, $t0, $a3
+		lbu $a0, 0($v0)
+		addu $v1, $t1, $a3
+		addiu $a3, $a3, 1
+		bne $a3, $a2, 6b
+		sb $a0, 0($v1)
+		
+		jr $ra
+		move $v0, $t2
+
+memcpy_from_uspace_failover_address:
+memcpy_to_uspace_failover_address:
+	jr $ra
+	move $v0, $zero
+
+.macro fpu_gp_save reg ctx
+	mfc1 $t0, $\reg
+	sw $t0, \reg * 4(\ctx)
+.endm
+
+.macro fpu_gp_restore reg ctx
+	lw $t0, \reg * 4(\ctx)
+	mtc1 $t0, $\reg
+.endm
+
+.macro fpu_ct_save reg ctx
+	cfc1 $t0, $1
+	sw $t0, (\reg + 32) * 4(\ctx)
+.endm
+
+.macro fpu_ct_restore reg ctx
+	lw $t0, (\reg + 32) * 4(\ctx)
+	ctc1 $t0, $\reg
+.endm
+
+.global fpu_context_save
+fpu_context_save:
+#ifdef CONFIG_FPU
+	fpu_gp_save 0, $a0
+	fpu_gp_save 1, $a0
+	fpu_gp_save 2, $a0
+	fpu_gp_save 3, $a0
+	fpu_gp_save 4, $a0
+	fpu_gp_save 5, $a0
+	fpu_gp_save 6, $a0
+	fpu_gp_save 7, $a0
+	fpu_gp_save 8, $a0
+	fpu_gp_save 9, $a0
+	fpu_gp_save 10, $a0
+	fpu_gp_save 11, $a0
+	fpu_gp_save 12, $a0
+	fpu_gp_save 13, $a0
+	fpu_gp_save 14, $a0
+	fpu_gp_save 15, $a0
+	fpu_gp_save 16, $a0
+	fpu_gp_save 17, $a0
+	fpu_gp_save 18, $a0
+	fpu_gp_save 19, $a0
+	fpu_gp_save 20, $a0
+	fpu_gp_save 21, $a0
+	fpu_gp_save 22, $a0
+	fpu_gp_save 23, $a0
+	fpu_gp_save 24, $a0
+	fpu_gp_save 25, $a0
+	fpu_gp_save 26, $a0
+	fpu_gp_save 27, $a0
+	fpu_gp_save 28, $a0
+	fpu_gp_save 29, $a0
+	fpu_gp_save 30, $a0
+	fpu_gp_save 31, $a0
+	
+	fpu_ct_save 1, $a0
+	fpu_ct_save 2, $a0
+	fpu_ct_save 3, $a0
+	fpu_ct_save 4, $a0
+	fpu_ct_save 5, $a0
+	fpu_ct_save 6, $a0
+	fpu_ct_save 7, $a0
+	fpu_ct_save 8, $a0
+	fpu_ct_save 9, $a0
+	fpu_ct_save 10, $a0
+	fpu_ct_save 11, $a0
+	fpu_ct_save 12, $a0
+	fpu_ct_save 13, $a0
+	fpu_ct_save 14, $a0
+	fpu_ct_save 15, $a0
+	fpu_ct_save 16, $a0
+	fpu_ct_save 17, $a0
+	fpu_ct_save 18, $a0
+	fpu_ct_save 19, $a0
+	fpu_ct_save 20, $a0
+	fpu_ct_save 21, $a0
+	fpu_ct_save 22, $a0
+	fpu_ct_save 23, $a0
+	fpu_ct_save 24, $a0
+	fpu_ct_save 25, $a0
+	fpu_ct_save 26, $a0
+	fpu_ct_save 27, $a0
+	fpu_ct_save 28, $a0
+	fpu_ct_save 29, $a0
+	fpu_ct_save 30, $a0
+	fpu_ct_save 31, $a0
+#endif
+	j $ra
+	nop
+
+.global fpu_context_restore
+fpu_context_restore:
+#ifdef CONFIG_FPU
+	fpu_gp_restore 0, $a0
+	fpu_gp_restore 1, $a0
+	fpu_gp_restore 2, $a0
+	fpu_gp_restore 3, $a0
+	fpu_gp_restore 4, $a0
+	fpu_gp_restore 5, $a0
+	fpu_gp_restore 6, $a0
+	fpu_gp_restore 7, $a0
+	fpu_gp_restore 8, $a0
+	fpu_gp_restore 9, $a0
+	fpu_gp_restore 10, $a0
+	fpu_gp_restore 11, $a0
+	fpu_gp_restore 12, $a0
+	fpu_gp_restore 13, $a0
+	fpu_gp_restore 14, $a0
+	fpu_gp_restore 15, $a0
+	fpu_gp_restore 16, $a0
+	fpu_gp_restore 17, $a0
+	fpu_gp_restore 18, $a0
+	fpu_gp_restore 19, $a0
+	fpu_gp_restore 20, $a0
+	fpu_gp_restore 21, $a0
+	fpu_gp_restore 22, $a0
+	fpu_gp_restore 23, $a0
+	fpu_gp_restore 24, $a0
+	fpu_gp_restore 25, $a0
+	fpu_gp_restore 26, $a0
+	fpu_gp_restore 27, $a0
+	fpu_gp_restore 28, $a0
+	fpu_gp_restore 29, $a0
+	fpu_gp_restore 30, $a0
+	fpu_gp_restore 31, $a0
+	
+	fpu_ct_restore 1, $a0
+	fpu_ct_restore 2, $a0
+	fpu_ct_restore 3, $a0
+	fpu_ct_restore 4, $a0
+	fpu_ct_restore 5, $a0
+	fpu_ct_restore 6, $a0
+	fpu_ct_restore 7, $a0
+	fpu_ct_restore 8, $a0
+	fpu_ct_restore 9, $a0
+	fpu_ct_restore 10, $a0
+	fpu_ct_restore 11, $a0
+	fpu_ct_restore 12, $a0
+	fpu_ct_restore 13, $a0
+	fpu_ct_restore 14, $a0
+	fpu_ct_restore 15, $a0
+	fpu_ct_restore 16, $a0
+	fpu_ct_restore 17, $a0
+	fpu_ct_restore 18, $a0
+	fpu_ct_restore 19, $a0
+	fpu_ct_restore 20, $a0
+	fpu_ct_restore 21, $a0
+	fpu_ct_restore 22, $a0
+	fpu_ct_restore 23, $a0
+	fpu_ct_restore 24, $a0
+	fpu_ct_restore 25, $a0
+	fpu_ct_restore 26, $a0
+	fpu_ct_restore 27, $a0
+	fpu_ct_restore 28, $a0
+	fpu_ct_restore 29, $a0
+	fpu_ct_restore 30, $a0
+	fpu_ct_restore 31, $a0
+#endif
+	j $ra
+	nop
+
+.global early_putchar
+early_putchar:
+	j $ra
+	nop
Index: kernel/arch/mips64/src/cache.c
===================================================================
--- kernel/arch/mips64/src/cache.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/cache.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/src/cache.c
Index: kernel/arch/mips64/src/context.S
===================================================================
--- kernel/arch/mips64/src/context.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/context.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/src/context.S
Index: kernel/arch/mips64/src/cpu
===================================================================
--- kernel/arch/mips64/src/cpu	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/cpu	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/src/cpu
Index: kernel/arch/mips64/src/ddi
===================================================================
--- kernel/arch/mips64/src/ddi	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/ddi	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/src/ddi
Index: kernel/arch/mips64/src/debug
===================================================================
--- kernel/arch/mips64/src/debug	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/debug	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/src/debug
Index: kernel/arch/mips64/src/debugger.c
===================================================================
--- kernel/arch/mips64/src/debugger.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/debugger.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/src/debugger.c
Index: kernel/arch/mips64/src/exception.c
===================================================================
--- kernel/arch/mips64/src/exception.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/exception.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/exception.h>
+#include <arch/interrupt.h>
+#include <arch/mm/tlb.h>
+#include <panic.h>
+#include <arch/cp0.h>
+#include <typedefs.h>
+#include <arch.h>
+#include <debug.h>
+#include <proc/thread.h>
+#include <print.h>
+#include <interrupt.h>
+#include <func.h>
+#include <ddi/irq.h>
+#include <arch/debugger.h>
+#include <symtab.h>
+
+static const char *exctable[] = {
+	"Interrupt",
+	"TLB Modified",
+	"TLB Invalid",
+	"TLB Invalid Store",
+	"Address Error - load/instr. fetch",
+	"Address Error - store",
+	"Bus Error - fetch instruction",
+	"Bus Error - data reference",
+	"Syscall",
+	"BreakPoint",
+	"Reserved Instruction",
+	"Coprocessor Unusable",
+	"Arithmetic Overflow",
+	"Trap",
+	"Virtual Coherency - instruction",
+	"Floating Point",
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	"WatchHi/WatchLo",  /* 23 */
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	"Virtual Coherency - data",
+};
+
+void istate_decode(istate_t *istate)
+{
+	printf("epc=%#018" PRIx64 "\tsta=%#018" PRIx64 "\t"
+	    "lo =%#018" PRIx64 "\thi =%#018" PRIx64 "\n",
+	    istate->epc, istate->status, istate->lo, istate->hi);
+	
+	printf("a0 =%#018" PRIx64 "\ta1 =%#018" PRIx64 "\t"
+	    "a2 =%#018" PRIx64 "\ta3 =%#018" PRIx64 "\n",
+	    istate->a0, istate->a1, istate->a2, istate->a3);
+	
+	printf("t0 =%#018" PRIx64 "\tt1 =%#018" PRIx64 "\t"
+	    "t2 =%#018" PRIx64 "\tt3 =%#018" PRIx64 "\n",
+	    istate->t0, istate->t1, istate->t2, istate->t3);
+	
+	printf("t4 =%#018" PRIx64 "\tt5 =%#018" PRIx64 "\t"
+	    "t6 =%#018" PRIx64 "\tt7 =%#018" PRIx64 "\n",
+	    istate->t4, istate->t5, istate->t6, istate->t7);
+	
+	printf("t8 =%#018" PRIx64 "\tt9 =%#018" PRIx64 "\t"
+	    "v0 =%#018" PRIx64 "\tv1 =%#018" PRIx64 "\n",
+	    istate->t8, istate->t9, istate->v0, istate->v1);
+	
+	printf("s0 =%#018" PRIx64 "\ts1 =%#018" PRIx64 "\t"
+	    "s2 =%#018" PRIx64 "\ts3 =%#018" PRIx64 "\n",
+	    istate->s0, istate->s1, istate->s2, istate->s3);
+	
+	printf("s4 =%#018" PRIx64 "\ts5 =%#018" PRIx64 "\t"
+	    "s6 =%#018" PRIx64 "\ts7 =%#018" PRIx64 "\n",
+	    istate->s4, istate->s5, istate->s6, istate->s7);
+	
+	printf("s8 =%#018" PRIx64 "\tat =%#018" PRIx64 "\t"
+	    "kt0=%#018" PRIx64 "\tkt1=%#018" PRIx64 "\n",
+	    istate->s8, istate->at, istate->kt0, istate->kt1);
+	
+	printf("sp =%#018" PRIx64 "\tra =%#018" PRIx64 "\t"
+	    "gp =%#018" PRIx64 "\n",
+	    istate->sp, istate->ra, istate->gp);
+}
+
+static void unhandled_exception(unsigned int n, istate_t *istate)
+{
+	fault_if_from_uspace(istate, "Unhandled exception %s.", exctable[n]);
+	panic_badtrap(istate, n, "Unhandled exception %s.", exctable[n]);
+}
+
+static void reserved_instr_exception(unsigned int n, istate_t *istate)
+{
+	if (*((uint32_t *) istate->epc) == 0x7c03e83b) {
+		ASSERT(THREAD);
+		istate->epc += 4;
+		istate->v1 = istate->kt1;
+	} else
+		unhandled_exception(n, istate);
+}
+
+static void breakpoint_exception(unsigned int n, istate_t *istate)
+{
+#ifdef CONFIG_DEBUG
+	debugger_bpoint(istate);
+#else
+	/* it is necessary to not re-execute BREAK instruction after 
+	   returning from Exception handler
+	   (see page 138 in R4000 Manual for more information) */
+	istate->epc += 4;
+#endif
+}
+
+static void tlbmod_exception(unsigned int n, istate_t *istate)
+{
+	tlb_modified(istate);
+}
+
+static void tlbinv_exception(unsigned int n, istate_t *istate)
+{
+	tlb_invalid(istate);
+}
+
+#ifdef CONFIG_FPU_LAZY
+static void cpuns_exception(unsigned int n, istate_t *istate)
+{
+	if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
+		scheduler_fpu_lazy_request();
+	else {
+		fault_if_from_uspace(istate,
+		    "Unhandled Coprocessor Unusable Exception.");
+		panic_badtrap(istate, n,
+		    "Unhandled Coprocessor Unusable Exception.");
+	}
+}
+#endif
+
+static void interrupt_exception(unsigned int n, istate_t *istate)
+{
+	/* Decode interrupt number and process the interrupt */
+	uint32_t cause = (cp0_cause_read() >> 8) & 0xff;
+	
+	unsigned int i;
+	for (i = 0; i < 8; i++) {
+		if (cause & (1 << i)) {
+			irq_t *irq = irq_dispatch_and_lock(i);
+			if (irq) {
+				/*
+				 * The IRQ handler was found.
+				 */
+				irq->handler(irq);
+				irq_spinlock_unlock(&irq->lock, false);
+			} else {
+				/*
+				 * Spurious interrupt.
+				 */
+#ifdef CONFIG_DEBUG
+				printf("cpu%u: spurious interrupt (inum=%u)\n",
+				    CPU->id, i);
+#endif
+			}
+		}
+	}
+}
+
+/** Handle syscall userspace call */
+static void syscall_exception(unsigned int n, istate_t *istate)
+{
+	fault_if_from_uspace(istate, "Syscall is handled through shortcut.");
+}
+
+void exception_init(void)
+{
+	unsigned int i;
+	
+	/* Clear exception table */
+	for (i = 0; i < IVT_ITEMS; i++)
+		exc_register(i, "undef", false,
+		    (iroutine_t) unhandled_exception);
+	
+	exc_register(EXC_Bp, "bkpoint", true,
+	    (iroutine_t) breakpoint_exception);
+	exc_register(EXC_RI, "resinstr", true,
+	    (iroutine_t) reserved_instr_exception);
+	exc_register(EXC_Mod, "tlb_mod", true,
+	    (iroutine_t) tlbmod_exception);
+	exc_register(EXC_TLBL, "tlbinvl", true,
+	    (iroutine_t) tlbinv_exception);
+	exc_register(EXC_TLBS, "tlbinvl", true,
+	    (iroutine_t) tlbinv_exception);
+	exc_register(EXC_Int, "interrupt", true,
+	    (iroutine_t) interrupt_exception);
+	
+#ifdef CONFIG_FPU_LAZY
+	exc_register(EXC_CpU, "cpunus", true,
+	    (iroutine_t) cpuns_exception);
+#endif
+	
+	exc_register(EXC_Sys, "syscall", true,
+	    (iroutine_t) syscall_exception);
+}
+
+/** @}
+ */
Index: kernel/arch/mips64/src/fpu_context.c
===================================================================
--- kernel/arch/mips64/src/fpu_context.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/fpu_context.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/src/fpu_context.c
Index: kernel/arch/mips64/src/interrupt.c
===================================================================
--- kernel/arch/mips64/src/interrupt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/interrupt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#include <interrupt.h>
+#include <arch/interrupt.h>
+#include <typedefs.h>
+#include <arch.h>
+#include <arch/cp0.h>
+#include <arch/smp/dorder.h>
+#include <time/clock.h>
+#include <ipc/sysipc.h>
+#include <ddi/device.h>
+
+#define IRQ_COUNT   8
+#define TIMER_IRQ   7
+#define DORDER_IRQ  5
+
+function virtual_timer_fnc = NULL;
+static irq_t timer_irq;
+static irq_t dorder_irq;
+
+// TODO: This is SMP unsafe!!!
+
+uint32_t count_hi = 0;
+static unsigned long nextcount;
+static unsigned long lastcount;
+
+/** Disable interrupts.
+ *
+ * @return Old interrupt priority level.
+ */
+ipl_t interrupts_disable(void)
+{
+	ipl_t ipl = (ipl_t) cp0_status_read();
+	cp0_status_write(ipl & ~cp0_status_ie_enabled_bit);
+	return ipl;
+}
+
+/** Enable interrupts.
+ *
+ * @return Old interrupt priority level.
+ */
+ipl_t interrupts_enable(void)
+{
+	ipl_t ipl = (ipl_t) cp0_status_read();
+	cp0_status_write(ipl | cp0_status_ie_enabled_bit);
+	return ipl;
+}
+
+/** Restore interrupt priority level.
+ *
+ * @param ipl Saved interrupt priority level.
+ */
+void interrupts_restore(ipl_t ipl)
+{
+	cp0_status_write(cp0_status_read() | (ipl & cp0_status_ie_enabled_bit));
+}
+
+/** Read interrupt priority level.
+ *
+ * @return Current interrupt priority level.
+ */
+ipl_t interrupts_read(void)
+{
+	return cp0_status_read();
+}
+
+/** Check interrupts state.
+ *
+ * @return True if interrupts are disabled.
+ *
+ */
+bool interrupts_disabled(void)
+{
+	return !(cp0_status_read() & cp0_status_ie_enabled_bit);
+}
+
+/** Start hardware clock
+ *
+ */
+static void timer_start(void)
+{
+	lastcount = cp0_count_read();
+	nextcount = cp0_compare_value + cp0_count_read();
+	cp0_compare_write(nextcount);
+}
+
+static irq_ownership_t timer_claim(irq_t *irq)
+{
+	return IRQ_ACCEPT;
+}
+
+static void timer_irq_handler(irq_t *irq)
+{
+	if (cp0_count_read() < lastcount)
+		/* Count overflow detected */
+		count_hi++;
+	
+	lastcount = cp0_count_read();
+	
+	unsigned long drift = cp0_count_read() - nextcount;
+	while (drift > cp0_compare_value) {
+		drift -= cp0_compare_value;
+		CPU->missed_clock_ticks++;
+	}
+	
+	nextcount = cp0_count_read() + cp0_compare_value - drift;
+	cp0_compare_write(nextcount);
+	
+	/*
+	 * We are holding a lock which prevents preemption.
+	 * Release the lock, call clock() and reacquire the lock again.
+	 */
+	irq_spinlock_unlock(&irq->lock, false);
+	clock();
+	irq_spinlock_lock(&irq->lock, false);
+	
+	if (virtual_timer_fnc != NULL)
+		virtual_timer_fnc();
+}
+
+static irq_ownership_t dorder_claim(irq_t *irq)
+{
+	return IRQ_ACCEPT;
+}
+
+static void dorder_irq_handler(irq_t *irq)
+{
+	dorder_ipi_ack(1 << dorder_cpuid());
+}
+
+/* Initialize basic tables for exception dispatching */
+void interrupt_init(void)
+{
+	irq_init(IRQ_COUNT, IRQ_COUNT);
+	
+	irq_initialize(&timer_irq);
+	timer_irq.devno = device_assign_devno();
+	timer_irq.inr = TIMER_IRQ;
+	timer_irq.claim = timer_claim;
+	timer_irq.handler = timer_irq_handler;
+	irq_register(&timer_irq);
+	
+	timer_start();
+	cp0_unmask_int(TIMER_IRQ);
+	
+	irq_initialize(&dorder_irq);
+	dorder_irq.devno = device_assign_devno();
+	dorder_irq.inr = DORDER_IRQ;
+	dorder_irq.claim = dorder_claim;
+	dorder_irq.handler = dorder_irq_handler;
+	irq_register(&dorder_irq);
+	
+	cp0_unmask_int(DORDER_IRQ);
+}
+
+/** @}
+ */
Index: kernel/arch/mips64/src/mips64.c
===================================================================
--- kernel/arch/mips64/src/mips64.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/mips64.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64
+ * @{
+ */
+/** @file
+ */
+
+#include <arch.h>
+#include <arch/cp0.h>
+#include <arch/exception.h>
+#include <arch/debug.h>
+#include <mm/as.h>
+#include <userspace.h>
+#include <memstr.h>
+#include <proc/thread.h>
+#include <abi/proc/uarg.h>
+#include <print.h>
+#include <console/console.h>
+#include <syscall/syscall.h>
+#include <sysinfo/sysinfo.h>
+#include <arch/interrupt.h>
+#include <interrupt.h>
+#include <console/chardev.h>
+#include <arch/barrier.h>
+#include <arch/debugger.h>
+#include <genarch/fb/fb.h>
+#include <abi/fb/visuals.h>
+#include <genarch/drivers/dsrln/dsrlnin.h>
+#include <genarch/drivers/dsrln/dsrlnout.h>
+#include <genarch/srln/srln.h>
+#include <macros.h>
+#include <config.h>
+#include <str.h>
+#include <arch/drivers/msim.h>
+#include <arch/asm/regname.h>
+
+/* Size of the code jumping to the exception handler code
+ * - J+NOP
+ */
+#define EXCEPTION_JUMP_SIZE  8
+
+#define TLB_EXC    ((char *) 0xffffffff80000000)
+#define NORM_EXC   ((char *) 0xffffffff80000180)
+#define CACHE_EXC  ((char *) 0xffffffff80000100)
+
+
+/* Why the linker moves the variable 64K away in assembler
+ * when not in .text section?
+ */
+
+/* Stack pointer saved when entering user mode */
+uintptr_t supervisor_sp __attribute__ ((section (".text")));
+
+size_t cpu_count = 0;
+
+/** Performs mips64-specific initialization before main_bsp() is called. */
+void arch_pre_main(void *entry __attribute__((unused)), bootinfo_t *bootinfo)
+{
+	init.cnt = min3(bootinfo->cnt, TASKMAP_MAX_RECORDS, CONFIG_INIT_TASKS);
+	
+	size_t i;
+	for (i = 0; i < init.cnt; i++) {
+		init.tasks[i].addr = (uintptr_t) bootinfo->tasks[i].addr;
+		init.tasks[i].size = bootinfo->tasks[i].size;
+		str_cpy(init.tasks[i].name, CONFIG_TASK_NAME_BUFLEN,
+		    bootinfo->tasks[i].name);
+	}
+	
+	for (i = 0; i < CPUMAP_MAX_RECORDS; i++) {
+		if ((bootinfo->cpumap & (1 << i)) != 0)
+			cpu_count++;
+	}
+}
+
+void arch_pre_mm_init(void)
+{
+	/* It is not assumed by default */
+	interrupts_disable();
+	
+	/* Initialize dispatch table */
+	exception_init();
+
+	/* Copy the exception vectors to the right places */
+	memcpy(TLB_EXC, (char *) tlb_refill_entry, EXCEPTION_JUMP_SIZE);
+	smc_coherence_block(TLB_EXC, EXCEPTION_JUMP_SIZE);
+	memcpy(NORM_EXC, (char *) exception_entry, EXCEPTION_JUMP_SIZE);
+	smc_coherence_block(NORM_EXC, EXCEPTION_JUMP_SIZE);
+	memcpy(CACHE_EXC, (char *) cache_error_entry, EXCEPTION_JUMP_SIZE);
+	smc_coherence_block(CACHE_EXC, EXCEPTION_JUMP_SIZE);
+	
+	/*
+	 * Switch to BEV normal level so that exception vectors point to the
+	 * kernel. Clear the error level.
+	 */
+	cp0_status_write(cp0_status_read() &
+	    ~(cp0_status_bev_bootstrap_bit | cp0_status_erl_error_bit));
+	
+	/*
+	 * Mask all interrupts
+	 */
+	cp0_mask_all_int();
+	
+	debugger_init();
+}
+
+void arch_post_mm_init(void)
+{
+	interrupt_init();
+	
+#ifdef CONFIG_MIPS_PRN
+	outdev_t *dsrlndev = dsrlnout_init((ioport8_t *) MSIM_KBD_ADDRESS);
+	if (dsrlndev)
+		stdout_wire(dsrlndev);
+#endif
+}
+
+void arch_post_cpu_init(void)
+{
+}
+
+void arch_pre_smp_init(void)
+{
+}
+
+void arch_post_smp_init(void)
+{
+	static const char *platform;
+	
+	/* Set platform name. */
+#ifdef MACHINE_msim
+	platform = "msim";
+#endif
+	sysinfo_set_item_data("platform", NULL, (void *) platform,
+	    str_size(platform));
+	
+#ifdef CONFIG_MIPS_KBD
+	/*
+	 * Initialize the msim/GXemul keyboard port. Then initialize the serial line
+	 * module and connect it to the msim/GXemul keyboard. Enable keyboard interrupts.
+	 */
+	dsrlnin_instance_t *dsrlnin_instance
+	    = dsrlnin_init((dsrlnin_t *) MSIM_KBD_ADDRESS, MSIM_KBD_IRQ);
+	if (dsrlnin_instance) {
+		srln_instance_t *srln_instance = srln_init();
+		if (srln_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *srln = srln_wire(srln_instance, sink);
+			dsrlnin_wire(dsrlnin_instance, srln);
+			cp0_unmask_int(MSIM_KBD_IRQ);
+		}
+	}
+	
+	/*
+	 * This is the necessary evil until the userspace driver is entirely
+	 * self-sufficient.
+	 */
+	sysinfo_set_item_val("kbd", NULL, true);
+	sysinfo_set_item_val("kbd.inr", NULL, MSIM_KBD_IRQ);
+	sysinfo_set_item_val("kbd.address.virtual", NULL, MSIM_KBD_ADDRESS);
+#endif
+}
+
+void calibrate_delay_loop(void)
+{
+}
+
+void userspace(uspace_arg_t *kernel_uarg)
+{
+	/* EXL = 1, UM = 1, IE = 1 */
+	cp0_status_write(cp0_status_read() | (cp0_status_exl_exception_bit |
+	    cp0_status_um_bit | cp0_status_ie_enabled_bit));
+	cp0_epc_write((uintptr_t) kernel_uarg->uspace_entry);
+	userspace_asm(((uintptr_t) kernel_uarg->uspace_stack + STACK_SIZE),
+	    (uintptr_t) kernel_uarg->uspace_uarg,
+	    (uintptr_t) kernel_uarg->uspace_entry);
+	
+	while (1);
+}
+
+/** Perform mips64 specific tasks needed before the new task is run. */
+void before_task_runs_arch(void)
+{
+}
+
+/** Perform mips64 specific tasks needed before the new thread is scheduled. */
+void before_thread_runs_arch(void)
+{
+	supervisor_sp =
+	    (uintptr_t) &THREAD->kstack[STACK_SIZE - SP_DELTA];
+}
+
+void after_thread_ran_arch(void)
+{
+}
+
+/** Set thread-local-storage pointer
+ *
+ * We have it currently in K1, it is
+ * possible to have it separately in the future.
+ */
+sysarg_t sys_tls_set(sysarg_t addr)
+{
+	return 0;
+}
+
+void arch_reboot(void)
+{
+	___halt();
+	while (1);
+}
+
+/** Construct function pointer
+ *
+ * @param fptr   function pointer structure
+ * @param addr   function address
+ * @param caller calling function address
+ *
+ * @return address of the function pointer
+ *
+ */
+void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
+{
+	return addr;
+}
+
+void irq_initialize_arch(irq_t *irq)
+{
+	(void) irq;
+}
+
+/** @}
+ */
Index: kernel/arch/mips64/src/mm/as.c
===================================================================
--- kernel/arch/mips64/src/mm/as.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/mm/as.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/as.h>
+#include <genarch/mm/as_ht.h>
+#include <genarch/mm/page_ht.h>
+#include <genarch/mm/asid_fifo.h>
+#include <arch/mm/tlb.h>
+#include <mm/tlb.h>
+#include <mm/as.h>
+#include <arch/cp0.h>
+
+/** Architecture dependent address space init. */
+void as_arch_init(void)
+{
+	as_operations = &as_ht_operations;
+	asid_fifo_init();
+}
+
+/** Install address space.
+ *
+ * Install ASID.
+ *
+ * @param as Address space structure.
+ *
+ */
+void as_install_arch(as_t *as)
+{
+	/*
+	 * Install ASID.
+	 */
+	entry_hi_t hi;
+	hi.value = cp0_entry_hi_read();
+	hi.asid = as->asid;
+	cp0_entry_hi_write(hi.value);
+}
+
+/** @}
+ */
Index: kernel/arch/mips64/src/mm/frame.c
===================================================================
--- kernel/arch/mips64/src/mm/frame.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/mm/frame.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#include <macros.h>
+#include <arch/mm/frame.h>
+#include <arch/mm/tlb.h>
+#include <interrupt.h>
+#include <mm/frame.h>
+#include <mm/asid.h>
+#include <config.h>
+#include <arch/drivers/msim.h>
+#include <print.h>
+
+#define ZERO_PAGE_MASK    TLB_PAGE_MASK_256K
+#define ZERO_FRAMES       2048
+#define ZERO_PAGE_WIDTH   18  /* 256K */
+#define ZERO_PAGE_SIZE    (1 << ZERO_PAGE_WIDTH)
+#define ZERO_PAGE_ASID    ASID_INVALID
+#define ZERO_PAGE_TLBI    0
+#define ZERO_PAGE_ADDR    0
+#define ZERO_PAGE_OFFSET  (ZERO_PAGE_SIZE / sizeof(uint32_t) - 1)
+#define ZERO_PAGE_VALUE   (((volatile uint32_t *) ZERO_PAGE_ADDR)[ZERO_PAGE_OFFSET])
+
+#define ZERO_PAGE_VALUE_KSEG1(frame) \
+	(((volatile uint32_t *) (0xa0000000 + (frame << ZERO_PAGE_WIDTH)))[ZERO_PAGE_OFFSET])
+
+#define MAX_REGIONS  32
+
+typedef struct {
+	pfn_t start;
+	pfn_t count;
+} phys_region_t;
+
+static size_t phys_regions_count = 0;
+static phys_region_t phys_regions[MAX_REGIONS];
+
+/** Check whether frame is available
+ *
+ * Returns true if given frame is generally available for use.
+ * Returns false if given frame is used for physical memory
+ * mapped devices and cannot be used.
+ *
+ */
+static bool frame_available(pfn_t frame)
+{
+#ifdef MACHINE_msim
+	/* MSIM device (dprinter) */
+	if (frame == (KA2PA(MSIM_VIDEORAM) >> ZERO_PAGE_WIDTH))
+		return false;
+	
+	/* MSIM device (dkeyboard) */
+	if (frame == (KA2PA(MSIM_KBD_ADDRESS) >> ZERO_PAGE_WIDTH))
+		return false;
+#endif
+	
+	return true;
+}
+
+/** Check whether frame is safe to write
+ *
+ * Returns true if given frame is safe for read/write test.
+ * Returns false if given frame should not be touched.
+ *
+ */
+static bool frame_safe(pfn_t frame)
+{
+	/* Kernel structures */
+	if ((frame << ZERO_PAGE_WIDTH) < KA2PA(config.base))
+		return false;
+	
+	/* Kernel */
+	if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
+	    KA2PA(config.base), config.kernel_size))
+		return false;
+	
+	/* Kernel stack */
+	if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
+	    KA2PA(config.stack_base), config.stack_size))
+		return false;
+	
+	/* Init tasks */
+	bool safe = true;
+	size_t i;
+	for (i = 0; i < init.cnt; i++)
+		if (overlaps(frame << ZERO_PAGE_WIDTH, ZERO_PAGE_SIZE,
+		    KA2PA(init.tasks[i].addr), init.tasks[i].size)) {
+			safe = false;
+			break;
+		}
+	
+	return safe;
+}
+
+static void frame_add_region(pfn_t start_frame, pfn_t end_frame)
+{
+	if (end_frame > start_frame) {
+		/* Convert 1M frames to 16K frames */
+		pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH);
+		pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH);
+		
+		/* Interrupt vector frame is blacklisted */
+		pfn_t conf_frame;
+		if (first == 0)
+			conf_frame = 1;
+		else
+			conf_frame = first;
+		
+		zone_create(first, count, conf_frame, 0);
+		
+		if (phys_regions_count < MAX_REGIONS) {
+			phys_regions[phys_regions_count].start = first;
+			phys_regions[phys_regions_count].count = count;
+			phys_regions_count++;
+		}
+	}
+}
+
+/** Create memory zones
+ *
+ * Walk through available 256 KB chunks of physical
+ * memory and create zones.
+ *
+ * Note: It is assumed that the TLB is not yet being
+ * used in any way, thus there is no interference.
+ *
+ */
+void frame_arch_init(void)
+{
+	ipl_t ipl = interrupts_disable();
+	
+	/* Clear and initialize TLB */
+	cp0_pagemask_write(ZERO_PAGE_MASK);
+	cp0_entry_lo0_write(0);
+	cp0_entry_lo1_write(0);
+	cp0_entry_hi_write(0);
+	
+	for (size_t i = 0; i < TLB_ENTRY_COUNT; i++) {
+		cp0_index_write(i);
+		tlbwi();
+	}
+	
+	pfn_t start_frame = 0;
+	pfn_t frame;
+	bool avail = true;
+	
+	/* Walk through all 1 MB frames */
+	for (frame = 0; frame < ZERO_FRAMES; frame++) {
+		if (!frame_available(frame))
+			avail = false;
+		else {
+			if (frame_safe(frame)) {
+				entry_lo_t lo0;
+				entry_lo_t lo1;
+				entry_hi_t hi;
+				tlb_prepare_entry_lo(&lo0, false, true, true, false, frame << (ZERO_PAGE_WIDTH - 12));
+				tlb_prepare_entry_lo(&lo1, false, false, false, false, 0);
+				tlb_prepare_entry_hi(&hi, ZERO_PAGE_ASID, ZERO_PAGE_ADDR);
+				
+				cp0_pagemask_write(ZERO_PAGE_MASK);
+				cp0_entry_lo0_write(lo0.value);
+				cp0_entry_lo1_write(lo1.value);
+				cp0_entry_hi_write(hi.value);
+				cp0_index_write(ZERO_PAGE_TLBI);
+				tlbwi();
+				
+				ZERO_PAGE_VALUE = 0;
+				if (ZERO_PAGE_VALUE != 0)
+					avail = false;
+				else {
+					ZERO_PAGE_VALUE = 0xdeadbeef;
+					if (ZERO_PAGE_VALUE != 0xdeadbeef)
+						avail = false;
+				}
+			}
+		}
+		
+		if (!avail) {
+			frame_add_region(start_frame, frame);
+			start_frame = frame + 1;
+			avail = true;
+		}
+	}
+	
+	frame_add_region(start_frame, frame);
+	
+	/* Blacklist interrupt vector frame */
+	frame_mark_unavailable(0, 1);
+	
+	/* Cleanup */
+	cp0_pagemask_write(ZERO_PAGE_MASK);
+	cp0_entry_lo0_write(0);
+	cp0_entry_lo1_write(0);
+	cp0_entry_hi_write(0);
+	cp0_index_write(ZERO_PAGE_TLBI);
+	tlbwi();
+	
+	interrupts_restore(ipl);
+}
+
+void physmem_print(void)
+{
+	printf("[base            ] [size            ]\n");
+	
+	for (size_t i = 0; i < phys_regions_count; i++) {
+		printf("%#018lx %18lu\n", PFN2ADDR(phys_regions[i].start),
+		    PFN2ADDR(phys_regions[i].count));
+	}
+}
+
+/** @}
+ */
Index: kernel/arch/mips64/src/mm/page.c
===================================================================
--- kernel/arch/mips64/src/mm/page.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/mm/page.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/page.h>
+#include <genarch/mm/page_ht.h>
+#include <mm/page.h>
+#include <mm/frame.h>
+
+void page_arch_init(void)
+{
+	page_mapping_operations = &ht_mapping_operations;
+}
+
+/** Map device into kernel space
+ * - on mips, all devices are already mapped into kernel space,
+ *   translate the physical address to uncached area
+ */
+uintptr_t hw_map(uintptr_t physaddr, size_t size)
+{
+	return physaddr + 0xffffffffa0000000;
+}
+
+/** @}
+ */
Index: kernel/arch/mips64/src/mm/tlb.c
===================================================================
--- kernel/arch/mips64/src/mm/tlb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/mm/tlb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2003-2004 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 mips64mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/tlb.h>
+#include <mm/asid.h>
+#include <mm/tlb.h>
+#include <mm/page.h>
+#include <mm/as.h>
+#include <arch/cp0.h>
+#include <panic.h>
+#include <arch.h>
+#include <synch/mutex.h>
+#include <print.h>
+#include <debug.h>
+#include <align.h>
+#include <interrupt.h>
+#include <symtab.h>
+
+/** Initialize TLB.
+ *
+ * Invalidate all entries and mark wired entries.
+ *
+ */
+void tlb_arch_init(void)
+{
+	cp0_pagemask_write(TLB_PAGE_MASK_16K);
+	cp0_entry_hi_write(0);
+	cp0_entry_lo0_write(0);
+	cp0_entry_lo1_write(0);
+	
+	/* Clear and initialize TLB. */
+	
+	for (unsigned int i = 0; i < TLB_ENTRY_COUNT; i++) {
+		cp0_index_write(i);
+		tlbwi();
+	}
+	
+	/*
+	 * The kernel is going to make use of some wired
+	 * entries (e.g. mapping kernel stacks in kseg3).
+	 */
+	cp0_wired_write(TLB_WIRED);
+}
+
+/** Try to find PTE for faulting address.
+ *
+ * @param badvaddr Faulting virtual address.
+ * @param access   Access mode that caused the fault.
+ * @param istate   Pointer to interrupted state.
+ * @param pfrc     Pointer to variable where as_page_fault()
+ *                 return code will be stored.
+ *
+ * @return PTE on success, NULL otherwise.
+ *
+ */
+static pte_t *find_mapping_and_check(uintptr_t badvaddr, int access,
+    istate_t *istate, int *pfrc)
+{
+	entry_hi_t hi;
+	hi.value = cp0_entry_hi_read();
+	
+	/*
+	 * Handler cannot succeed if the ASIDs don't match.
+	 */
+	if (hi.asid != AS->asid) {
+		printf("EntryHi.asid=%d, AS->asid=%d\n", hi.asid, AS->asid);
+		return NULL;
+	}
+	
+	/*
+	 * Check if the mapping exists in page tables.
+	 */
+	pte_t *pte = page_mapping_find(AS, badvaddr, true);
+	if ((pte) && (pte->p) && ((pte->w) || (access != PF_ACCESS_WRITE))) {
+		/*
+		 * Mapping found in page tables.
+		 * Immediately succeed.
+		 */
+		return pte;
+	} else {
+		int rc;
+		
+		/*
+		 * Mapping not found in page tables.
+		 * Resort to higher-level page fault handler.
+		 */
+		switch (rc = as_page_fault(badvaddr, access, istate)) {
+		case AS_PF_OK:
+			/*
+			 * The higher-level page fault handler succeeded,
+			 * The mapping ought to be in place.
+			 */
+			pte = page_mapping_find(AS, badvaddr, true);
+			ASSERT(pte);
+			ASSERT(pte->p);
+			ASSERT((pte->w) || (access != PF_ACCESS_WRITE));
+			return pte;
+		case AS_PF_DEFER:
+			*pfrc = AS_PF_DEFER;
+			return NULL;
+		case AS_PF_FAULT:
+			*pfrc = AS_PF_FAULT;
+			return NULL;
+		default:
+			panic("Unexpected return code (%d).", rc);
+		}
+	}
+}
+
+void tlb_prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d,
+    bool c, uintptr_t addr)
+{
+	lo->value = 0;
+	lo->g = g;
+	lo->v = v;
+	lo->d = d;
+	lo->c = c ? PAGE_CACHEABLE_EXC_WRITE : PAGE_UNCACHED;
+	lo->pfn = ADDR2PFN(addr);
+}
+
+void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr)
+{
+	hi->value = ALIGN_DOWN(addr, PAGE_SIZE * 2);
+	hi->asid = asid;
+}
+
+static void tlb_refill_fail(istate_t *istate)
+{
+	uintptr_t va = cp0_badvaddr_read();
+	
+	fault_if_from_uspace(istate, "TLB Refill Exception on %p.",
+	    (void *) va);
+	panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, "TLB Refill Exception.");
+}
+
+static void tlb_invalid_fail(istate_t *istate)
+{
+	uintptr_t va = cp0_badvaddr_read();
+	
+	fault_if_from_uspace(istate, "TLB Invalid Exception on %p.",
+	    (void *) va);
+	panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, "TLB Invalid Exception.");
+}
+
+static void tlb_modified_fail(istate_t *istate)
+{
+	uintptr_t va = cp0_badvaddr_read();
+	
+	fault_if_from_uspace(istate, "TLB Modified Exception on %p.",
+	    (void *) va);
+	panic_memtrap(istate, PF_ACCESS_WRITE, va, "TLB Modified Exception.");
+}
+
+/** Process TLB Refill Exception.
+ *
+ * @param istate Interrupted register context.
+ *
+ */
+void tlb_refill(istate_t *istate)
+{
+	uintptr_t badvaddr = cp0_badvaddr_read();
+	
+	mutex_lock(&AS->lock);
+	asid_t asid = AS->asid;
+	mutex_unlock(&AS->lock);
+	
+	int pfrc;
+	pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ,
+	    istate, &pfrc);
+	if (!pte) {
+		switch (pfrc) {
+		case AS_PF_FAULT:
+			goto fail;
+			break;
+		case AS_PF_DEFER:
+			/*
+			 * The page fault came during copy_from_uspace()
+			 * or copy_to_uspace().
+			 */
+			return;
+		default:
+			panic("Unexpected pfrc (%d).", pfrc);
+		}
+	}
+	
+	/*
+	 * Record access to PTE.
+	 */
+	pte->a = 1;
+	
+	entry_lo_t lo;
+	entry_hi_t hi;
+	
+	tlb_prepare_entry_hi(&hi, asid, badvaddr);
+	tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->c,
+	    pte->frame);
+	
+	/*
+	 * New entry is to be inserted into TLB
+	 */
+	cp0_entry_hi_write(hi.value);
+	
+	if ((badvaddr / PAGE_SIZE) % 2 == 0) {
+		cp0_entry_lo0_write(lo.value);
+		cp0_entry_lo1_write(0);
+	} else {
+		cp0_entry_lo0_write(0);
+		cp0_entry_lo1_write(lo.value);
+	}
+	
+	cp0_pagemask_write(TLB_PAGE_MASK_16K);
+	tlbwr();
+	
+	return;
+	
+fail:
+	tlb_refill_fail(istate);
+}
+
+/** Process TLB Invalid Exception.
+ *
+ * @param istate Interrupted register context.
+ *
+ */
+void tlb_invalid(istate_t *istate)
+{
+	uintptr_t badvaddr = cp0_badvaddr_read();
+	
+	/*
+	 * Locate the faulting entry in TLB.
+	 */
+	entry_hi_t hi;
+	hi.value = cp0_entry_hi_read();
+	
+	tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);
+	cp0_entry_hi_write(hi.value);
+	tlbp();
+	
+	tlb_index_t index;
+	index.value = cp0_index_read();
+	
+	/*
+	 * Fail if the entry is not in TLB.
+	 */
+	if (index.p) {
+		printf("TLB entry not found.\n");
+		goto fail;
+	}
+	
+	int pfrc;
+	pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ,
+	    istate, &pfrc);
+	if (!pte) {
+		switch (pfrc) {
+		case AS_PF_FAULT:
+			goto fail;
+			break;
+		case AS_PF_DEFER:
+			/*
+			 * The page fault came during copy_from_uspace()
+			 * or copy_to_uspace().
+			 */
+			return;
+		default:
+			panic("Unexpected pfrc (%d).", pfrc);
+		}
+	}
+	
+	/*
+	 * Read the faulting TLB entry.
+	 */
+	tlbr();
+	
+	/*
+	 * Record access to PTE.
+	 */
+	pte->a = 1;
+	
+	entry_lo_t lo;
+	tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, pte->c,
+	    pte->frame);
+	
+	/*
+	 * The entry is to be updated in TLB.
+	 */
+	if ((badvaddr / PAGE_SIZE) % 2 == 0)
+		cp0_entry_lo0_write(lo.value);
+	else
+		cp0_entry_lo1_write(lo.value);
+	
+	cp0_pagemask_write(TLB_PAGE_MASK_16K);
+	tlbwi();
+	
+	return;
+	
+fail:
+	tlb_invalid_fail(istate);
+}
+
+/** Process TLB Modified Exception.
+ *
+ * @param istate Interrupted register context.
+ *
+ */
+void tlb_modified(istate_t *istate)
+{
+	uintptr_t badvaddr = cp0_badvaddr_read();
+	
+	/*
+	 * Locate the faulting entry in TLB.
+	 */
+	entry_hi_t hi;
+	hi.value = cp0_entry_hi_read();
+	
+	tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);
+	cp0_entry_hi_write(hi.value);
+	tlbp();
+	
+	tlb_index_t index;
+	index.value = cp0_index_read();
+	
+	/*
+	 * Fail if the entry is not in TLB.
+	 */
+	if (index.p) {
+		printf("TLB entry not found.\n");
+		goto fail;
+	}
+	
+	int pfrc;
+	pte_t *pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE,
+	    istate, &pfrc);
+	if (!pte) {
+		switch (pfrc) {
+		case AS_PF_FAULT:
+			goto fail;
+			break;
+		case AS_PF_DEFER:
+			/*
+			 * The page fault came during copy_from_uspace()
+			 * or copy_to_uspace().
+			 */
+			return;
+		default:
+			panic("Unexpected pfrc (%d).", pfrc);
+		}
+	}
+	
+	/*
+	 * Read the faulting TLB entry.
+	 */
+	tlbr();
+	
+	/*
+	 * Record access and write to PTE.
+	 */
+	pte->a = 1;
+	pte->d = 1;
+	
+	entry_lo_t lo;
+	tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w, pte->c,
+	    pte->frame);
+	
+	/*
+	 * The entry is to be updated in TLB.
+	 */
+	if ((badvaddr / PAGE_SIZE) % 2 == 0)
+		cp0_entry_lo0_write(lo.value);
+	else
+		cp0_entry_lo1_write(lo.value);
+	
+	cp0_pagemask_write(TLB_PAGE_MASK_16K);
+	tlbwi();
+	
+	return;
+	
+fail:
+	tlb_modified_fail(istate);
+}
+
+/** Print contents of TLB. */
+void tlb_print(void)
+{
+	entry_hi_t hi_save;
+	hi_save.value = cp0_entry_hi_read();
+	
+	printf("[nr] [asid] [vpn2] [mask] [gvdc] [pfn ]\n");
+	
+	for (unsigned int i = 0; i < TLB_ENTRY_COUNT; i++) {
+		cp0_index_write(i);
+		tlbr();
+		
+		page_mask_t mask;
+		mask.value = cp0_pagemask_read();
+		
+		entry_hi_t hi;
+		hi.value = cp0_entry_hi_read();
+		
+		entry_lo_t lo0;
+		lo0.value = cp0_entry_lo0_read();
+		
+		entry_lo_t lo1;
+		lo1.value = cp0_entry_lo1_read();
+		
+		printf("%-4u %-6u %#6x %#6x  %1u%1u%1u%1u  %#6x\n",
+		    i, hi.asid, hi.vpn2, mask.mask,
+		    lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn);
+		printf("                           %1u%1u%1u%1u  %#6x\n",
+		    lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn);
+	}
+	
+	cp0_entry_hi_write(hi_save.value);
+}
+
+/** Invalidate all not wired TLB entries. */
+void tlb_invalidate_all(void)
+{
+	entry_hi_t hi_save;
+	hi_save.value = cp0_entry_hi_read();
+	ipl_t ipl = interrupts_disable();
+	
+	for (unsigned int i = TLB_WIRED; i < TLB_ENTRY_COUNT; i++) {
+		cp0_index_write(i);
+		tlbr();
+		
+		entry_lo_t lo0;
+		lo0.value = cp0_entry_lo0_read();
+		
+		entry_lo_t lo1;
+		lo1.value = cp0_entry_lo1_read();
+		
+		lo0.v = 0;
+		lo1.v = 0;
+		
+		cp0_entry_lo0_write(lo0.value);
+		cp0_entry_lo1_write(lo1.value);
+		
+		tlbwi();
+	}
+	
+	interrupts_restore(ipl);
+	cp0_entry_hi_write(hi_save.value);
+}
+
+/** Invalidate all TLB entries belonging to specified address space.
+ *
+ * @param asid Address space identifier.
+ *
+ */
+void tlb_invalidate_asid(asid_t asid)
+{
+	ASSERT(asid != ASID_INVALID);
+	
+	entry_hi_t hi_save;
+	hi_save.value = cp0_entry_hi_read();
+	ipl_t ipl = interrupts_disable();
+	
+	for (unsigned int i = 0; i < TLB_ENTRY_COUNT; i++) {
+		cp0_index_write(i);
+		tlbr();
+		
+		entry_hi_t hi;
+		hi.value = cp0_entry_hi_read();
+		
+		if (hi.asid == asid) {
+			entry_lo_t lo0;
+			lo0.value = cp0_entry_lo0_read();
+			
+			entry_lo_t lo1;
+			lo1.value = cp0_entry_lo1_read();
+			
+			lo0.v = 0;
+			lo1.v = 0;
+			
+			cp0_entry_lo0_write(lo0.value);
+			cp0_entry_lo1_write(lo1.value);
+			
+			tlbwi();
+		}
+	}
+	
+	interrupts_restore(ipl);
+	cp0_entry_hi_write(hi_save.value);
+}
+
+/** Invalidate TLB entries for specified page range belonging to specified
+ * address space.
+ *
+ * @param asid Address space identifier.
+ * @param page First page whose TLB entry is to be invalidated.
+ * @param cnt  Number of entries to invalidate.
+ *
+ */
+void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
+{
+	if (asid == ASID_INVALID)
+		return;
+	
+	entry_hi_t hi_save;
+	hi_save.value = cp0_entry_hi_read();
+	ipl_t ipl = interrupts_disable();
+	
+	for (unsigned int i = 0; i < cnt + 1; i += 2) {
+		entry_hi_t hi;
+		hi.value = 0;
+		tlb_prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE);
+		cp0_entry_hi_write(hi.value);
+		
+		tlbp();
+		
+		tlb_index_t index;
+		index.value = cp0_index_read();
+		
+		if (!index.p) {
+			/*
+			 * Entry was found, index register contains valid
+			 * index.
+			 */
+			tlbr();
+			
+			entry_lo_t lo0;
+			lo0.value = cp0_entry_lo0_read();
+			
+			entry_lo_t lo1;
+			lo1.value = cp0_entry_lo1_read();
+			
+			lo0.v = 0;
+			lo1.v = 0;
+			
+			cp0_entry_lo0_write(lo0.value);
+			cp0_entry_lo1_write(lo1.value);
+			
+			tlbwi();
+		}
+	}
+	
+	interrupts_restore(ipl);
+	cp0_entry_hi_write(hi_save.value);
+}
+
+/** @}
+ */
Index: kernel/arch/mips64/src/smp/dorder.c
===================================================================
--- kernel/arch/mips64/src/smp/dorder.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/smp/dorder.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007 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.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#include <typedefs.h>
+#include <smp/ipi.h>
+#include <arch/smp/dorder.h>
+
+#define MSIM_DORDER_ADDRESS  0xffffffffb0000100
+
+#ifdef CONFIG_SMP
+
+void ipi_broadcast_arch(int ipi)
+{
+	*((volatile uint32_t *) MSIM_DORDER_ADDRESS) = 0x7fffffff;
+}
+
+#endif
+
+uint32_t dorder_cpuid(void)
+{
+	return *((volatile uint32_t *) MSIM_DORDER_ADDRESS);
+}
+
+void dorder_ipi_ack(uint32_t mask)
+{
+	*((volatile uint32_t *) (MSIM_DORDER_ADDRESS + 4)) = mask;
+}
+
+/** @}
+ */
Index: kernel/arch/mips64/src/smp/smp.c
===================================================================
--- kernel/arch/mips64/src/smp/smp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/smp/smp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+/** @addtogroup mips64
+ * @{
+ */
+/** @file
+ */
+
+#include <config.h>
+#include <smp/smp.h>
+#include <arch/arch.h>
+
+#ifdef CONFIG_SMP
+
+void smp_init(void)
+{
+	config.cpu_count = cpu_count;
+}
+
+void kmp(void *arg __attribute__((unused)))
+{
+}
+
+#endif /* CONFIG_SMP */
+
+/** @}
+ */
Index: kernel/arch/mips64/src/start.S
===================================================================
--- kernel/arch/mips64/src/start.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/mips64/src/start.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,385 @@
+#
+# Copyright (c) 2003-2004 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.
+#
+
+#include <arch/asm/regname.h>
+#include <arch/mm/page.h>
+#include <arch/asm/boot.h>
+#include <arch/context_offset.h>
+#include <arch/stack.h>
+
+.text
+
+.set noat
+.set noreorder
+.set nomacro
+
+.global kernel_image_start
+.global tlb_refill_entry
+.global cache_error_entry
+.global exception_entry
+.global userspace_asm
+
+/*
+ * Which status bits are thread-local:
+ * KSU(UM), EXL, ERL, IE
+ */
+#define REG_SAVE_MASK 0x1f
+
+#define ISTATE_OFFSET_A0         0
+#define ISTATE_OFFSET_A1         8
+#define ISTATE_OFFSET_A2         16
+#define ISTATE_OFFSET_A3         24
+#define ISTATE_OFFSET_T0         32
+#define ISTATE_OFFSET_T1         40
+#define ISTATE_OFFSET_V0         48
+#define ISTATE_OFFSET_V1         56
+#define ISTATE_OFFSET_AT         64
+#define ISTATE_OFFSET_T2         72
+#define ISTATE_OFFSET_T3         80
+#define ISTATE_OFFSET_T4         88
+#define ISTATE_OFFSET_T5         96
+#define ISTATE_OFFSET_T6         104
+#define ISTATE_OFFSET_T7         112
+#define ISTATE_OFFSET_S0         120
+#define ISTATE_OFFSET_S1         128
+#define ISTATE_OFFSET_S2         136
+#define ISTATE_OFFSET_S3         144
+#define ISTATE_OFFSET_S4         152
+#define ISTATE_OFFSET_S5         160
+#define ISTATE_OFFSET_S6         168
+#define ISTATE_OFFSET_S7         176
+#define ISTATE_OFFSET_T8         184
+#define ISTATE_OFFSET_T9         192
+#define ISTATE_OFFSET_KT0        200
+#define ISTATE_OFFSET_KT1        208
+#define ISTATE_OFFSET_GP         216
+#define ISTATE_OFFSET_SP         224
+#define ISTATE_OFFSET_S8         232
+#define ISTATE_OFFSET_RA         240
+#define ISTATE_OFFSET_LO         248
+#define ISTATE_OFFSET_HI         252
+#define ISTATE_OFFSET_STATUS     256
+#define ISTATE_OFFSET_EPC        264
+#define ISTATE_OFFSET_ALIGNMENT  272
+
+#define ISTATE_SOFT_SIZE         280
+
+/*
+ * The fake ABI prologue is never executed and may not be part of the
+ * procedure's body. Instead, it should be immediately preceding the procedure's
+ * body. Its only purpose is to trick the stack trace walker into thinking that
+ * the exception is more or less just a normal function call.
+ */
+.macro FAKE_ABI_PROLOGUE
+	sub $sp, ISTATE_SOFT_SIZE
+	sd $ra, ISTATE_OFFSET_EPC($sp)
+.endm
+
+/*
+ * Save registers to space defined by \r
+ * We will change status: Disable ERL, EXL, UM, IE
+ * These changes will be automatically reversed in REGISTER_LOAD
+ * %sp is NOT saved as part of these registers
+ */
+.macro REGISTERS_STORE_AND_EXC_RESET r
+	sd $at, ISTATE_OFFSET_AT(\r)
+	sd $v0, ISTATE_OFFSET_V0(\r)
+	sd $v1, ISTATE_OFFSET_V1(\r)
+	sd $a0, ISTATE_OFFSET_A0(\r)
+	sd $a1, ISTATE_OFFSET_A1(\r)
+	sd $a2, ISTATE_OFFSET_A2(\r)
+	sd $a3, ISTATE_OFFSET_A3(\r)
+	sd $t0, ISTATE_OFFSET_T0(\r)
+	sd $t1, ISTATE_OFFSET_T1(\r)
+	sd $t2, ISTATE_OFFSET_T2(\r)
+	sd $t3, ISTATE_OFFSET_T3(\r)
+	sd $t4, ISTATE_OFFSET_T4(\r)
+	sd $t5, ISTATE_OFFSET_T5(\r)
+	sd $t6, ISTATE_OFFSET_T6(\r)
+	sd $t7, ISTATE_OFFSET_T7(\r)
+	sd $t8, ISTATE_OFFSET_T8(\r)
+	sd $t9, ISTATE_OFFSET_T9(\r)
+	sd $s0, ISTATE_OFFSET_S0(\r)
+	sd $s1, ISTATE_OFFSET_S1(\r)
+	sd $s2, ISTATE_OFFSET_S2(\r)
+	sd $s3, ISTATE_OFFSET_S3(\r)
+	sd $s4, ISTATE_OFFSET_S4(\r)
+	sd $s5, ISTATE_OFFSET_S5(\r)
+	sd $s6, ISTATE_OFFSET_S6(\r)
+	sd $s7, ISTATE_OFFSET_S7(\r)
+	sd $s8, ISTATE_OFFSET_S8(\r)
+	
+	mflo $at
+	sw $at, ISTATE_OFFSET_LO(\r)
+	mfhi $at
+	sw $at, ISTATE_OFFSET_HI(\r)
+	
+	sd $gp, ISTATE_OFFSET_GP(\r)
+	sd $ra, ISTATE_OFFSET_RA(\r)
+	sd $k0, ISTATE_OFFSET_KT0(\r)
+	sd $k1, ISTATE_OFFSET_KT1(\r)
+	
+	dmfc0 $t0, $status
+	dmfc0 $t1, $epc
+	
+	/* save only KSU, EXL, ERL, IE */
+	and $t2, $t0, REG_SAVE_MASK
+	
+	/* clear KSU, EXL, ERL, IE */
+	li $t3, ~(REG_SAVE_MASK)
+	and $t0, $t0, $t3
+	
+	sd $t2, ISTATE_OFFSET_STATUS(\r)
+	sd $t1, ISTATE_OFFSET_EPC(\r)
+	dmtc0 $t0, $status
+.endm
+
+.macro REGISTERS_LOAD r
+	/*
+	 * Update only UM, EXR, IE from status, the rest
+	 * is controlled by OS and not bound to task.
+	 */
+	dmfc0 $t0, $status
+	ld $t1, ISTATE_OFFSET_STATUS(\r)
+	
+	/* mask UM, EXL, ERL, IE */
+	li $t2, ~REG_SAVE_MASK
+	and $t0, $t0, $t2
+	
+	/* copy UM, EXL, ERL, IE from saved status */
+	or $t0, $t0, $t1
+	dmtc0 $t0, $status
+	
+	ld $v0, ISTATE_OFFSET_V0(\r)
+	ld $v1, ISTATE_OFFSET_V1(\r)
+	ld $a0, ISTATE_OFFSET_A0(\r)
+	ld $a1, ISTATE_OFFSET_A1(\r)
+	ld $a2, ISTATE_OFFSET_A2(\r)
+	ld $a3, ISTATE_OFFSET_A3(\r)
+	ld $t0, ISTATE_OFFSET_T0(\r)
+	ld $t1, ISTATE_OFFSET_T1(\r)
+	ld $t2, ISTATE_OFFSET_T2(\r)
+	ld $t3, ISTATE_OFFSET_T3(\r)
+	ld $t4, ISTATE_OFFSET_T4(\r)
+	ld $t5, ISTATE_OFFSET_T5(\r)
+	ld $t6, ISTATE_OFFSET_T6(\r)
+	ld $t7, ISTATE_OFFSET_T7(\r)
+	ld $t8, ISTATE_OFFSET_T8(\r)
+	ld $t9, ISTATE_OFFSET_T9(\r)
+	
+	ld $gp, ISTATE_OFFSET_GP(\r)
+	ld $ra, ISTATE_OFFSET_RA(\r)
+	ld $k1, ISTATE_OFFSET_KT1(\r)
+	
+	lw $at, ISTATE_OFFSET_LO(\r)
+	mtlo $at
+	lw $at, ISTATE_OFFSET_HI(\r)
+	mthi $at
+	
+	ld $at, ISTATE_OFFSET_EPC(\r)
+	dmtc0 $at, $epc
+	
+	ld $at, ISTATE_OFFSET_AT(\r)
+	ld $sp, ISTATE_OFFSET_SP(\r)
+.endm
+
+/*
+ * Move kernel stack pointer address to register $k0.
+ * If we are in user mode, load the appropriate stack address.
+ */
+.macro KERNEL_STACK_TO_K0
+	/* if we are in user mode */
+	dmfc0 $k0, $status
+	andi $k0, 0x10
+	
+	beq $k0, $0, 1f
+	move $k0, $sp
+	
+	/* move $k0 pointer to kernel stack */
+	dla $k0, supervisor_sp
+	
+	/* move $k0 (supervisor_sp) */
+	lw $k0, ($k0)
+	
+	1:
+.endm
+
+.org 0x0
+kernel_image_start:
+	/* load temporary stack */
+	lui $sp, %hi(end_stack)
+	ori $sp, $sp, %lo(end_stack)
+	
+	/* not sure about this, but might be needed for PIC code */
+	lui $gp, 0x8000
+	
+	/* $a1 contains physical address of bootinfo_t */
+	jal arch_pre_main
+	nop
+	
+	j main_bsp
+	nop
+
+.space TEMP_STACK_SIZE
+end_stack:
+
+tlb_refill_entry:
+	j tlb_refill_handler
+	nop
+
+cache_error_entry:
+	j cache_error_handler
+	nop
+
+exception_entry:
+	j exception_handler
+	nop
+
+	FAKE_ABI_PROLOGUE
+exception_handler:
+	KERNEL_STACK_TO_K0
+	
+	sub $k0, ISTATE_SOFT_SIZE
+	sw $sp, ISTATE_OFFSET_SP($k0)
+	move $sp, $k0
+	
+	mfc0 $k0, $cause
+	
+	sra $k0, $k0, 0x2    /* cp0_exc_cause() part 1 */
+	andi $k0, $k0, 0x1f  /* cp0_exc_cause() part 2 */
+	sub $k0, 8           /* 8 = SYSCALL */
+	
+	beqz $k0, syscall_shortcut
+	add $k0, 8           /* revert $k0 back to correct exc number */
+	
+	REGISTERS_STORE_AND_EXC_RESET $sp
+	
+	move $a1, $sp
+	jal exc_dispatch     /* exc_dispatch(excno, register_space) */
+	move $a0, $k0
+	
+	REGISTERS_LOAD $sp
+	/* the $sp is automatically restored to former value */
+	eret
+
+/** Syscall entry
+ *
+ * Registers:
+ *
+ * @param $v0 Syscall number.
+ * @param $a0 1st argument.
+ * @param $a1 2nd argument.
+ * @param $a2 3rd argument.
+ * @param $a3 4th argument.
+ * @param $t0 5th argument.
+ * @param $t1 6th argument.
+ *
+ * @return The return value will be stored in $v0.
+ *
+ */
+syscall_shortcut:
+	mfc0 $t3, $epc
+	mfc0 $t2, $status
+	sw $t3, ISTATE_OFFSET_EPC($sp)  /* save EPC */
+	sw $k1, ISTATE_OFFSET_KT1($sp)  /* save $k1 not saved on context switch */
+	
+	and $t4, $t2, REG_SAVE_MASK  /* save only KSU, EXL, ERL, IE */
+	li $t5, ~(0x1f)
+	and $t2, $t2, $t5  /* clear KSU, EXL, ERL */
+	ori $t2, $t2, 0x1  /* set IE */
+	
+	sw $t4, ISTATE_OFFSET_STATUS($sp)
+	mtc0 $t2, $status
+	
+	/*
+	 * Call the higher level system call handler.
+	 *
+	 */
+	sw $t0, ISTATE_OFFSET_T0($sp)  /* save the 5th argument on the stack */
+	sw $t1, ISTATE_OFFSET_T1($sp)  /* save the 6th argument on the stack */
+	jal syscall_handler
+	sw $v0, ISTATE_OFFSET_V0($sp)  /* save the syscall number on the stack */
+	
+	/* restore status */
+	mfc0 $t2, $status
+	lw $t3, ISTATE_OFFSET_STATUS($sp)
+	
+	/*
+	 * Change back to EXL = 1 (from last exception), otherwise
+	 * an interrupt could rewrite the CP0 - EPC.
+	 *
+	 */
+	li $t4, ~REG_SAVE_MASK  /* mask UM, EXL, ERL, IE */
+	and $t2, $t2, $t4
+	or $t2, $t2, $t3  /* copy saved UM, EXL, ERL, IE */
+	mtc0 $t2, $status
+	
+	/* restore epc + 4 */
+	lw $t2, ISTATE_OFFSET_EPC($sp)
+	lw $k1, ISTATE_OFFSET_KT1($sp)
+	addi $t2, $t2, 4
+	mtc0 $t2, $epc
+	
+	lw $sp, ISTATE_OFFSET_SP($sp)  /* restore $sp */
+	eret
+
+	FAKE_ABI_PROLOGUE
+tlb_refill_handler:
+	KERNEL_STACK_TO_K0
+	sub $k0, ISTATE_SOFT_SIZE
+	REGISTERS_STORE_AND_EXC_RESET $k0
+	sw $sp, ISTATE_OFFSET_SP($k0)
+	move $sp, $k0
+	
+	jal tlb_refill
+	move $a0, $sp 
+	
+	REGISTERS_LOAD $sp
+	eret
+
+	FAKE_ABI_PROLOGUE
+cache_error_handler:
+	KERNEL_STACK_TO_K0
+	sub $k0, ISTATE_SOFT_SIZE 
+	REGISTERS_STORE_AND_EXC_RESET $k0
+	sw $sp, ISTATE_OFFSET_SP($k0)
+	move $sp, $k0
+	
+	jal cache_error
+	move $a0, $sp
+	
+	REGISTERS_LOAD $sp
+	eret
+
+userspace_asm:
+	move $sp, $a0
+	move $v0, $a1
+	move $t9, $a2      /* set up correct entry into PIC code */
+	xor $a0, $a0, $a0  /* $a0 is defined to hold pcb_ptr */
+	                   /* set it to 0 */
+	eret
Index: kernel/arch/ppc32/Makefile.inc
===================================================================
--- kernel/arch/ppc32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -55,4 +55,5 @@
 	arch/$(KARCH)/src/mm/frame.c \
 	arch/$(KARCH)/src/mm/page.c \
+	arch/$(KARCH)/src/mm/pht.c \
 	arch/$(KARCH)/src/mm/tlb.c \
 	arch/$(KARCH)/src/drivers/pic.c
Index: kernel/arch/ppc32/_link.ld.in
===================================================================
--- kernel/arch/ppc32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,5 @@
 		kdata_start = .;
 		*(K_DATA_START);
-		*(.rodata);
-		*(.rodata.*);
+		*(.rodata .rodata.*);
 		*(.data);       /* initialized data */
 		*(.sdata);
Index: kernel/arch/ppc32/include/asm.h
===================================================================
--- kernel/arch/ppc32/include/asm.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/asm.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 #include <typedefs.h>
 #include <config.h>
-#include <arch/cpu.h>
+#include <arch/msr.h>
 #include <arch/mm/asid.h>
 #include <trace.h>
Index: kernel/arch/ppc32/include/boot/boot.h
===================================================================
--- kernel/arch/ppc32/include/boot/boot.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/boot/boot.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,7 +37,4 @@
 
 #define BOOT_OFFSET  0x8000
-
-/* Temporary stack size for boot process */
-#define TEMP_STACK_SIZE  0x1000
 
 #define TASKMAP_MAX_RECORDS        32
Index: kernel/arch/ppc32/include/context_offset.h
===================================================================
--- kernel/arch/ppc32/include/context_offset.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -75,7 +75,16 @@
 
 #ifdef __ASM__
-# include <arch/asm/regname.h>
 
-# ctx: address of the structure with saved context
+#ifdef KERNEL
+
+#include <arch/asm/regname.h>
+
+#else /* KERNEL */
+
+#include <libarch/regname.h>
+
+#endif /* KERNEL */
+
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_SAVE_ARCH_CORE ctx:req
 	stw sp, OFFSET_SP(\ctx)
@@ -102,5 +111,5 @@
 .endm
 
-# ctx: address of the structure with saved context
+/* ctx: address of the structure with saved context */
 .macro CONTEXT_RESTORE_ARCH_CORE ctx:req
 	lwz sp, OFFSET_SP(\ctx)
Index: kernel/arch/ppc32/include/cpu.h
===================================================================
--- kernel/arch/ppc32/include/cpu.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/cpu.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,19 +36,4 @@
 #define KERN_ppc32_CPU_H_
 
-/* MSR bits */
-#define MSR_DR  (1 << 4)
-#define MSR_IR  (1 << 5)
-#define MSR_PR  (1 << 14)
-#define MSR_EE  (1 << 15)
-
-/* HID0 bits */
-#define HID0_STEN  (1 << 24)
-#define HID0_ICE   (1 << 15)
-#define HID0_DCE   (1 << 14)
-#define HID0_ICFI  (1 << 11)
-#define HID0_DCI   (1 << 10)
-
-#ifndef __ASM__
-
 #include <typedefs.h>
 #include <trace.h>
@@ -67,6 +52,4 @@
 }
 
-#endif /* __ASM__ */
-
 #endif
 
Index: kernel/arch/ppc32/include/exception.h
===================================================================
--- kernel/arch/ppc32/include/exception.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/exception.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 
 #include <typedefs.h>
-#include <arch/cpu.h>
+#include <arch/msr.h>
 #include <trace.h>
 
Index: kernel/arch/ppc32/include/interrupt.h
===================================================================
--- kernel/arch/ppc32/include/interrupt.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/interrupt.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,4 +45,7 @@
 #define VECTOR_EXTERNAL             4
 #define VECTOR_DECREMENTER          8
+#define VECTOR_ITLB_MISS            13
+#define VECTOR_DTLB_MISS_LOAD       14
+#define VECTOR_DTLB_MISS_STORE      15
 
 extern void start_decrementer(void);
Index: kernel/arch/ppc32/include/istate.h
===================================================================
--- kernel/arch/ppc32/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,7 +36,15 @@
 #define KERN_ppc32_EXCEPTION_H_
 
-#include <typedefs.h>
-#include <arch/cpu.h>
 #include <trace.h>
+
+#ifdef KERNEL
+
+#include <arch/msr.h>
+
+#else /* KERNEL */
+
+#include <libarch/msr.h>
+
+#endif /* KERNEL */
 
 typedef struct istate {
@@ -73,5 +81,5 @@
 	uint32_t cr;
 	uint32_t pc;
-	uint32_t srr1;
+	uint32_t msr;
 	uint32_t lr;
 	uint32_t ctr;
@@ -90,10 +98,8 @@
 /** Return true if exception happened while in userspace
  *
- * The contexts of MSR register was stored in SRR1.
- *
  */
 NO_TRACE static inline int istate_from_uspace(istate_t *istate)
 {
-	return (istate->srr1 & MSR_PR) != 0;
+	return (istate->msr & MSR_PR) != 0;
 }
 
Index: rnel/arch/ppc32/include/memstr.h
===================================================================
--- kernel/arch/ppc32/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2005 Sergey Bondari
- * 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 ppc32
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_ppc32_MEMSTR_H_
-#define KERN_ppc32_MEMSTR_H_
-
-#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
-
-extern void memsetw(void *, size_t, uint16_t);
-extern void memsetb(void *, size_t, uint8_t);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/ppc32/include/mm/as.h
===================================================================
--- kernel/arch/ppc32/include/mm/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,12 +36,12 @@
 #define KERN_ppc32_AS_H_
 
+#include <arch/mm/pht.h>
+
 #define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  0
 
-#define KERNEL_ADDRESS_SPACE_START_ARCH  ((unsigned long) 0x80000000)
-#define KERNEL_ADDRESS_SPACE_END_ARCH    ((unsigned long) 0xffffffff)
-#define USER_ADDRESS_SPACE_START_ARCH    ((unsigned long) 0x00000000)
-#define USER_ADDRESS_SPACE_END_ARCH      ((unsigned long) 0x7fffffff)
-
-#define USTACK_ADDRESS_ARCH  (0x7fffffff - (PAGE_SIZE - 1))
+#define KERNEL_ADDRESS_SPACE_START_ARCH  UINT32_C(0x80000000)
+#define KERNEL_ADDRESS_SPACE_END_ARCH    UINT32_C(0xffffffff)
+#define USER_ADDRESS_SPACE_START_ARCH    UINT32_C(0x00000000)
+#define USER_ADDRESS_SPACE_END_ARCH      UINT32_C(0x7fffffff)
 
 typedef struct {
@@ -54,5 +54,7 @@
 #define as_create_arch(as, flags)       (as != as)
 #define as_deinstall_arch(as)
-#define as_invalidate_translation_cache(as, page, cnt)
+
+#define as_invalidate_translation_cache(as, page, cnt) \
+	pht_invalidate((as), (page), (cnt))
 
 extern void as_arch_init(void);
Index: kernel/arch/ppc32/include/mm/frame.h
===================================================================
--- kernel/arch/ppc32/include/mm/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #define FRAME_SIZE   (1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -63,5 +62,4 @@
 
 #endif /* __ASM__ */
-#endif /* KERNEL */
 
 #endif
Index: kernel/arch/ppc32/include/mm/page.h
===================================================================
--- kernel/arch/ppc32/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,6 +41,4 @@
 #define PAGE_WIDTH  FRAME_WIDTH
 #define PAGE_SIZE   FRAME_SIZE
-
-#ifdef KERNEL
 
 #ifndef __ASM__
@@ -181,6 +179,4 @@
 #endif /* __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/ppc32/include/mm/pht.h
===================================================================
--- kernel/arch/ppc32/include/mm/pht.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/ppc32/include/mm/pht.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/** @addtogroup ppc32mm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_ppc32_PHT_H_
+#define KERN_ppc32_PHT_H_
+
+#include <arch/interrupt.h>
+#include <typedefs.h>
+
+/* Forward declaration. */
+struct as;
+
+extern void pht_init(void);
+extern void pht_refill(unsigned int, istate_t *);
+extern void pht_invalidate(struct as *, uintptr_t, size_t);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/ppc32/include/mm/tlb.h
===================================================================
--- kernel/arch/ppc32/include/mm/tlb.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/mm/tlb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,4 @@
 
 #include <arch/interrupt.h>
-#include <typedefs.h>
 
 #define WIMG_GUARDED    0x01
@@ -75,11 +74,5 @@
 } ptelo_t;
 
-extern void pht_init(void);
-extern void pht_refill(unsigned int, istate_t *);
-
-extern bool pht_refill_real(unsigned int, istate_t *)
-    __attribute__ ((section("K_UNMAPPED_TEXT_START")));
-extern void tlb_refill_real(unsigned int, uint32_t, ptehi_t, ptelo_t,
-    istate_t *) __attribute__ ((section("K_UNMAPPED_TEXT_START")));
+extern void tlb_refill(unsigned int, istate_t *);
 
 #endif
Index: kernel/arch/ppc32/include/msr.h
===================================================================
--- kernel/arch/ppc32/include/msr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/ppc32/include/msr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ppc32
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_ppc32_MSR_H_
+#define KERN_ppc32_MSR_H_
+
+/* MSR bits */
+#define MSR_DR  (1 << 4)
+#define MSR_IR  (1 << 5)
+#define MSR_PR  (1 << 14)
+#define MSR_EE  (1 << 15)
+
+/* HID0 bits */
+#define HID0_STEN  (1 << 24)
+#define HID0_ICE   (1 << 15)
+#define HID0_DCE   (1 << 14)
+#define HID0_ICFI  (1 << 11)
+#define HID0_DCI   (1 << 10)
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/ppc32/include/types.h
===================================================================
--- kernel/arch/ppc32/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
 
 typedef uint32_t size_t;
+typedef int32_t ssize_t;
 
 typedef uint32_t uintptr_t;
Index: kernel/arch/ppc32/src/asm.S
===================================================================
--- kernel/arch/ppc32/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -28,5 +28,5 @@
 
 #include <arch/asm/regname.h>
-#include <arch/cpu.h>
+#include <arch/msr.h>
 
 .text
@@ -35,7 +35,4 @@
 .global iret
 .global iret_syscall
-.global memsetb
-.global memsetw
-.global memcpy
 .global memcpy_from_uspace
 .global memcpy_to_uspace
@@ -208,11 +205,4 @@
 	rfi
 
-memsetb:
-	b _memsetb
-
-memsetw:
-	b _memsetw
-
-memcpy:
 memcpy_from_uspace:
 memcpy_to_uspace:
Index: kernel/arch/ppc32/src/boot/boot.S
===================================================================
--- kernel/arch/ppc32/src/boot/boot.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/src/boot/boot.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -28,5 +28,5 @@
 
 #include <arch/asm/regname.h>
-#include <arch/boot/boot.h>
+#include <config.h>
 
 .section K_TEXT_START, "ax"
@@ -56,4 +56,4 @@
 .align 12
 kernel_stack_bottom:
-	.space TEMP_STACK_SIZE
+	.space STACK_SIZE
 kernel_stack:
Index: kernel/arch/ppc32/src/exception.S
===================================================================
--- kernel/arch/ppc32/src/exception.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/src/exception.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -28,5 +28,5 @@
 
 #include <arch/asm/regname.h>
-#include <arch/cpu.h>
+#include <arch/msr.h>
 #include <arch/mm/page.h>
 
@@ -142,5 +142,6 @@
 	CONTEXT_STORE
 	
-	b data_storage
+	li r3, 2
+	b jump_to_kernel
 
 .org 0x400
@@ -149,5 +150,6 @@
 	CONTEXT_STORE
 	
-	b instruction_storage
+	li r3, 3
+	b jump_to_kernel
 
 .org 0x500
@@ -227,5 +229,6 @@
 	CONTEXT_STORE
 	
-	b tlb_miss
+	li r3, 13
+	b jump_to_kernel
 
 .org 0x1100
@@ -234,5 +237,6 @@
 	CONTEXT_STORE
 	
-	b tlb_miss
+	li r3, 14
+	b jump_to_kernel
 
 .org 0x1200
@@ -241,42 +245,8 @@
 	CONTEXT_STORE
 	
-	b tlb_miss
+	li r3, 15
+	b jump_to_kernel
 
 .org 0x4000
-data_storage:
-	li r3, 2
-	mr r4, sp
-	addi r4, r4, 8
-	bl pht_refill_real
-	
-	cmpwi r3, 0
-	bne iret_real
-	
-	li r3, 2
-	b jump_to_kernel
-
-instruction_storage:
-	li r3, 3
-	mr r4, sp
-	addi r4, r4, 8
-	bl pht_refill_real
-	
-	cmpwi r3, 0
-	bne iret_real
-	
-	li r3, 3
-	b jump_to_kernel
-
-tlb_miss:
-	li r3, 16
-	mfspr r4, tlbmiss
-	mfspr r5, ptehi
-	mfspr r6, ptelo
-	mr r7, sp
-	addi r7, r7, 20
-	
-	bl tlb_refill_real
-	b iret_real
-
 jump_to_kernel:
 	lis r12, iret@ha
@@ -313,57 +283,2 @@
 	addis sp, sp, 0x8000
 	rfi
-
-iret_real:
-	lwz r0, 8(sp)
-	lwz r2, 12(sp)
-	lwz r3, 16(sp)
-	lwz r4, 20(sp)
-	lwz r5, 24(sp)
-	lwz r6, 28(sp)
-	lwz r7, 32(sp)
-	lwz r8, 36(sp)
-	lwz r9, 40(sp)
-	lwz r10, 44(sp)
-	lwz r11, 48(sp)
-	lwz r13, 52(sp)
-	lwz r14, 56(sp)
-	lwz r15, 60(sp)
-	lwz r16, 64(sp)
-	lwz r17, 68(sp)
-	lwz r18, 72(sp)
-	lwz r19, 76(sp)
-	lwz r20, 80(sp)
-	lwz r21, 84(sp)
-	lwz r22, 88(sp)
-	lwz r23, 92(sp)
-	lwz r24, 96(sp)
-	lwz r25, 100(sp)
-	lwz r26, 104(sp)
-	lwz r27, 108(sp)
-	lwz r28, 112(sp)
-	lwz r29, 116(sp)
-	lwz r30, 120(sp)
-	lwz r31, 124(sp)
-	
-	lwz r12, 128(sp)
-	mtcr r12
-	
-	lwz r12, 132(sp)
-	mtsrr0 r12
-	
-	lwz r12, 136(sp)
-	mtsrr1 r12
-	
-	lwz r12, 140(sp)
-	mtlr r12
-	
-	lwz r12, 144(sp)
-	mtctr r12
-	
-	lwz r12, 148(sp)
-	mtxer r12
-	
-	lwz r12, 156(sp)
-	lwz sp, 160(sp)
-	
-	rfi
Index: kernel/arch/ppc32/src/interrupt.c
===================================================================
--- kernel/arch/ppc32/src/interrupt.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/src/interrupt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,4 +42,5 @@
 #include <arch/drivers/pic.h>
 #include <arch/mm/tlb.h>
+#include <arch/mm/pht.h>
 #include <print.h>
 
@@ -54,44 +55,44 @@
 void istate_decode(istate_t *istate)
 {
-	printf("r0 =%#0" PRIx32 "\tr1 =%p\tr2 =%#0" PRIx32 "\n",
-	    istate->r0, (void *) istate->sp, istate->r2);
+	printf("r0 =%0#10" PRIx32 "\tr1 =%0#10" PRIx32 "\t"
+	    "r2 =%0#10" PRIx32 "\n", istate->r0, istate->sp, istate->r2);
 	
-	printf("r3 =%#0" PRIx32 "\tr4 =%#0" PRIx32 "\tr5 =%#0" PRIx32 "\n",
-	    istate->r3, istate->r4, istate->r5);
+	printf("r3 =%0#10" PRIx32 "\tr4 =%0#10" PRIx32 "\t"
+	    "r5 =%0#10" PRIx32 "\n", istate->r3, istate->r4, istate->r5);
 	
-	printf("r6 =%#0" PRIx32 "\tr7 =%#0" PRIx32 "\tr8 =%#0" PRIx32 "\n",
-	    istate->r6, istate->r7, istate->r8);
+	printf("r6 =%0#10" PRIx32 "\tr7 =%0#10" PRIx32 "\t"
+	    "r8 =%0#10" PRIx32 "\n", istate->r6, istate->r7, istate->r8);
 	
-	printf("r9 =%#0" PRIx32 "\tr10=%#0" PRIx32 "\tr11=%#0" PRIx32 "\n",
-	    istate->r9, istate->r10, istate->r11);
+	printf("r9 =%0#10" PRIx32 "\tr10=%0#10" PRIx32 "\t"
+	    "r11=%0#10" PRIx32 "\n", istate->r9, istate->r10, istate->r11);
 	
-	printf("r12=%#0" PRIx32 "\tr13=%#0" PRIx32 "\tr14=%#0" PRIx32 "\n",
-	    istate->r12, istate->r13, istate->r14);
+	printf("r12=%0#10" PRIx32 "\tr13=%0#10" PRIx32 "\t"
+	    "r14=%0#10" PRIx32 "\n", istate->r12, istate->r13, istate->r14);
 	
-	printf("r15=%#0" PRIx32 "\tr16=%#0" PRIx32 "\tr17=%#0" PRIx32 "\n",
-	    istate->r15, istate->r16, istate->r17);
+	printf("r15=%0#10" PRIx32 "\tr16=%0#10" PRIx32 "\t"
+	    "r17=%0#10" PRIx32 "\n", istate->r15, istate->r16, istate->r17);
 	
-	printf("r18=%#0" PRIx32 "\tr19=%#0" PRIx32 "\tr20=%#0" PRIx32 "\n",
-	    istate->r18, istate->r19, istate->r20);
+	printf("r18=%0#10" PRIx32 "\tr19=%0#10" PRIx32 "\t"
+	    "r20=%0#10" PRIx32 "\n", istate->r18, istate->r19, istate->r20);
 	
-	printf("r21=%#0" PRIx32 "\tr22=%#0" PRIx32 "\tr23=%#0" PRIx32 "\n",
-	    istate->r21, istate->r22, istate->r23);
+	printf("r21=%0#10" PRIx32 "\tr22=%0#10" PRIx32 "\t"
+	    "r23=%0#10" PRIx32 "\n", istate->r21, istate->r22, istate->r23);
 	
-	printf("r24=%#0" PRIx32 "\tr25=%#0" PRIx32 "\tr26=%#0" PRIx32 "\n",
-	    istate->r24, istate->r25, istate->r26);
+	printf("r24=%0#10" PRIx32 "\tr25=%0#10" PRIx32 "\t"
+	    "r26=%0#10" PRIx32 "\n", istate->r24, istate->r25, istate->r26);
 	
-	printf("r27=%#0" PRIx32 "\tr28=%#0" PRIx32 "\tr29=%#0" PRIx32 "\n",
-	    istate->r27, istate->r28, istate->r29);
+	printf("r27=%0#10" PRIx32 "\tr28=%0#10" PRIx32 "\t"
+	    "r29=%0#10" PRIx32 "\n", istate->r27, istate->r28, istate->r29);
 	
-	printf("r30=%#0" PRIx32 "\tr31=%#0" PRIx32 "\n",
+	printf("r30=%0#10" PRIx32 "\tr31=%0#10" PRIx32 "\n",
 	    istate->r30, istate->r31);
 	
-	printf("cr =%#0" PRIx32 "\tpc =%p\tlr =%p\n",
-	    istate->cr, (void *) istate->pc, (void *) istate->lr);
+	printf("cr =%0#10" PRIx32 "\tpc =%0#10" PRIx32 "\t"
+	    "lr =%0#10" PRIx32 "\n", istate->cr, istate->pc, istate->lr);
 	
-	printf("ctr=%#0" PRIx32 "\txer=%#0" PRIx32 "\tdar=%#0" PRIx32 "\n",
-	    istate->ctr, istate->xer, istate->dar);
+	printf("ctr=%0#10" PRIx32 "\txer=%0#10" PRIx32 "\t"
+	    "dar=%0#10" PRIx32 "\n", istate->ctr, istate->xer, istate->dar);
 	
-	printf("srr1=%p\n", (void *) istate->srr1);
+	printf("srr1=%0#10" PRIx32 "\n", istate->srr1);
 }
 
@@ -153,4 +154,10 @@
 	exc_register(VECTOR_DECREMENTER, "timer", true,
 	    exception_decrementer);
+	exc_register(VECTOR_ITLB_MISS, "itlb_miss", true,
+	    tlb_refill);
+	exc_register(VECTOR_DTLB_MISS_LOAD, "dtlb_miss_load", true,
+	    tlb_refill);
+	exc_register(VECTOR_DTLB_MISS_STORE, "dtlb_miss_store", true,
+	    tlb_refill);
 }
 
Index: kernel/arch/ppc32/src/mm/page.c
===================================================================
--- kernel/arch/ppc32/src/mm/page.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/src/mm/page.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,4 +43,5 @@
 	if (config.cpu_active == 1)
 		page_mapping_operations = &pt_mapping_operations;
+	as_switch(NULL, AS_KERNEL);
 }
 
Index: kernel/arch/ppc32/src/mm/pht.c
===================================================================
--- kernel/arch/ppc32/src/mm/pht.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/arch/ppc32/src/mm/pht.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/** @addtogroup ppc32mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/pht.h>
+#include <arch/mm/tlb.h>
+#include <interrupt.h>
+#include <mm/as.h>
+#include <mm/page.h>
+#include <macros.h>
+#include <typedefs.h>
+
+static unsigned int seed = 42;
+
+/** Try to find PTE for faulting address
+ *
+ * @param as       Address space.
+ * @param badvaddr Faulting virtual address.
+ * @param access   Access mode that caused the fault.
+ * @param istate   Pointer to interrupted state.
+ * @param pfrc     Pointer to variable where as_page_fault() return code
+ *                 will be stored.
+ *
+ * @return PTE on success, NULL otherwise.
+ *
+ */
+static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access,
+    istate_t *istate, int *pfrc)
+{
+	/*
+	 * Check if the mapping exists in page tables.
+	 */
+	pte_t *pte = page_mapping_find(as, badvaddr, true);
+	if ((pte) && (pte->present)) {
+		/*
+		 * Mapping found in page tables.
+		 * Immediately succeed.
+		 */
+		return pte;
+	} else {
+		/*
+		 * Mapping not found in page tables.
+		 * Resort to higher-level page fault handler.
+		 */
+		int rc = as_page_fault(badvaddr, access, istate);
+		switch (rc) {
+		case AS_PF_OK:
+			/*
+			 * The higher-level page fault handler succeeded,
+			 * The mapping ought to be in place.
+			 */
+			pte = page_mapping_find(as, badvaddr, true);
+			ASSERT((pte) && (pte->present));
+			*pfrc = 0;
+			return pte;
+		case AS_PF_DEFER:
+			*pfrc = rc;
+			return NULL;
+		case AS_PF_FAULT:
+			*pfrc = rc;
+			return NULL;
+		default:
+			panic("Unexpected rc (%d).", rc);
+		}
+	}
+}
+
+static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
+{
+	fault_if_from_uspace(istate, "PHT Refill Exception on %p.",
+	    (void *) badvaddr);
+	panic_memtrap(istate, PF_ACCESS_UNKNOWN, badvaddr,
+	    "PHT Refill Exception.");
+}
+
+static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
+{
+	uint32_t page = (vaddr >> 12) & 0xffff;
+	uint32_t api = (vaddr >> 22) & 0x3f;
+	
+	uint32_t vsid = sr_get(vaddr);
+	uint32_t sdr1 = sdr1_get();
+	
+	// FIXME: compute size of PHT exactly
+	phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
+	
+	/* Primary hash (xor) */
+	uint32_t h = 0;
+	uint32_t hash = vsid ^ page;
+	uint32_t base = (hash & 0x3ff) << 3;
+	uint32_t i;
+	bool found = false;
+	
+	/* Find colliding PTE in PTEG */
+	for (i = 0; i < 8; i++) {
+		if ((phte[base + i].v)
+		    && (phte[base + i].vsid == vsid)
+		    && (phte[base + i].api == api)
+		    && (phte[base + i].h == 0)) {
+			found = true;
+			break;
+		}
+	}
+	
+	if (!found) {
+		/* Find unused PTE in PTEG */
+		for (i = 0; i < 8; i++) {
+			if (!phte[base + i].v) {
+				found = true;
+				break;
+			}
+		}
+	}
+	
+	if (!found) {
+		/* Secondary hash (not) */
+		uint32_t base2 = (~hash & 0x3ff) << 3;
+		
+		/* Find colliding PTE in PTEG */
+		for (i = 0; i < 8; i++) {
+			if ((phte[base2 + i].v)
+			    && (phte[base2 + i].vsid == vsid)
+			    && (phte[base2 + i].api == api)
+			    && (phte[base2 + i].h == 1)) {
+				found = true;
+				base = base2;
+				h = 1;
+				break;
+			}
+		}
+		
+		if (!found) {
+			/* Find unused PTE in PTEG */
+			for (i = 0; i < 8; i++) {
+				if (!phte[base2 + i].v) {
+					found = true;
+					base = base2;
+					h = 1;
+					break;
+				}
+			}
+		}
+		
+		if (!found)
+			i = RANDI(seed) % 8;
+	}
+	
+	phte[base + i].v = 1;
+	phte[base + i].vsid = vsid;
+	phte[base + i].h = h;
+	phte[base + i].api = api;
+	phte[base + i].rpn = pte->pfn;
+	phte[base + i].r = 0;
+	phte[base + i].c = 0;
+	phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0);
+	phte[base + i].pp = 2; // FIXME
+}
+
+/** Process Instruction/Data Storage Exception
+ *
+ * @param n      Exception vector number.
+ * @param istate Interrupted register context.
+ *
+ */
+void pht_refill(unsigned int n, istate_t *istate)
+{
+	uintptr_t badvaddr;
+	
+	if (n == VECTOR_DATA_STORAGE)
+		badvaddr = istate->dar;
+	else
+		badvaddr = istate->pc;
+	
+	int pfrc;
+	pte_t *pte = find_mapping_and_check(AS, badvaddr,
+	    PF_ACCESS_READ /* FIXME */, istate, &pfrc);
+	
+	if (!pte) {
+		switch (pfrc) {
+		case AS_PF_FAULT:
+			pht_refill_fail(badvaddr, istate);
+			return;
+		case AS_PF_DEFER:
+			/*
+			 * The page fault came during copy_from_uspace()
+			 * or copy_to_uspace().
+			 */
+			return;
+		default:
+			panic("Unexpected pfrc (%d).", pfrc);
+		}
+	}
+	
+	/* Record access to PTE */
+	pte->accessed = 1;
+	pht_insert(badvaddr, pte);
+}
+
+void pht_invalidate(as_t *as, uintptr_t page, size_t pages)
+{
+	uint32_t sdr1 = sdr1_get();
+	
+	// FIXME: compute size of PHT exactly
+	phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
+	
+	// FIXME: this invalidates all PHT entries,
+	// which is an overkill, invalidate only
+	// selectively
+	for (size_t i = 0; i < 8192; i++) {
+		phte[i].v = 0;
+	}
+}
+
+/** @}
+ */
Index: kernel/arch/ppc32/src/mm/tlb.c
===================================================================
--- kernel/arch/ppc32/src/mm/tlb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/src/mm/tlb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,337 +33,23 @@
  */
 
-#include <mm/tlb.h>
 #include <arch/mm/tlb.h>
-#include <arch/interrupt.h>
 #include <interrupt.h>
-#include <mm/as.h>
-#include <mm/page.h>
-#include <arch.h>
-#include <print.h>
-#include <macros.h>
-#include <symtab.h>
+#include <typedefs.h>
 
-static unsigned int seed = 10;
-static unsigned int seed_real
-    __attribute__ ((section("K_UNMAPPED_DATA_START"))) = 42;
-
-/** Try to find PTE for faulting address
- *
- * @param as       Address space.
- * @param lock     Lock/unlock the address space.
- * @param badvaddr Faulting virtual address.
- * @param access   Access mode that caused the fault.
- * @param istate   Pointer to interrupted state.
- * @param pfrc     Pointer to variable where as_page_fault() return code
- *                 will be stored.
- *
- * @return PTE on success, NULL otherwise.
- *
- */
-static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access,
-    istate_t *istate, int *pfrc)
+void tlb_refill(unsigned int n, istate_t *istate)
 {
-	ASSERT(mutex_locked(&as->lock));
-
-	/*
-	 * Check if the mapping exists in page tables.
-	 */
-	pte_t *pte = page_mapping_find(as, badvaddr);
-	if ((pte) && (pte->present)) {
-		/*
-		 * Mapping found in page tables.
-		 * Immediately succeed.
-		 */
-		return pte;
-	} else {
-		/*
-		 * Mapping not found in page tables.
-		 * Resort to higher-level page fault handler.
-		 */
-		page_table_unlock(as, true);
-		
-		int rc = as_page_fault(badvaddr, access, istate);
-		switch (rc) {
-		case AS_PF_OK:
-			/*
-			 * The higher-level page fault handler succeeded,
-			 * The mapping ought to be in place.
-			 */
-			page_table_lock(as, true);
-			pte = page_mapping_find(as, badvaddr);
-			ASSERT((pte) && (pte->present));
-			*pfrc = 0;
-			return pte;
-		case AS_PF_DEFER:
-			page_table_lock(as, true);
-			*pfrc = rc;
-			return NULL;
-		case AS_PF_FAULT:
-			page_table_lock(as, true);
-			*pfrc = rc;
-			return NULL;
-		default:
-			panic("Unexpected rc (%d).", rc);
-		}
-	}
-}
-
-static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate)
-{
-	fault_if_from_uspace(istate, "PHT Refill Exception on %p.",
-	    (void *) badvaddr);
-	panic_memtrap(istate, PF_ACCESS_UNKNOWN, badvaddr,
-	    "PHT Refill Exception.");
-}
-
-static void pht_insert(const uintptr_t vaddr, const pte_t *pte)
-{
-	uint32_t page = (vaddr >> 12) & 0xffff;
-	uint32_t api = (vaddr >> 22) & 0x3f;
+	uint32_t tlbmiss;
+	ptehi_t ptehi;
+	ptelo_t ptelo;
 	
-	uint32_t vsid = sr_get(vaddr);
-	uint32_t sdr1 = sdr1_get();
+	asm volatile (
+		"mfspr %[tlbmiss], 980\n"
+		"mfspr %[ptehi], 981\n"
+		"mfspr %[ptelo], 982\n"
+		: [tlbmiss] "=r" (tlbmiss),
+		  [ptehi] "=r" (ptehi),
+		  [ptelo] "=r" (ptelo)
+	);
 	
-	// FIXME: compute size of PHT exactly
-	phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
-	
-	/* Primary hash (xor) */
-	uint32_t h = 0;
-	uint32_t hash = vsid ^ page;
-	uint32_t base = (hash & 0x3ff) << 3;
-	uint32_t i;
-	bool found = false;
-	
-	/* Find colliding PTE in PTEG */
-	for (i = 0; i < 8; i++) {
-		if ((phte[base + i].v)
-		    && (phte[base + i].vsid == vsid)
-		    && (phte[base + i].api == api)
-		    && (phte[base + i].h == 0)) {
-			found = true;
-			break;
-		}
-	}
-	
-	if (!found) {
-		/* Find unused PTE in PTEG */
-		for (i = 0; i < 8; i++) {
-			if (!phte[base + i].v) {
-				found = true;
-				break;
-			}
-		}
-	}
-	
-	if (!found) {
-		/* Secondary hash (not) */
-		uint32_t base2 = (~hash & 0x3ff) << 3;
-		
-		/* Find colliding PTE in PTEG */
-		for (i = 0; i < 8; i++) {
-			if ((phte[base2 + i].v)
-			    && (phte[base2 + i].vsid == vsid)
-			    && (phte[base2 + i].api == api)
-			    && (phte[base2 + i].h == 1)) {
-				found = true;
-				base = base2;
-				h = 1;
-				break;
-			}
-		}
-		
-		if (!found) {
-			/* Find unused PTE in PTEG */
-			for (i = 0; i < 8; i++) {
-				if (!phte[base2 + i].v) {
-					found = true;
-					base = base2;
-					h = 1;
-					break;
-				}
-			}
-		}
-		
-		if (!found)
-			i = RANDI(seed) % 8;
-	}
-	
-	phte[base + i].v = 1;
-	phte[base + i].vsid = vsid;
-	phte[base + i].h = h;
-	phte[base + i].api = api;
-	phte[base + i].rpn = pte->pfn;
-	phte[base + i].r = 0;
-	phte[base + i].c = 0;
-	phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0);
-	phte[base + i].pp = 2; // FIXME
-}
-
-/** Process Instruction/Data Storage Exception
- *
- * @param n      Exception vector number.
- * @param istate Interrupted register context.
- *
- */
-void pht_refill(unsigned int n, istate_t *istate)
-{
-	as_t *as = (AS == NULL) ? AS_KERNEL : AS;
-	uintptr_t badvaddr;
-	
-	if (n == VECTOR_DATA_STORAGE)
-		badvaddr = istate->dar;
-	else
-		badvaddr = istate->pc;
-	
-	page_table_lock(as, true);
-	
-	int pfrc;
-	pte_t *pte = find_mapping_and_check(as, badvaddr,
-	    PF_ACCESS_READ /* FIXME */, istate, &pfrc);
-	
-	if (!pte) {
-		switch (pfrc) {
-		case AS_PF_FAULT:
-			goto fail;
-			break;
-		case AS_PF_DEFER:
-			/*
-			 * The page fault came during copy_from_uspace()
-			 * or copy_to_uspace().
-			 */
-			page_table_unlock(as, true);
-			return;
-		default:
-			panic("Unexpected pfrc (%d).", pfrc);
-		}
-	}
-	
-	/* Record access to PTE */
-	pte->accessed = 1;
-	pht_insert(badvaddr, pte);
-	
-	page_table_unlock(as, true);
-	return;
-	
-fail:
-	page_table_unlock(as, true);
-	pht_refill_fail(badvaddr, istate);
-}
-
-/** Process Instruction/Data Storage Exception in Real Mode
- *
- * @param n      Exception vector number.
- * @param istate Interrupted register context.
- *
- */
-bool pht_refill_real(unsigned int n, istate_t *istate)
-{
-	uintptr_t badvaddr;
-	
-	if (n == VECTOR_DATA_STORAGE)
-		badvaddr = istate->dar;
-	else
-		badvaddr = istate->pc;
-	
-	uint32_t physmem = physmem_top();
-	
-	if ((badvaddr < PA2KA(0)) || (badvaddr >= PA2KA(physmem)))
-		return false;
-	
-	uint32_t page = (badvaddr >> 12) & 0xffff;
-	uint32_t api = (badvaddr >> 22) & 0x3f;
-	
-	uint32_t vsid = sr_get(badvaddr);
-	uint32_t sdr1 = sdr1_get();
-	
-	// FIXME: compute size of PHT exactly
-	phte_t *phte_real = (phte_t *) (sdr1 & 0xffff0000);
-	
-	/* Primary hash (xor) */
-	uint32_t h = 0;
-	uint32_t hash = vsid ^ page;
-	uint32_t base = (hash & 0x3ff) << 3;
-	uint32_t i;
-	bool found = false;
-	
-	/* Find colliding PTE in PTEG */
-	for (i = 0; i < 8; i++) {
-		if ((phte_real[base + i].v)
-		    && (phte_real[base + i].vsid == vsid)
-		    && (phte_real[base + i].api == api)
-		    && (phte_real[base + i].h == 0)) {
-			found = true;
-			break;
-		}
-	}
-	
-	if (!found) {
-		/* Find unused PTE in PTEG */
-		for (i = 0; i < 8; i++) {
-			if (!phte_real[base + i].v) {
-				found = true;
-				break;
-			}
-		}
-	}
-	
-	if (!found) {
-		/* Secondary hash (not) */
-		uint32_t base2 = (~hash & 0x3ff) << 3;
-		
-		/* Find colliding PTE in PTEG */
-		for (i = 0; i < 8; i++) {
-			if ((phte_real[base2 + i].v)
-			    && (phte_real[base2 + i].vsid == vsid)
-			    && (phte_real[base2 + i].api == api)
-			    && (phte_real[base2 + i].h == 1)) {
-				found = true;
-				base = base2;
-				h = 1;
-				break;
-			}
-		}
-		
-		if (!found) {
-			/* Find unused PTE in PTEG */
-			for (i = 0; i < 8; i++) {
-				if (!phte_real[base2 + i].v) {
-					found = true;
-					base = base2;
-					h = 1;
-					break;
-				}
-			}
-		}
-		
-		if (!found) {
-			/* Use secondary hash to avoid collisions
-			   with usual PHT refill handler. */
-			i = RANDI(seed_real) % 8;
-			base = base2;
-			h = 1;
-		}
-	}
-	
-	phte_real[base + i].v = 1;
-	phte_real[base + i].vsid = vsid;
-	phte_real[base + i].h = h;
-	phte_real[base + i].api = api;
-	phte_real[base + i].rpn = KA2PA(badvaddr) >> 12;
-	phte_real[base + i].r = 0;
-	phte_real[base + i].c = 0;
-	phte_real[base + i].wimg = 0;
-	phte_real[base + i].pp = 2; // FIXME
-	
-	return true;
-}
-
-/** Process ITLB/DTLB Miss Exception in Real Mode
- *
- *
- */
-void tlb_refill_real(unsigned int n, uint32_t tlbmiss, ptehi_t ptehi,
-    ptelo_t ptelo, istate_t *istate)
-{
 	uint32_t badvaddr = tlbmiss & 0xfffffffc;
 	uint32_t physmem = physmem_top();
@@ -395,19 +81,19 @@
 void tlb_invalidate_all(void)
 {
-	uint32_t index;
+	asm volatile (
+		"sync\n"
+	);
+	
+	for (unsigned int i = 0; i < 0x00040000; i += 0x00001000) {
+		asm volatile (
+			"tlbie %[i]\n"
+			:: [i] "r" (i)
+		);
+	}
 	
 	asm volatile (
-		"li %[index], 0\n"
-		"sync\n"
-		
-		".rept 64\n"
-		"	tlbie %[index]\n"
-		"	addi %[index], %[index], 0x1000\n"
-		".endr\n"
-		
 		"eieio\n"
 		"tlbsync\n"
 		"sync\n"
-		: [index] "=r" (index)
 	);
 }
@@ -415,16 +101,4 @@
 void tlb_invalidate_asid(asid_t asid)
 {
-	uint32_t sdr1 = sdr1_get();
-	
-	// FIXME: compute size of PHT exactly
-	phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
-	
-	size_t i;
-	for (i = 0; i < 8192; i++) {
-		if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&
-		    (phte[i].vsid < ((asid << 4) + 16)))
-			phte[i].v = 0;
-	}
-	
 	tlb_invalidate_all();
 }
@@ -432,5 +106,4 @@
 void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
 {
-	// TODO
 	tlb_invalidate_all();
 }
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/src/ppc32.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,10 +41,10 @@
 #include <interrupt.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <genarch/ofw/ofw_tree.h>
 #include <genarch/ofw/pci.h>
 #include <userspace.h>
 #include <mm/page.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <console/console.h>
 #include <sysinfo/sysinfo.h>
@@ -265,6 +265,5 @@
 {
 	userspace_asm((uintptr_t) kernel_uarg->uspace_uarg,
-	    (uintptr_t) kernel_uarg->uspace_stack +
-	    THREAD_STACK_SIZE - SP_DELTA,
+	    (uintptr_t) kernel_uarg->uspace_stack + STACK_SIZE - SP_DELTA,
 	    (uintptr_t) kernel_uarg->uspace_entry);
 	
Index: kernel/arch/ppc32/src/proc/scheduler.c
===================================================================
--- kernel/arch/ppc32/src/proc/scheduler.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/ppc32/src/proc/scheduler.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -55,5 +55,5 @@
 	asm volatile (
 		"mtsprg0 %[ksp]\n"
-		:: [ksp] "r" (KA2PA(&THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA]))
+		:: [ksp] "r" (KA2PA(&THREAD->kstack[STACK_SIZE - SP_DELTA]))
 	);
 }
Index: kernel/arch/sparc64/Makefile.inc
===================================================================
--- kernel/arch/sparc64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -31,5 +31,5 @@
 BFD = binary
 
-GCC_CFLAGS += -m64 -mcpu=ultrasparc -mcmodel=medlow
+GCC_CFLAGS += -m64 -mcpu=ultrasparc -mcmodel=medlow -mno-fpu
 SUNCC_CFLAGS += -m64 -xarch=sparc -xregs=appl,no%float
 
@@ -84,7 +84,5 @@
 	arch/$(KARCH)/src/drivers/tick.c \
 	arch/$(KARCH)/src/drivers/kbd.c \
-	arch/$(KARCH)/src/drivers/sgcn.c \
 	arch/$(KARCH)/src/drivers/pci.c \
-	arch/$(KARCH)/src/drivers/fhc.c \
 	arch/$(KARCH)/src/trap/$(USARCH)/interrupt.c
 
Index: kernel/arch/sparc64/_link.ld.in
===================================================================
--- kernel/arch/sparc64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -15,11 +15,10 @@
 		ktext_start = .;
 		*(K_TEXT_START)
-		*(.text);
+		*(.text .text.*);
 		ktext_end = .;
 		
 		kdata_start = .;
 		*(K_DATA_START)
-		*(.rodata);
-		*(.rodata.*);
+		*(.rodata .rodata.*);
 		*(.data);                   /* initialized data */
 		*(.sdata);
Index: kernel/arch/sparc64/include/barrier.h
===================================================================
--- kernel/arch/sparc64/include/barrier.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,14 +37,4 @@
 
 #include <trace.h>
-
-#ifdef KERNEL
-
-#include <typedefs.h>
-
-#else
-
-#include <stdint.h>
-
-#endif
 
 /*
Index: kernel/arch/sparc64/include/cpu.h
===================================================================
--- kernel/arch/sparc64/include/cpu.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/cpu.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -59,9 +59,4 @@
 #include <arch/asm.h>
 
-#ifdef CONFIG_SMP
-#include <arch/mm/cache.h>
-#endif
-
-
 #if defined (SUN4U)
 #include <arch/sun4u/cpu.h>
Index: rnel/arch/sparc64/include/drivers/fhc.h
===================================================================
--- kernel/arch/sparc64/include/drivers/fhc.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2006 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 sparc64
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_sparc64_FHC_H_
-#define KERN_sparc64_FHC_H_
-
-#include <typedefs.h>
-#include <genarch/ofw/ofw_tree.h>
-
-typedef struct {
-	volatile uint32_t *uart_imap;
-} fhc_t;
-
-extern fhc_t *central_fhc;
-
-extern fhc_t *fhc_init(ofw_tree_node_t *);
-extern void fhc_enable_interrupt(fhc_t *, int);
-extern void fhc_clear_interrupt(void *, int);
-
-#endif
-
-/** @}
- */
Index: rnel/arch/sparc64/include/drivers/sgcn.h
===================================================================
--- kernel/arch/sparc64/include/drivers/sgcn.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,151 +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.
- */
-
-/** @addtogroup sparc64	
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_sparc64_SGCN_H_
-#define KERN_sparc64_SGCN_H_
-
-#include <typedefs.h>
-#include <console/chardev.h>
-#include <proc/thread.h>
-#include <synch/spinlock.h>
-
-/* number of bytes in the TOC magic, including the NULL-terminator */
-#define TOC_MAGIC_BYTES  8
-
-/* number of bytes in the TOC key, including the NULL-terminator */
-#define TOC_KEY_SIZE  8
-
-/* maximum number of entries in the SRAM table of contents */
-#define MAX_TOC_ENTRIES  32
-
-/* number of bytes in the SGCN buffer magic, including the NULL-terminator */
-#define SGCN_MAGIC_BYTES  4
-
-/**
- * Entry in the SRAM table of contents. Describes one segment of the SRAM
- * which serves a particular purpose (e.g. OBP serial console, Solaris serial
- * console, Solaris mailbox,...).
- */
-typedef struct {
-	/** key (e.g. "OBPCONS", "SOLCONS", "SOLMBOX",...) */
-	char key[TOC_KEY_SIZE];
-	
-	/** size of the segment in bytes */
-	uint32_t size;
-	
-	/** offset of the segment within SRAM */
-	uint32_t offset;
-} __attribute ((packed)) toc_entry_t;
-
-/**
- * SRAM table of contents. Describes all segments within the SRAM.
- */
-typedef struct {
-	/** hard-wired to "TOCSRAM" */
-	char magic[TOC_MAGIC_BYTES];
-	
-	/** we don't need this */
-	char unused[8];
-	
-	/** TOC entries */
-	toc_entry_t keys[MAX_TOC_ENTRIES];
-} __attribute__ ((packed)) iosram_toc_t;
-
-/**
- * SGCN buffer header. It is placed at the very beginning of the SGCN
- * buffer.
- */
-typedef struct {
-	/** hard-wired to "CON" */
-	char magic[SGCN_MAGIC_BYTES];
-	
-	/** we don't need this */
-	char unused[8];
-	
-	/** offset within the SGCN buffer of the input buffer start */
-	uint32_t in_begin;
-	
-	/** offset within the SGCN buffer of the input buffer end */
-	uint32_t in_end;
-	
-	/** offset within the SGCN buffer of the input buffer read pointer */
-	uint32_t in_rdptr;
-	
-	/** offset within the SGCN buffer of the input buffer write pointer */
-	uint32_t in_wrptr;
-	
-	/** offset within the SGCN buffer of the output buffer start */
-	uint32_t out_begin;
-	
-	/** offset within the SGCN buffer of the output buffer end */
-	uint32_t out_end;
-	
-	/** offset within the SGCN buffer of the output buffer read pointer */
-	uint32_t out_rdptr;
-	
-	/** offset within the SGCN buffer of the output buffer write pointer */
-	uint32_t out_wrptr;
-} __attribute__ ((packed)) sgcn_buffer_header_t;
-
-typedef struct {
-	/** Starting address of SRAM */
-	uintptr_t sram_begin;
-	
-	/** Starting address of the SGCN buffer */
-	uintptr_t buffer_begin;
-	
-	/**
-	 * Ensure that writing to the buffer and consequent
-	 * update of the write pointer are one atomic operation.
-	 */
-	SPINLOCK_DECLARE(output_lock);
-	
-	/**
-	 * Prevent the input buffer read/write pointers from
-	 * getting to inconsistent state.
-	 */
-	SPINLOCK_DECLARE(input_lock);
-	
-	thread_t *thread;
-	indev_t *srlnin;
-} sgcn_instance_t;
-
-extern sgcn_instance_t *sgcnin_init(void);
-extern void sgcnin_wire(sgcn_instance_t *, indev_t *);
-extern outdev_t *sgcnout_init(void);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/sparc64/include/elf.h
===================================================================
--- kernel/arch/sparc64/include/elf.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup sparc64	
+/** @addtogroup sparc64
  * @{
  */
@@ -36,7 +36,7 @@
 #define KERN_sparc64_ELF_H_
 
-#define	ELF_MACHINE		EM_SPARCV9
-#define ELF_DATA_ENCODING	ELFDATA2MSB
-#define ELF_CLASS		ELFCLASS64
+#define ELF_MACHINE        EM_SPARCV9
+#define ELF_DATA_ENCODING  ELFDATA2MSB
+#define ELF_CLASS          ELFCLASS64
 
 #endif
Index: kernel/arch/sparc64/include/istate.h
===================================================================
--- kernel/arch/sparc64/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,13 +37,15 @@
 #define KERN_sparc64_ISTATE_H_
 
+#include <trace.h>
+
+#ifdef KERNEL
+
 #include <arch/regdef.h>
 
-#ifdef KERNEL
-#include <typedefs.h>
-#include <trace.h>
-#else
-#include <sys/types.h>
-#define NO_TRACE
-#endif
+#else /* KERNEL */
+
+#include <libarch/regdef.h>
+
+#endif /* KERNEL */
 
 typedef struct istate {
Index: rnel/arch/sparc64/include/memstr.h
===================================================================
--- kernel/arch/sparc64/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2005 Sergey Bondari
- * 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
- */
-
-#ifndef KERN_sparc64_MEMSTR_H_
-#define KERN_sparc64_MEMSTR_H_
-
-#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
-
-extern void memsetw(void *, size_t, uint16_t);
-extern void memsetb(void *, size_t, uint8_t);
-
-#endif
-
-/** @}
- */
Index: rnel/arch/sparc64/include/mm/cache.h
===================================================================
--- kernel/arch/sparc64/include/mm/cache.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- * Copyright (c) 2006 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 sparc64mm	
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_sparc64_CACHE_H_
-#define KERN_sparc64_CACHE_H_
-
-#include <mm/page.h>
-#include <mm/frame.h>
-
-#endif
-
-/** @}
- */
Index: kernel/arch/sparc64/include/mm/page.h
===================================================================
--- kernel/arch/sparc64/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -54,6 +54,4 @@
 #define MMU_PAGES_PER_PAGE	(1 << (PAGE_WIDTH - MMU_PAGE_WIDTH))
 
-#ifdef KERNEL
-
 #ifndef __ASM__
 
@@ -77,6 +75,4 @@
 #endif /* !def __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/sparc64/include/mm/sun4u/as.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4u/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/mm/sun4u/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup sparc64mm	
+/** @addtogroup sparc64mm
  * @{
  */
@@ -38,12 +38,10 @@
 #include <arch/mm/tte.h>
 
-#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH	1
+#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  1
 
-#define KERNEL_ADDRESS_SPACE_START_ARCH		(unsigned long) 0x0000000000000000
-#define KERNEL_ADDRESS_SPACE_END_ARCH		(unsigned long) 0xffffffffffffffff
-#define USER_ADDRESS_SPACE_START_ARCH		(unsigned long) 0x0000000000000000
-#define USER_ADDRESS_SPACE_END_ARCH		(unsigned long) 0xffffffffffffffff
-
-#define USTACK_ADDRESS_ARCH	(0xffffffffffffffffULL - (PAGE_SIZE - 1))
+#define KERNEL_ADDRESS_SPACE_START_ARCH  UINT64_C(0x0000000000000000)
+#define KERNEL_ADDRESS_SPACE_END_ARCH    UINT64_C(0xffffffffffffffff)
+#define USER_ADDRESS_SPACE_START_ARCH    UINT64_C(0x0000000000000000)
+#define USER_ADDRESS_SPACE_END_ARCH      UINT64_C(0xffffffffffffffff)
 
 #ifdef CONFIG_TSB
Index: kernel/arch/sparc64/include/mm/sun4u/frame.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4u/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/mm/sun4u/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,5 +52,4 @@
 #define FRAME_SIZE		(1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -80,5 +79,4 @@
 
 #endif
-#endif
 
 #endif
Index: kernel/arch/sparc64/include/mm/sun4v/as.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/mm/sun4v/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,12 +40,10 @@
 #include <arch/mm/tsb.h>
 
-#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH	1
+#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  1
 
-#define KERNEL_ADDRESS_SPACE_START_ARCH		(unsigned long) 0x0000000000000000
-#define KERNEL_ADDRESS_SPACE_END_ARCH		(unsigned long) 0xffffffffffffffff
-#define USER_ADDRESS_SPACE_START_ARCH		(unsigned long) 0x0000000000000000
-#define USER_ADDRESS_SPACE_END_ARCH		(unsigned long) 0xffffffffffffffff
-
-#define USTACK_ADDRESS_ARCH	(0xffffffffffffffffULL - (PAGE_SIZE - 1))
+#define KERNEL_ADDRESS_SPACE_START_ARCH  UINT64_C(0x0000000000000000)
+#define KERNEL_ADDRESS_SPACE_END_ARCH    UINT64_C(0xffffffffffffffff)
+#define USER_ADDRESS_SPACE_START_ARCH    UINT64_C(0x0000000000000000)
+#define USER_ADDRESS_SPACE_END_ARCH      UINT64_C(0xffffffffffffffff)
 
 #ifdef CONFIG_TSB
Index: kernel/arch/sparc64/include/mm/sun4v/frame.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/mm/sun4v/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,5 +42,4 @@
 #define FRAME_SIZE		(1 << FRAME_WIDTH)
 
-#ifdef KERNEL
 #ifndef __ASM__
 
@@ -52,5 +51,4 @@
 
 #endif
-#endif
 
 #endif
Index: kernel/arch/sparc64/include/mm/sun4v/page.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/mm/sun4v/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -46,6 +46,4 @@
 #define MMU_PAGES_PER_PAGE	(1 << (PAGE_WIDTH - MMU_PAGE_WIDTH))
 
-#ifdef KERNEL
-
 #ifndef __ASM__
 
@@ -69,6 +67,4 @@
 #endif /* !def __ASM__ */
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/arch/sparc64/include/sun4u/cpu.h
===================================================================
--- kernel/arch/sparc64/include/sun4u/cpu.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/sun4u/cpu.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -60,8 +60,4 @@
 #include <trace.h>
 
-#ifdef CONFIG_SMP
-#include <arch/mm/cache.h>
-#endif
-
 typedef struct {
 	uint32_t mid;              /**< Processor ID as read from
Index: kernel/arch/sparc64/include/sun4v/regdef.h
===================================================================
--- kernel/arch/sparc64/include/sun4v/regdef.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/sun4v/regdef.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -28,5 +28,5 @@
  */
 
-/** @addtogroup sparc64	
+/** @addtogroup sparc64
  * @{
  */
@@ -37,17 +37,8 @@
 #define KERN_sparc64_sun4v_REGDEF_H_
 
-#define PSTATE_IE_BIT	(1 << 1)
-#define PSTATE_PRIV_BIT	(1 << 2)
-#define PSTATE_PEF_BIT	(1 << 4)
+#define TSTATE_CWP_MASK  0x1f
 
-#define TSTATE_PSTATE_SHIFT	8
-#define TSTATE_PRIV_BIT		(PSTATE_PRIV_BIT << TSTATE_PSTATE_SHIFT)
-#define TSTATE_CWP_MASK		0x1f
-#define TSTATE_IE_BIT		(PSTATE_IE_BIT << TSTATE_PSTATE_SHIFT)
-
-#define WSTATE_NORMAL(n)	(n)
-#define WSTATE_OTHER(n)		((n) << 3)
-
-#define TSTATE_PEF_BIT		(PSTATE_PEF_BIT << TSTATE_PSTATE_SHIFT)
+#define WSTATE_NORMAL(n)  (n)
+#define WSTATE_OTHER(n)   ((n) << 3)
 
 #endif
Index: kernel/arch/sparc64/include/types.h
===================================================================
--- kernel/arch/sparc64/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
 
 typedef uint64_t size_t;
+typedef int64_t ssize_t;
 
 typedef uint64_t uintptr_t;
Index: kernel/arch/sparc64/src/asm.S
===================================================================
--- kernel/arch/sparc64/src/asm.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,78 +34,4 @@
 .register %g2, #scratch
 .register %g3, #scratch
-
-/*
- * This is the assembly language version of our _memcpy() generated by gcc.
- */
-.global memcpy
-memcpy:
-	mov %o0, %o3  /* save dst */
-	add %o1, 7, %g1
-	and %g1, -8, %g1
-	cmp %o1, %g1
-	be,pn %xcc, 3f
-	add %o0, 7, %g1
-	mov 0, %g3
-	
-	0:
-	
-		brz,pn %o2, 2f
-		mov 0, %g2
-	
-	1:
-	
-		ldub [%g3 + %o1], %g1
-		add %g2, 1, %g2
-		cmp %o2, %g2
-		stb %g1, [%g3 + %o0]
-		bne,pt %xcc, 1b
-		mov %g2, %g3
-	
-	2:
-	
-		jmp %o7 + 8  /* exit point */
-		mov %o3, %o0
-	
-	3:
-	
-		and %g1, -8, %g1
-		cmp %o0, %g1
-		bne,pt %xcc, 0b
-		mov 0, %g3
-		srlx %o2, 3, %g4
-		brz,pn %g4, 5f
-		mov 0, %g5
-	
-	4:
-	
-		sllx %g3, 3, %g2
-		add %g5, 1, %g3
-		ldx [%o1 + %g2], %g1
-		mov %g3, %g5
-		cmp %g4, %g3
-		bne,pt %xcc, 4b
-		stx %g1, [%o0 + %g2]
-	
-	5:
-	
-		and %o2, 7, %o2
-		brz,pn %o2, 2b
-		sllx %g4, 3, %g1
-		mov 0, %g2
-		add %g1, %o0, %o0
-		add %g1, %o1, %g4
-		mov 0, %g3
-	
-	6:
-	
-		ldub [%g2 + %g4], %g1
-		stb %g1, [%g2 + %o0]
-		add %g3, 1, %g2
-		cmp %o2, %g2
-		bne,pt %xcc, 6b
-		mov %g2, %g3
-		
-		jmp %o7 + 8  /* exit point */
-		mov %o3, %o0
 
 /*
@@ -264,14 +190,4 @@
 	mov %g0, %o0  /* return 0 on failure */
 
-.global memsetb
-memsetb:
-	ba %xcc, _memsetb
-	nop
-
-.global memsetw
-memsetw:
-	ba %xcc, _memsetw
-	nop
-
 .global early_putchar
 early_putchar:
Index: kernel/arch/sparc64/src/console.c
===================================================================
--- kernel/arch/sparc64/src/console.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/console.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,4 @@
 #include <arch/drivers/scr.h>
 #include <arch/drivers/kbd.h>
-#include <arch/drivers/sgcn.h>
 #include <genarch/srln/srln.h>
 #include <console/chardev.h>
@@ -89,26 +88,4 @@
 }
 
-/** Initilize I/O on the Serengeti machine. */
-static void serengeti_init(void)
-{
-#ifdef CONFIG_SGCN_KBD
-	sgcn_instance_t *sgcn_instance = sgcnin_init();
-	if (sgcn_instance) {
-		srln_instance_t *srln_instance = srln_init();
-		if (srln_instance) {
-			indev_t *sink = stdin_wire();
-			indev_t *srln = srln_wire(srln_instance, sink);
-			sgcnin_wire(sgcn_instance, srln);
-		}
-	}
-#endif
-	
-#ifdef CONFIG_SGCN_PRN
-	outdev_t *sgcndev = sgcnout_init();
-	if (sgcndev)
-		stdout_wire(sgcndev);
-#endif
-}
-
 /**
  * Initialize input/output. Auto-detects the type of machine
@@ -127,9 +104,6 @@
 	prop = ofw_tree_getprop(aliases, "def-cn");
 	
-	if ((!prop) || (!prop->value) || (str_cmp(prop->value, "/sgcn") != 0)) {
+	if ((!prop) || (!prop->value))
 		standard_console_init(aliases);
-	} else {
-		serengeti_init();
-	}
 }
 
Index: rnel/arch/sparc64/src/drivers/fhc.c
===================================================================
--- kernel/arch/sparc64/src/drivers/fhc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,129 +1,0 @@
-/*
- * Copyright (c) 2006 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 sparc64
- * @{
- */
-/**
- * @file
- * @brief	FireHose Controller (FHC) driver.
- *
- * Note that this driver is a result of reverse engineering
- * rather than implementation of a specification. This
- * is due to the fact that the FHC documentation is not
- * publicly available.
- */
-
-#include <arch/drivers/fhc.h>
-#include <arch/trap/interrupt.h>
-#include <mm/page.h>
-#include <mm/slab.h>
-#include <typedefs.h>
-#include <genarch/ofw/ofw_tree.h>
-#include <genarch/ofw/fhc.h>
-#include <sysinfo/sysinfo.h>
-
-fhc_t *central_fhc = NULL;
-
-/**
- * I suspect this must be hardcoded in the FHC.
- * If it is not, than we can read all IMAP registers
- * and get the complete mapping.
- */
-#define FHC_UART_INR	0x39	
-
-#define FHC_UART_IMAP	0x0
-#define FHC_UART_ICLR	0x4
-
-#define UART_IMAP_REG	4
-
-fhc_t *fhc_init(ofw_tree_node_t *node)
-{
-	fhc_t *fhc;
-	ofw_tree_property_t *prop;
-
-	prop = ofw_tree_getprop(node, "reg");
-	
-	if (!prop || !prop->value)
-		return NULL;
-		
-	size_t regs = prop->size / sizeof(ofw_central_reg_t);
-	if (regs + 1 < UART_IMAP_REG)
-		return NULL;
-
-	ofw_central_reg_t *reg = &((ofw_central_reg_t *) prop->value)[UART_IMAP_REG];
-
-	uintptr_t paddr;
-	if (!ofw_central_apply_ranges(node->parent, reg, &paddr))
-		return NULL;
-
-	fhc = (fhc_t *) malloc(sizeof(fhc_t), FRAME_ATOMIC);
-	if (!fhc)
-		return NULL;
-
-	fhc->uart_imap = (uint32_t *) hw_map(paddr, reg->size);
-	
-	/*
-	 * Set sysinfo data needed by the uspace FHC driver.
-	 */
-	sysinfo_set_item_val("fhc.uart.size", NULL, reg->size);
-	sysinfo_set_item_val("fhc.uart.physical", NULL, paddr);
-	sysinfo_set_item_val("kbd.cir.fhc", NULL, 1);
-
-	return fhc;
-}
-
-void fhc_enable_interrupt(fhc_t *fhc, int inr)
-{
-	switch (inr) {
-	case FHC_UART_INR:
-		fhc->uart_imap[FHC_UART_IMAP] |= IMAP_V_MASK;
-		break;
-	default:
-		panic("Unexpected INR (%d).", inr);
-		break;
-	}
-}
-
-void fhc_clear_interrupt(void *fhcp, int inr)
-{
-	fhc_t *fhc = (fhc_t *)fhcp;
-	ASSERT(fhc->uart_imap);
-
-	switch (inr) {
-	case FHC_UART_INR:
-		fhc->uart_imap[FHC_UART_ICLR] = 0;
-		break;
-	default:
-		panic("Unexpected INR (%d).", inr);
-		break;
-	}
-}
-
-/** @}
- */
Index: kernel/arch/sparc64/src/drivers/kbd.c
===================================================================
--- kernel/arch/sparc64/src/drivers/kbd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,4 @@
 #include <arch/drivers/kbd.h>
 #include <genarch/ofw/ofw_tree.h>
-#include <genarch/ofw/fhc.h>
 #include <genarch/ofw/ebus.h>
 #include <console/console.h>
@@ -51,8 +50,4 @@
 #endif
 
-#ifdef CONFIG_Z8530
-#include <genarch/drivers/z8530/z8530.h>
-#endif
-
 #ifdef CONFIG_NS16550
 #include <genarch/drivers/ns16550/ns16550.h>
@@ -60,90 +55,4 @@
 
 #ifdef CONFIG_SUN_KBD
-
-#ifdef CONFIG_Z8530
-
-static bool kbd_z8530_init(ofw_tree_node_t *node)
-{
-	const char *name = ofw_tree_node_name(node);
-	
-	if (str_cmp(name, "zs") != 0)
-		return false;
-	
-	/*
-	 * Read 'interrupts' property.
-	 */
-	ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
-	if ((!prop) || (!prop->value)) {
-		printf("z8530: Unable to find interrupts property\n");
-		return false;
-	}
-	
-	uint32_t interrupts = *((uint32_t *) prop->value);
-	
-	/*
-	 * Read 'reg' property.
-	 */
-	prop = ofw_tree_getprop(node, "reg");
-	if ((!prop) || (!prop->value)) {
-		printf("z8530: Unable to find reg property\n");
-		return false;
-	}
-	
-	size_t size = ((ofw_fhc_reg_t *) prop->value)->size;
-	
-	uintptr_t pa;
-	if (!ofw_fhc_apply_ranges(node->parent,
-	    ((ofw_fhc_reg_t *) prop->value), &pa)) {
-		printf("z8530: Failed to determine address\n");
-		return false;
-	}
-	
-	inr_t inr;
-	cir_t cir;
-	void *cir_arg;
-	if (!ofw_fhc_map_interrupt(node->parent,
-	    ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
-	    &cir_arg)) {
-		printf("z8530: Failed to determine interrupt\n");
-		return false;
-	}
-	
-	/*
-	 * We need to pass aligned address to hw_map().
-	 * However, the physical keyboard address can
-	 * be pretty much unaligned, depending on the
-	 * underlying controller.
-	 */
-	uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
-	size_t offset = pa - aligned_addr;
-	
-	z8530_t *z8530 = (z8530_t *)
-	    (hw_map(aligned_addr, offset + size) + offset);
-	
-	z8530_instance_t *z8530_instance = z8530_init(z8530, inr, cir, cir_arg);
-	if (z8530_instance) {
-		kbrd_instance_t *kbrd_instance = kbrd_init();
-		if (kbrd_instance) {
-			indev_t *sink = stdin_wire();
-			indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
-			z8530_wire(z8530_instance, kbrd);
-		}
-	}
-	
-	/*
-	 * This is the necessary evil until the userspace drivers are
-	 * entirely self-sufficient.
-	 */
-	sysinfo_set_item_val("kbd", NULL, true);
-	sysinfo_set_item_val("kbd.inr", NULL, inr);
-	sysinfo_set_item_val("kbd.address.kernel", NULL,
-	    (uintptr_t) z8530);
-	sysinfo_set_item_val("kbd.address.physical", NULL, pa);
-	sysinfo_set_item_val("kbd.type.z8530", NULL, true);
-	
-	return true;
-}
-
-#endif /* CONFIG_Z8530 */
 
 #ifdef CONFIG_NS16550
@@ -243,8 +152,4 @@
 void kbd_init(ofw_tree_node_t *node)
 {
-#ifdef CONFIG_Z8530
-	kbd_z8530_init(node);
-#endif
-	
 #ifdef CONFIG_NS16550
 	kbd_ns16550_init(node);
Index: kernel/arch/sparc64/src/drivers/niagara.c
===================================================================
--- kernel/arch/sparc64/src/drivers/niagara.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/drivers/niagara.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,5 +32,5 @@
 /**
  * @file
- * @brief	Niagara input/output driver based on hypervisor calls.
+ * @brief Niagara input/output driver based on hypervisor calls.
  */
 
@@ -52,13 +52,13 @@
 #include <genarch/srln/srln.h>
 
-/* polling interval in miliseconds */
+/* Polling interval in miliseconds */
 #define POLL_INTERVAL  10000
 
-/* device instance */
+/* Device instance */
 static niagara_instance_t *instance = NULL;
 
-static void niagara_putchar(outdev_t *, const wchar_t, bool);
-
-/** character device operations */
+static void niagara_putchar(outdev_t *, const wchar_t);
+
+/** Character device operations */
 static outdev_operations_t niagara_ops = {
 	.write = niagara_putchar,
@@ -66,103 +66,115 @@
 };
 
-/*
+/**
  * The driver uses hypercalls to print characters to the console. Since the
  * hypercall cannot be performed from the userspace, we do this:
- * The kernel "little brother" driver (which will be present no matter what the
- * DDI architecture is - as we need the kernel part for the kconsole)
+ *
+ * The kernel "little brother" driver (which will be present no matter what
+ * the DDI architecture is -- as we need the kernel part for the kconsole)
  * defines a shared buffer. Kernel walks through the buffer (in the same thread
  * which is used for polling the keyboard) and prints any pending characters
- * to the console (using hypercalls). The userspace fb server maps this shared
- * buffer to its address space and output operation it does is performed using
- * the mapped buffer. The shared buffer definition follows.
- */
-#define OUTPUT_BUFFER_SIZE	((PAGE_SIZE) - 2 * 8)
+ * to the console (using hypercalls).
+ *
+ * The userspace fb server maps this shared buffer to its address space and
+ * output operation it does is performed using the mapped buffer. The shared
+ * 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;
+} __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) output_buffer;
+
+static parea_t outbuf_parea;
 
 /**
  * Analogous to the output_buffer, see the previous definition.
  */
-#define INPUT_BUFFER_SIZE	((PAGE_SIZE) - 2 * 8)
+#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;
-
-
-/** Writes a single character to the standard output. */
+} __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) input_buffer;
+
+static parea_t inbuf_parea;
+
+/** Write a single character to the standard output. */
 static inline void do_putchar(const char c) {
-	/* repeat until the buffer is non-full */
-	while (__hypercall_fast1(CONS_PUTCHAR, c) == HV_EWOULDBLOCK)
-		;
-}
-
-/** Writes a single character to the standard output. */
-static void niagara_putchar(outdev_t *dev, const wchar_t ch, bool silent)
-{
-        if (silent)
-            return;
-
-	do_putchar(ch);
-	if (ch == '\n')
-		do_putchar('\r');
-}
-
-/**
- * Function regularly called by the keyboard polling thread. Asks the
- * hypervisor whether there is any unread character. If so, it picks it up
- * and sends it to the upper layers of HelenOS.
- *
- * Apart from that, it also checks whether the userspace output driver has
- * pushed any characters to the output buffer. If so, it prints them.
- */
-static void niagara_poll(niagara_instance_t *instance)
-{
-	/* print any pending characters from the shared buffer to the console */
+	/* Repeat until the buffer is non-full */
+	while (__hypercall_fast1(CONS_PUTCHAR, c) == HV_EWOULDBLOCK);
+}
+
+/** Write a single character to the standard output. */
+static void niagara_putchar(outdev_t *dev, const wchar_t ch)
+{
+	if ((!outbuf_parea.mapped) || (console_override)) {
+		do_putchar(ch);
+		if (ch == '\n')
+			do_putchar('\r');
+	}
+}
+
+/** Poll keyboard and print pending characters.
+ *
+ * Ask the hypervisor whether there is any unread character. If so,
+ * pick it up and send it to the indev layer.
+ *
+ * Check whether the userspace output driver has pushed any
+ * characters to the output buffer and eventually print them.
+ *
+ */
+static void niagara_poll(void)
+{
+	/*
+	 * Print any pending characters from the
+	 * shared buffer to the console.
+	 */
+	
 	while (output_buffer.read_ptr != output_buffer.write_ptr) {
 		do_putchar(output_buffer.data[output_buffer.read_ptr]);
 		output_buffer.read_ptr =
-			((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE;
-	}
-
+		    ((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE;
+	}
+	
+	/*
+	 * Read character from keyboard.
+	 */
+	
 	uint64_t c;
-
-	/* read character from keyboard, send it to upper layers of HelenOS */
 	if (__hypercall_fast_ret1(0, 0, 0, 0, 0, CONS_GETCHAR, &c) == HV_EOK) {
-		if (!silent) {
-			/* kconsole active, send the character to kernel */
+		if ((!inbuf_parea.mapped) || (console_override)) {
+			/*
+			 * Kernel console is active, send
+			 * the character to kernel.
+			 */
 			indev_push_character(instance->srlnin, c);
 		} else {
-			/* kconsole inactive, send the character to uspace driver */
+			/*
+			 * Kernel console is inactive, send
+			 * the character to uspace driver.
+			 */
 			input_buffer.data[input_buffer.write_ptr] = (char) c;
 			input_buffer.write_ptr =
-				((input_buffer.write_ptr) + 1) % INPUT_BUFFER_SIZE;
+			    ((input_buffer.write_ptr) + 1) % INPUT_BUFFER_SIZE;
 		}
 	}
 }
 
-/**
- * Polling thread function.
- */
-static void kniagarapoll(void *instance) {
+/** Polling thread function.
+ *
+ */
+static void kniagarapoll(void *arg) {
 	while (true) {
-		niagara_poll(instance);
+		niagara_poll();
 		thread_usleep(POLL_INTERVAL);
 	}
 }
 
-/**
- * Initializes the input/output subsystem so that the Niagara standard
- * input/output is used.
+/** Initialize the input/output subsystem
+ *
  */
 static void niagara_init(void)
@@ -172,57 +184,54 @@
 	
 	instance = malloc(sizeof(niagara_instance_t), FRAME_ATOMIC);
-	
-	if (instance) {
-		instance->thread = thread_create(kniagarapoll, instance, TASK, 0,
-			"kniagarapoll", true);
-		
-		if (!instance->thread) {
-			free(instance);
-			instance = NULL;
-			return;
-		}
-	}
-
+	instance->thread = thread_create(kniagarapoll, NULL, TASK, 0,
+	    "kniagarapoll", true);
+	
+	if (!instance->thread) {
+		free(instance);
+		instance = NULL;
+		return;
+	}
+	
 	instance->srlnin = NULL;
-
+	
 	output_buffer.read_ptr = 0;
 	output_buffer.write_ptr = 0;
 	input_buffer.write_ptr = 0;
 	input_buffer.read_ptr = 0;
-
+	
 	/*
 	 * Set sysinfos and pareas so that the userspace counterpart of the
 	 * niagara fb and kbd driver can communicate with kernel using shared
 	 * buffers.
- 	 */
-
+	 */
+	
 	sysinfo_set_item_val("fb.kind", NULL, 5);
-
+	
 	sysinfo_set_item_val("niagara.outbuf.address", NULL,
-		KA2PA(&output_buffer));
+	    KA2PA(&output_buffer));
 	sysinfo_set_item_val("niagara.outbuf.size", NULL,
-		PAGE_SIZE);
+	    PAGE_SIZE);
 	sysinfo_set_item_val("niagara.outbuf.datasize", NULL,
-		OUTPUT_BUFFER_SIZE);
-
+	    OUTPUT_BUFFER_SIZE);
+	
 	sysinfo_set_item_val("niagara.inbuf.address", NULL,
-		KA2PA(&input_buffer));
+	    KA2PA(&input_buffer));
 	sysinfo_set_item_val("niagara.inbuf.size", NULL,
-		PAGE_SIZE);
+	    PAGE_SIZE);
 	sysinfo_set_item_val("niagara.inbuf.datasize", NULL,
-		INPUT_BUFFER_SIZE);
-
-	static parea_t outbuf_parea;
+	   INPUT_BUFFER_SIZE);
+	
 	outbuf_parea.pbase = (uintptr_t) (KA2PA(&output_buffer));
 	outbuf_parea.frames = 1;
 	outbuf_parea.unpriv = false;
+	outbuf_parea.mapped = false;
 	ddi_parea_register(&outbuf_parea);
-
-	static parea_t inbuf_parea;
+	
 	inbuf_parea.pbase = (uintptr_t) (KA2PA(&input_buffer));
 	inbuf_parea.frames = 1;
 	inbuf_parea.unpriv = false;
+	inbuf_parea.mapped = false;
 	ddi_parea_register(&inbuf_parea);
-
+	
 	outdev_t *niagara_dev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
 	outdev_initialize("niagara_dev", niagara_dev, &niagara_ops);
@@ -230,11 +239,11 @@
 }
 
-/**
- * A public function which initializes input from the Niagara console.
+/** Initialize input from the Niagara console.
+ *
  */
 niagara_instance_t *niagarain_init(void)
 {
 	niagara_init();
-
+	
 	if (instance) {
 		srln_instance_t *srln_instance = srln_init();
@@ -242,10 +251,10 @@
 			indev_t *sink = stdin_wire();
 			indev_t *srln = srln_wire(srln_instance, sink);
-
-			// wire std. input to niagara
+			
 			instance->srlnin = srln;
 			thread_ready(instance->thread);
 		}
 	}
+	
 	return instance;
 }
Index: kernel/arch/sparc64/src/drivers/scr.c
===================================================================
--- kernel/arch/sparc64/src/drivers/scr.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/drivers/scr.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,5 @@
 #include <genarch/ofw/upa.h>
 #include <genarch/fb/fb.h>
-#include <genarch/fb/visuals.h>
+#include <abi/fb/visuals.h>
 #include <console/chardev.h>
 #include <console/console.h>
Index: rnel/arch/sparc64/src/drivers/sgcn.c
===================================================================
--- kernel/arch/sparc64/src/drivers/sgcn.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,358 +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.
- */
-
-/** @addtogroup sparc64
- * @{
- */
-/**
- * @file
- * @brief SGCN driver.
- */
-
-#include <arch.h>
-#include <arch/drivers/sgcn.h>
-#include <arch/drivers/kbd.h>
-#include <genarch/ofw/ofw_tree.h>
-#include <debug.h>
-#include <str.h>
-#include <print.h>
-#include <mm/page.h>
-#include <proc/thread.h>
-#include <console/chardev.h>
-#include <console/console.h>
-#include <sysinfo/sysinfo.h>
-#include <synch/spinlock.h>
-
-#define POLL_INTERVAL  10000
-
-/*
- * Physical address at which the SBBC starts. This value has been obtained
- * by inspecting (using Simics) memory accesses made by OBP. It is valid
- * for the Simics-simulated Serengeti machine. The author of this code is
- * not sure whether this value is valid generally. 
- */
-#define SBBC_START  0x63000000000
-
-/* offset of SRAM within the SBBC memory */
-#define SBBC_SRAM_OFFSET  0x900000
-
-/* size (in bytes) of the physical memory area which will be mapped */
-#define MAPPED_AREA_SIZE  (128 * 1024)
-
-/* magic string contained at the beginning of SRAM */
-#define SRAM_TOC_MAGIC  "TOCSRAM"
-
-/*
- * Key into the SRAM table of contents which identifies the entry
- * describing the OBP console buffer. It is worth mentioning
- * that the OBP console buffer is not the only console buffer
- * which can be used. It is, however, used because when the kernel
- * is running, the OBP buffer is not used by OBP any more but OBP
- * has already made necessary arrangements so that the output will
- * be read from the OBP buffer and input will go to the OBP buffer.
- * Therefore HelenOS needs to make no such arrangements any more.
- */
-#define CONSOLE_KEY  "OBPCONS"
-
-/* magic string contained at the beginning of the console buffer */
-#define SGCN_BUFFER_MAGIC  "CON"
-
-/*
- * Returns a pointer to the object of a given type which is placed at the given
- * offset from the SRAM beginning.
- */
-#define SRAM(type, offset)  ((type *) (instance->sram_begin + (offset)))
-
-/* Returns a pointer to the SRAM table of contents. */
-#define SRAM_TOC  (SRAM(iosram_toc_t, 0))
-
-/*
- * Returns a pointer to the object of a given type which is placed at the given
- * offset from the console buffer beginning.
- */
-#define SGCN_BUFFER(type, offset) \
-	((type *) (instance->buffer_begin + (offset)))
-
-/** Returns a pointer to the console buffer header. */
-#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
-
-static void sgcn_putchar(outdev_t *, const wchar_t, bool);
-
-static outdev_operations_t sgcndev_ops = {
-	.write = sgcn_putchar,
-	.redraw = NULL
-};
-
-static sgcn_instance_t *instance = NULL;
-
-/**
- * Set some sysinfo values (SRAM address and SRAM size).
- */
-static void register_sram(uintptr_t sram_begin_physical)
-{
-	sysinfo_set_item_val("sram.area.size", NULL, MAPPED_AREA_SIZE);
-	sysinfo_set_item_val("sram.address.physical", NULL,
-	    sram_begin_physical);
-}
-
-/**
- * Initializes the starting address of SRAM.
- *
- * The SRAM starts 0x900000 + C bytes behind the SBBC start in the
- * physical memory, where C is the value read from the "iosram-toc"
- * property of the "/chosen" OBP node. The sram_begin variable will
- * be set to the virtual address which maps to the SRAM physical
- * address.
- */
-static void init_sram_begin(void)
-{
-	ASSERT(instance);
-	
-	ofw_tree_node_t *chosen = ofw_tree_lookup("/chosen");
-	if (!chosen)
-		panic("Cannot find '/chosen'.");
-	
-	ofw_tree_property_t *iosram_toc =
-	    ofw_tree_getprop(chosen, "iosram-toc");
-	if (!iosram_toc)
-		panic("Cannot find property 'iosram-toc'.");
-	if (!iosram_toc->value)
-		panic("Cannot find SRAM TOC.");
-	
-	uintptr_t sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
-	    + *((uint32_t *) iosram_toc->value);
-	instance->sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
-	
-	register_sram(sram_begin_physical);
-}
-
-/**
- * Function regularly called by the keyboard polling thread. Finds out whether
- * there are some unread characters in the input queue. If so, it picks them up
- * and sends them to the upper layers of HelenOS.
- */
-static void sgcn_poll(sgcn_instance_t *instance)
-{
-	uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
-	uint32_t end = SGCN_BUFFER_HEADER->in_end;
-	uint32_t size = end - begin;
-	
-	if (silent)
-		return;
-	
-	spinlock_lock(&instance->input_lock);
-	
-	/* we need pointers to volatile variables */
-	volatile char *buf_ptr = (volatile char *)
-	    SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-	volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
-	volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
-	
-	while (*in_rdptr_ptr != *in_wrptr_ptr) {
-		buf_ptr = (volatile char *)
-		    SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-		char c = *buf_ptr;
-		*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
-		
-		indev_push_character(instance->srlnin, c);
-	}
-	
-	spinlock_unlock(&instance->input_lock);
-}
-
-/**
- * Polling thread function.
- */
-static void ksgcnpoll(void *instance) {
-	while (true) {
-		if (!silent)
-			sgcn_poll(instance);
-		
-		thread_usleep(POLL_INTERVAL);
-	}
-}
-
-/**
- * Initializes the starting address of the SGCN buffer.
- *
- * The offset of the SGCN buffer within SRAM is obtained from the
- * SRAM table of contents. The table of contents contains
- * information about several buffers, among which there is an OBP
- * console buffer - this one will be used as the SGCN buffer. 
- *
- * This function also writes the offset of the SGCN buffer within SRAM
- * under the sram.buffer.offset sysinfo key.
- */
-static void sgcn_init(void)
-{
-	if (instance)
-		return;
-	
-	instance = malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC);
-	
-	if (instance) {
-		instance->thread = thread_create(ksgcnpoll, instance, TASK, 0,
-		    "ksgcnpoll", true);
-		
-		if (!instance->thread) {
-			free(instance);
-			instance = NULL;
-			return;
-		}
-		
-		init_sram_begin();
-		
-		ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
-		
-		/* Lookup TOC entry with the correct key */
-		uint32_t i;
-		for (i = 0; i < MAX_TOC_ENTRIES; i++) {
-			if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
-				break;
-		}
-		ASSERT(i < MAX_TOC_ENTRIES);
-		
-		instance->buffer_begin =
-		    instance->sram_begin + SRAM_TOC->keys[i].offset;
-		
-		sysinfo_set_item_val("sram.buffer.offset", NULL,
-		    SRAM_TOC->keys[i].offset);
-		
-		instance->srlnin = NULL;
-	}
-}
-
-/**
- * Writes a single character to the SGCN (circular) output buffer
- * and updates the output write pointer so that SGCN gets to know
- * that the character has been written.
- */
-static void sgcn_do_putchar(const char c)
-{
-	uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
-	uint32_t end = SGCN_BUFFER_HEADER->out_end;
-	uint32_t size = end - begin;
-	
-	/* We need pointers to volatile variables */
-	volatile char *buf_ptr = (volatile char *)
-	    SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
-	volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
-	volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
-	
-	/*
-	 * Write the character and increment the write pointer modulo the
-	 * output buffer size. Note that if we are to rewrite a character
-	 * which has not been read by the SGCN controller yet (i.e. the output
-	 * buffer is full), we need to wait until the controller reads some more
-	 * characters. We wait actively, which means that all threads waiting
-	 * for the lock are blocked. However, this situation is
-	 *   1) rare - the output buffer is big, so filling the whole
-	 *             output buffer is improbable
-	 *   2) short-lasting - it will take the controller only a fraction
-	 *             of millisecond to pick the unread characters up
-	 *   3) not serious - the blocked threads are those that print something
-	 *             to user console, which is not a time-critical operation
-	 */
-	uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
-	while (*out_rdptr_ptr == new_wrptr);
-	
-	*buf_ptr = c;
-	*out_wrptr_ptr = new_wrptr;
-}
-
-/**
- * SGCN output operation. Prints a single character to the SGCN. Newline
- * character is converted to CRLF.
- */
-static void sgcn_putchar(outdev_t *dev, const wchar_t ch, bool silent)
-{
-	if (!silent) {
-		spinlock_lock(&instance->output_lock);
-		
-		if (ascii_check(ch)) {
-			if (ch == '\n')
-				sgcn_do_putchar('\r');
-			sgcn_do_putchar(ch);
-		} else
-			sgcn_do_putchar(U_SPECIAL);
-		
-		spinlock_unlock(&instance->output_lock);
-	}
-}
-
-/**
- * A public function which initializes input from the Serengeti console.
- */
-sgcn_instance_t *sgcnin_init(void)
-{
-	sgcn_init();
-	return instance;
-}
-
-void sgcnin_wire(sgcn_instance_t *instance, indev_t *srlnin)
-{
-	ASSERT(instance);
-	ASSERT(srlnin);
-	
-	instance->srlnin = srlnin;
-	thread_ready(instance->thread);
-	
-	sysinfo_set_item_val("kbd", NULL, true);
-}
-
-/**
- * A public function which initializes output to the Serengeti console.
- */
-outdev_t *sgcnout_init(void)
-{
-	sgcn_init();
-	if (!instance)
-		return NULL;
-	
-	outdev_t *sgcndev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
-	if (!sgcndev)
-		return NULL;
-	
-	outdev_initialize("sgcndev", sgcndev, &sgcndev_ops);
-	sgcndev->data = instance;
-	
-	if (!fb_exported) {
-		/*
-		 * This is the necessary evil until the userspace driver is entirely
-		 * self-sufficient.
-		 */
-		sysinfo_set_item_val("fb.kind", NULL, 4);
-		
-		fb_exported = true;
-	}
-	
-	return sgcndev;
-}
-
-/** @}
- */
Index: kernel/arch/sparc64/src/drivers/tick.c
===================================================================
--- kernel/arch/sparc64/src/drivers/tick.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/drivers/tick.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,6 +44,4 @@
 #include <debug.h>
 
-#define TICK_RESTART_TIME	50	/* Worst case estimate. */
-
 /** Initialize tick and stick interrupt. */
 void tick_init(void)
@@ -51,4 +49,5 @@
 	/* initialize TICK interrupt */
 	tick_compare_reg_t compare;
+	softint_reg_t clear;
 
 	interrupt_register(14, "tick_int", tick_interrupt);
@@ -59,8 +58,11 @@
 	tick_compare_write(compare.value);
 
+	clear.value = 0;
+	clear.tick_int = 1;
+	clear_softint_write(clear.value);
+
 #if defined (US3) || defined (SUN4V)
 	/* disable STICK interrupts and clear any pending ones */
 	tick_compare_reg_t stick_compare;
-	softint_reg_t clear;
 
 	stick_compare.value = stick_compare_read();
Index: kernel/arch/sparc64/src/mm/sun4u/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4u/as.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/mm/sun4u/as.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,9 +43,9 @@
 
 #include <arch/mm/tsb.h>
-#include <arch/memstr.h>
 #include <arch/asm.h>
 #include <mm/frame.h>
 #include <bitops.h>
 #include <macros.h>
+#include <memstr.h>
 
 #endif /* CONFIG_TSB */
Index: kernel/arch/sparc64/src/mm/sun4u/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4u/tlb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/mm/sun4u/tlb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -207,5 +207,5 @@
 
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, page_16k);
+	t = page_mapping_find(AS, page_16k, true);
 	if (t && PTE_EXECUTABLE(t)) {
 		/*
@@ -275,5 +275,5 @@
 
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, page_16k);
+	t = page_mapping_find(AS, page_16k, true);
 	if (t) {
 		/*
@@ -319,5 +319,5 @@
 
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, page_16k);
+	t = page_mapping_find(AS, page_16k, true);
 	if (t && PTE_WRITABLE(t)) {
 		/*
Index: kernel/arch/sparc64/src/mm/sun4v/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4v/as.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/mm/sun4v/as.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -46,9 +46,9 @@
 
 #include <arch/mm/tsb.h>
-#include <arch/memstr.h>
 #include <arch/asm.h>
 #include <mm/frame.h>
 #include <bitops.h>
 #include <macros.h>
+#include <memstr.h>
 
 #endif /* CONFIG_TSB */
Index: kernel/arch/sparc64/src/mm/sun4v/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4v/tlb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/mm/sun4v/tlb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -219,5 +219,5 @@
 
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 
 	if (t && PTE_EXECUTABLE(t)) {
@@ -275,5 +275,5 @@
 
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 	if (t) {
 		/*
@@ -317,5 +317,5 @@
 
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, va);
+	t = page_mapping_find(AS, va, true);
 	if (t && PTE_WRITABLE(t)) {
 		/*
Index: kernel/arch/sparc64/src/smp/sun4u/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4u/smp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/smp/sun4u/smp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,5 +42,4 @@
 #include <macros.h>
 #include <typedefs.h>
-#include <synch/synch.h>
 #include <synch/waitq.h>
 #include <print.h>
Index: kernel/arch/sparc64/src/smp/sun4v/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4v/smp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/smp/sun4v/smp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2006 Jakub Jermar
- * Copyright (c) 2009 Pavel Rimsky 
+ * Copyright (c) 2009 Pavel Rimsky
  * All rights reserved.
  *
@@ -45,5 +45,4 @@
 #include <func.h>
 #include <typedefs.h>
-#include <synch/synch.h>
 #include <synch/waitq.h>
 #include <print.h>
@@ -439,5 +438,5 @@
 	if (waitq_sleep_timeout(&ap_completion_wq, 10000000, SYNCH_FLAGS_NONE) ==
 	    ESYNCH_TIMEOUT)
-		printf("%s: waiting for processor (cpuid = %" PRIu32 ") timed out\n",
+		printf("%s: waiting for processor (cpuid = %" PRIu64 ") timed out\n",
 		    __func__, cpuid);
 	
Index: kernel/arch/sparc64/src/sun4v/start.S
===================================================================
--- kernel/arch/sparc64/src/sun4v/start.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/sun4v/start.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,4 +30,5 @@
 #include <arch/arch.h>
 #include <arch/stack.h>
+#include <arch/regdef.h>
 #include <arch/context_offset.h>
 #include <arch/sun4v/regdef.h>
@@ -296,5 +297,5 @@
 	 * Create the first stack frame.
 	 */
-	save %sp, -(STACK_WINDWO_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
+	save %sp, -(STACK_WINDOW_SAVE_AREA_SIZE + STACK_ARG_SAVE_AREA_SIZE), %sp
 	flushw
 	add %g0, -STACK_BIAS, %fp
Index: kernel/arch/sparc64/src/trap/sun4v/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/sun4v/interrupt.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/arch/sparc64/src/trap/sun4v/interrupt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -111,5 +111,5 @@
 			((void (*)(void)) data1)();
 		} else {
-			printf("Spurious interrupt on %d, data = %" PRIx64 ".\n",
+			printf("Spurious interrupt on %" PRIu64 ", data = %" PRIx64 ".\n",
 			    CPU->arch.id, data1);
 		}
Index: kernel/genarch/Makefile.inc
===================================================================
--- kernel/genarch/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -100,9 +100,4 @@
 endif
 
-ifeq ($(CONFIG_Z8530),y)
-	GENARCH_SOURCES += \
-		genarch/src/drivers/z8530/z8530.c
-endif
-
 ifeq ($(CONFIG_VIA_CUDA),y)
 	GENARCH_SOURCES += \
@@ -120,10 +115,4 @@
 		genarch/src/kbrd/kbrd.c \
 		genarch/src/kbrd/scanc_sun.c
-endif
-
-ifeq ($(CONFIG_PL050),y)
-	GENARCH_SOURCES += \
-		genarch/src/kbrd/kbrd_pl050.c \
-		genarch/src/kbrd/scanc_pl050.c
 endif
 
@@ -147,5 +136,4 @@
 	GENARCH_SOURCES += \
 		genarch/src/ofw/ebus.c \
-		genarch/src/ofw/fhc.c \
 		genarch/src/ofw/pci.c  \
 		genarch/src/ofw/sbus.c \
Index: kernel/genarch/include/drivers/s3c24xx_uart/s3c24xx_uart.h
===================================================================
--- kernel/genarch/include/drivers/s3c24xx_uart/s3c24xx_uart.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/include/drivers/s3c24xx_uart/s3c24xx_uart.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #define KERN_S3C24XX_UART_H_
 
+#include <ddi/ddi.h>
 #include <ddi/irq.h>
 #include <console/chardev.h>
@@ -83,7 +84,8 @@
 	indev_t *indev;
 	irq_t irq;
+	parea_t parea;
 } s3c24xx_uart_t;
 
-extern outdev_t *s3c24xx_uart_init(s3c24xx_uart_io_t *, inr_t inr);
+extern outdev_t *s3c24xx_uart_init(uintptr_t, inr_t inr);
 extern void s3c24xx_uart_input_wire(s3c24xx_uart_t *,
     indev_t *);
Index: rnel/genarch/include/drivers/z8530/z8530.h
===================================================================
--- kernel/genarch/include/drivers/z8530/z8530.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,128 +1,0 @@
-/*
- * Copyright (c) 2009 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 genarch
- * @{
- */
-/**
- * @file
- * @brief Headers for Zilog 8530 serial controller.
- */
-
-#ifndef KERN_Z8530_H_
-#define KERN_Z8530_H_
-
-#include <ddi/irq.h>
-#include <typedefs.h>
-#include <console/chardev.h>
-
-#define WR0   0
-#define WR1   1
-#define WR2   2
-#define WR3   3
-#define WR4   4
-#define WR5   5
-#define WR6   6
-#define WR7   7
-#define WR8   8
-#define WR9   9
-#define WR10  10
-#define WR11  11
-#define WR12  12
-#define WR13  13
-#define WR14  14
-#define WR15  15
-
-#define RR0   0
-#define RR1   1
-#define RR2   2
-#define RR3   3
-#define RR8   8
-#define RR10  10
-#define RR12  12
-#define RR13  13
-#define RR14  14
-#define RR15  15
-
-/** Reset pending TX interrupt. */
-#define WR0_TX_IP_RST  (0x5 << 3)
-#define WR0_ERR_RST    (0x6 << 3)
-
-/** Receive Interrupts Disabled. */
-#define WR1_RID     (0x0 << 3)
-/** Receive Interrupt on First Character or Special Condition. */
-#define WR1_RIFCSC  (0x1 << 3)
-/** Interrupt on All Receive Characters or Special Conditions. */
-#define WR1_IARCSC  (0x2 << 3)
-/** Receive Interrupt on Special Condition. */
-#define WR1_RISC    (0x3 << 3)
-/** Parity Is Special Condition. */
-#define WR1_PISC    (0x1 << 2)
-
-/** Rx Enable. */
-#define WR3_RX_ENABLE  (0x1 << 0)
-/** 8-bits per character. */
-#define WR3_RX8BITSCH  (0x3 << 6)
-
-/** Master Interrupt Enable. */
-#define WR9_MIE  (0x1 << 3)
-
-/** Receive Character Available. */
-#define RR0_RCA  (0x1 << 0)
-
-/** z8530's registers. */
-typedef struct {
-	union {
-		ioport8_t ctl_b;
-		ioport8_t status_b;
-	} __attribute__ ((packed));
-	uint8_t pad1;
-	ioport8_t data_b;
-	uint8_t pad2;
-	union {
-		ioport8_t ctl_a;
-		ioport8_t status_a;
-	} __attribute__ ((packed));
-	uint8_t pad3;
-	ioport8_t data_a;
-} __attribute__ ((packed)) z8530_t;
-
-/** Structure representing the z8530 device. */
-typedef struct {
-	irq_t irq;
-	z8530_t *z8530;
-	indev_t *kbrdin;
-} z8530_instance_t;
-
-extern z8530_instance_t *z8530_init(z8530_t *, inr_t, cir_t, void *);
-extern void z8530_wire(z8530_instance_t *, indev_t *);
-
-#endif
-
-/** @}
- */
Index: kernel/genarch/include/fb/fb.h
===================================================================
--- kernel/genarch/include/fb/fb.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/include/fb/fb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,6 +37,6 @@
 
 #include <typedefs.h>
+#include <abi/fb/visuals.h>
 #include <console/chardev.h>
-#include <genarch/fb/visuals.h>
 
 /**
Index: rnel/genarch/include/fb/visuals.h
===================================================================
--- kernel/genarch/include/fb/visuals.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * Copyright (c) 2006 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.
- */
-
-/** @addtogroup genarch
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_VISUALS_H_
-#define KERN_VISUALS_H_
-
-typedef enum {
-	VISUAL_UNKNOWN = 0,
-	VISUAL_INDIRECT_8,
-	VISUAL_RGB_5_5_5_LE,
-	VISUAL_RGB_5_5_5_BE,
-	VISUAL_RGB_5_6_5_LE,
-	VISUAL_RGB_5_6_5_BE,
-	VISUAL_BGR_8_8_8,
-	VISUAL_BGR_0_8_8_8,
-	VISUAL_BGR_8_8_8_0,
-	VISUAL_RGB_8_8_8,
-	VISUAL_RGB_0_8_8_8,
-	VISUAL_RGB_8_8_8_0
-} visual_t;
-
-#endif
-
-/** @}
- */
Index: kernel/genarch/include/mm/page_pt.h
===================================================================
--- kernel/genarch/include/mm/page_pt.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/include/mm/page_pt.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -129,5 +129,5 @@
 
 extern void page_mapping_insert_pt(as_t *, uintptr_t, uintptr_t, unsigned int);
-extern pte_t *page_mapping_find_pt(as_t *, uintptr_t);
+extern pte_t *page_mapping_find_pt(as_t *, uintptr_t, bool);
 
 #endif
Index: rnel/genarch/include/ofw/fhc.h
===================================================================
--- kernel/genarch/include/ofw/fhc.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * Copyright (c) 2006 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.
- */
-
-#ifndef KERN_FHC_H_
-#define KERN_FHC_H_
-
-#include <genarch/ofw/ofw_tree.h>
-#include <typedefs.h>
-#include <ddi/irq.h>
-#include <typedefs.h>
-
-typedef struct {
-	uint64_t addr;
-	uint32_t size;
-} __attribute__ ((packed)) ofw_fhc_reg_t;
-
-typedef struct {
-	uint64_t child_base;
-	uint64_t parent_base;
-	uint32_t size;
-} __attribute__ ((packed)) ofw_fhc_range_t;
-
-typedef struct {
-	uint64_t addr;
-	uint32_t size;
-} __attribute__ ((packed)) ofw_central_reg_t;
-
-typedef struct {
-	uint64_t child_base;
-	uint64_t parent_base;
-	uint32_t size;
-} __attribute__ ((packed)) ofw_central_range_t;
-
-extern bool ofw_fhc_apply_ranges(ofw_tree_node_t *, ofw_fhc_reg_t *,
-    uintptr_t *);
-extern bool ofw_central_apply_ranges(ofw_tree_node_t *, ofw_central_reg_t *,
-    uintptr_t *);
-
-extern bool ofw_fhc_map_interrupt(ofw_tree_node_t *, ofw_fhc_reg_t *,
-    uint32_t, int *, cir_t *, void **);
-
-#endif
Index: kernel/genarch/src/drivers/dsrln/dsrlnout.c
===================================================================
--- kernel/genarch/src/drivers/dsrln/dsrlnout.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/drivers/dsrln/dsrlnout.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,14 +42,16 @@
 #include <sysinfo/sysinfo.h>
 #include <str.h>
+#include <ddi/ddi.h>
 
 typedef struct {
+	parea_t parea;
 	ioport8_t *base;
 } dsrlnout_instance_t;
 
-static void dsrlnout_putchar(outdev_t *dev, const wchar_t ch, bool silent)
+static void dsrlnout_putchar(outdev_t *dev, const wchar_t ch)
 {
 	dsrlnout_instance_t *instance = (dsrlnout_instance_t *) dev->data;
 	
-	if (!silent) {
+	if ((!instance->parea.mapped) || (console_override)) {
 		if (ascii_check(ch))
 			pio_write_8(instance->base, ch);
@@ -70,5 +72,6 @@
 		return NULL;
 	
-	dsrlnout_instance_t *instance = malloc(sizeof(dsrlnout_instance_t), FRAME_ATOMIC);
+	dsrlnout_instance_t *instance = malloc(sizeof(dsrlnout_instance_t),
+	    FRAME_ATOMIC);
 	if (!instance) {
 		free(dsrlndev);
@@ -80,8 +83,15 @@
 	
 	instance->base = base;
+	link_initialize(&instance->parea.link);
+	instance->parea.pbase = KA2PA(base);
+	instance->parea.frames = 1;
+	instance->parea.unpriv = false;
+	instance->parea.mapped = false;
+	ddi_parea_register(&instance->parea);
 	
 	if (!fb_exported) {
 		/*
-		 * This is the necessary evil until the userspace driver is entirely
+		 * This is the necessary evil until
+		 * the userspace driver is entirely
 		 * self-sufficient.
 		 */
Index: kernel/genarch/src/drivers/ega/ega.c
===================================================================
--- kernel/genarch/src/drivers/ega/ega.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/drivers/ega/ega.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,5 +41,4 @@
 #include <mm/slab.h>
 #include <arch/mm/page.h>
-#include <synch/spinlock.h>
 #include <typedefs.h>
 #include <arch/asm.h>
@@ -65,4 +64,6 @@
 	IRQ_SPINLOCK_DECLARE(lock);
 	
+	parea_t parea;
+	
 	uint32_t cursor;
 	uint8_t *addr;
@@ -71,5 +72,5 @@
 } ega_instance_t;
 
-static void ega_putchar(outdev_t *, wchar_t, bool);
+static void ega_putchar(outdev_t *, wchar_t);
 static void ega_redraw(outdev_t *);
 
@@ -438,5 +439,5 @@
  * This function takes care of scrolling.
  */
-static void ega_check_cursor(ega_instance_t *instance, bool silent)
+static void ega_check_cursor(ega_instance_t *instance)
 {
 	if (instance->cursor < EGA_SCREEN)
@@ -449,5 +450,5 @@
 	    EGA_COLS, EMPTY_CHAR);
 	
-	if (!silent) {
+	if ((!instance->parea.mapped) || (console_override)) {
 		memmove((void *) instance->addr,
 		    (void *) (instance->addr + EGA_COLS * 2),
@@ -460,7 +461,7 @@
 }
 
-static void ega_show_cursor(ega_instance_t *instance, bool silent)
-{
-	if (!silent) {
+static void ega_show_cursor(ega_instance_t *instance)
+{
+	if ((!instance->parea.mapped) || (console_override)) {
 		pio_write_8(instance->base + EGA_INDEX_REG, 0x0a);
 		uint8_t stat = pio_read_8(instance->base + EGA_DATA_REG);
@@ -470,7 +471,7 @@
 }
 
-static void ega_move_cursor(ega_instance_t *instance, bool silent)
-{
-	if (!silent) {
+static void ega_move_cursor(ega_instance_t *instance)
+{
+	if ((!instance->parea.mapped) || (console_override)) {
 		pio_write_8(instance->base + EGA_INDEX_REG, 0x0e);
 		pio_write_8(instance->base + EGA_DATA_REG,
@@ -482,7 +483,7 @@
 }
 
-static void ega_sync_cursor(ega_instance_t *instance, bool silent)
-{
-	if (!silent) {
+static void ega_sync_cursor(ega_instance_t *instance)
+{
+	if ((!instance->parea.mapped) || (console_override)) {
 		pio_write_8(instance->base + EGA_INDEX_REG, 0x0e);
 		uint8_t hi = pio_read_8(instance->base + EGA_DATA_REG);
@@ -504,14 +505,14 @@
 	    EGA_SCREEN - instance->cursor, EMPTY_CHAR);
 	
-	if (!silent)
+	if ((!instance->parea.mapped) || (console_override))
 		memsetw(instance->addr + instance->cursor * 2,
 		    EGA_SCREEN - instance->cursor, EMPTY_CHAR);
 	
-	ega_check_cursor(instance, silent);
-	ega_move_cursor(instance, silent);
-	ega_show_cursor(instance, silent);
-}
-
-static void ega_display_char(ega_instance_t *instance, wchar_t ch, bool silent)
+	ega_check_cursor(instance);
+	ega_move_cursor(instance);
+	ega_show_cursor(instance);
+}
+
+static void ega_display_char(ega_instance_t *instance, wchar_t ch)
 {
 	uint16_t index = ega_oem_glyph(ch);
@@ -530,5 +531,5 @@
 	instance->backbuf[instance->cursor * 2 + 1] = style;
 	
-	if (!silent) {
+	if ((!instance->parea.mapped) || (console_override)) {
 		instance->addr[instance->cursor * 2] = glyph;
 		instance->addr[instance->cursor * 2 + 1] = style;
@@ -536,5 +537,5 @@
 }
 
-static void ega_putchar(outdev_t *dev, wchar_t ch, bool silent)
+static void ega_putchar(outdev_t *dev, wchar_t ch)
 {
 	ega_instance_t *instance = (ega_instance_t *) dev->data;
@@ -556,10 +557,10 @@
 		break;
 	default:
-		ega_display_char(instance, ch, silent);
+		ega_display_char(instance, ch);
 		instance->cursor++;
 		break;
 	}
-	ega_check_cursor(instance, silent);
-	ega_move_cursor(instance, silent);
+	ega_check_cursor(instance);
+	ega_move_cursor(instance);
 	
 	irq_spinlock_unlock(&instance->lock, true);
@@ -573,6 +574,6 @@
 	
 	memcpy(instance->addr, instance->backbuf, EGA_VRAM_SIZE);
-	ega_move_cursor(instance, silent);
-	ega_show_cursor(instance, silent);
+	ega_move_cursor(instance);
+	ega_show_cursor(instance);
 	
 	irq_spinlock_unlock(&instance->lock, true);
@@ -613,12 +614,20 @@
 	}
 	
+	link_initialize(&instance->parea.link);
+	instance->parea.pbase = addr;
+	instance->parea.frames = SIZE2FRAMES(EGA_VRAM_SIZE);
+	instance->parea.unpriv = false;
+	instance->parea.mapped = false;
+	ddi_parea_register(&instance->parea);
+	
 	/* Synchronize the back buffer and cursor position. */
 	memcpy(instance->backbuf, instance->addr, EGA_VRAM_SIZE);
-	ega_sync_cursor(instance, silent);
+	ega_sync_cursor(instance);
 	
 	if (!fb_exported) {
 		/*
-		 * This is the necessary evil until the userspace driver is entirely
-		 * self-sufficient.
+		 * We export the kernel framebuffer for uspace usage.
+		 * This is used in the case the uspace framebuffer
+		 * driver is not self-sufficient.
 		 */
 		sysinfo_set_item_val("fb", NULL, true);
Index: kernel/genarch/src/drivers/s3c24xx_uart/s3c24xx_uart.c
===================================================================
--- kernel/genarch/src/drivers/s3c24xx_uart/s3c24xx_uart.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/drivers/s3c24xx_uart/s3c24xx_uart.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,4 +44,5 @@
 #include <arch/asm.h>
 #include <mm/slab.h>
+#include <mm/page.h>
 #include <sysinfo/sysinfo.h>
 #include <str.h>
@@ -59,11 +60,14 @@
 }
 
-static void s3c24xx_uart_putchar(outdev_t *dev, wchar_t ch, bool silent)
+static void s3c24xx_uart_putchar(outdev_t *dev, wchar_t ch)
 {
-	if (!silent) {
+	s3c24xx_uart_t *uart =
+	    (s3c24xx_uart_t *) dev->data;
+	
+	if ((!uart->parea.mapped) || (console_override)) {
 		if (!ascii_check(ch)) {
 			s3c24xx_uart_sendb(dev, U_SPECIAL);
 		} else {
-    			if (ch == '\n')
+			if (ch == '\n')
 				s3c24xx_uart_sendb(dev, (uint8_t) '\r');
 			s3c24xx_uart_sendb(dev, (uint8_t) ch);
@@ -93,5 +97,5 @@
 };
 
-outdev_t *s3c24xx_uart_init(s3c24xx_uart_io_t *io, inr_t inr)
+outdev_t *s3c24xx_uart_init(uintptr_t paddr, inr_t inr)
 {
 	outdev_t *uart_dev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
@@ -109,5 +113,5 @@
 	uart_dev->data = uart;
 
-	uart->io = io;
+	uart->io = (s3c24xx_uart_io_t *) hw_map(paddr, PAGE_SIZE);
 	uart->indev = NULL;
 
@@ -127,13 +131,21 @@
 	pio_write_32(&uart->io->ucon,
 	    pio_read_32(&uart->io->ucon) & ~UCON_RX_INT_LEVEL);
-
+	
+	link_initialize(&uart->parea.link);
+	uart->parea.pbase = paddr;
+	uart->parea.frames = 1;
+	uart->parea.unpriv = false;
+	uart->parea.mapped = false;
+	ddi_parea_register(&uart->parea);
+	
 	if (!fb_exported) {
 		/*
-		 * This is the necessary evil until the userspace driver is entirely
+		 * This is the necessary evil until
+		 * the userspace driver is entirely
 		 * self-sufficient.
 		 */
 		sysinfo_set_item_val("fb", NULL, true);
 		sysinfo_set_item_val("fb.kind", NULL, 3);
-		sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(io));
+		sysinfo_set_item_val("fb.address.physical", NULL, paddr);
 
 		fb_exported = true;
Index: kernel/genarch/src/drivers/via-cuda/cuda.c
===================================================================
--- kernel/genarch/src/drivers/via-cuda/cuda.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/drivers/via-cuda/cuda.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -239,9 +239,9 @@
 	cuda_instance_t *instance = irq->instance;
 	cuda_t *dev = instance->cuda;
-	uint8_t data, b;
-
+	uint8_t b;
+	
 	b = pio_read_8(&dev->b);
-	data = pio_read_8(&dev->sr);
-
+	pio_read_8(&dev->sr);
+	
 	if ((b & TREQ) == 0) {
 		instance->xstate = cx_receive;
@@ -251,7 +251,7 @@
 		cuda_send_start(instance);
 	}
-
-        memcpy(buf, instance->rcv_buf, instance->bidx);
-        *len = instance->bidx;
+	
+	memcpy(buf, instance->rcv_buf, instance->bidx);
+	*len = instance->bidx;
 	instance->bidx = 0;
 }
Index: rnel/genarch/src/drivers/z8530/z8530.c
===================================================================
--- kernel/genarch/src/drivers/z8530/z8530.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,136 +1,0 @@
-/*
- * Copyright (c) 2009 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 genarch
- * @{
- */
-/**
- * @file
- * @brief Zilog 8530 serial controller driver.
- */
-
-#include <genarch/drivers/z8530/z8530.h>
-#include <console/chardev.h>
-#include <ddi/irq.h>
-#include <arch/asm.h>
-#include <mm/slab.h>
-#include <ddi/device.h>
-
-static inline void z8530_write(ioport8_t *ctl, uint8_t reg, uint8_t val)
-{
-	/*
-	 * Registers 8-15 will automatically issue the Point High
-	 * command as their bit 3 is 1.
-	 */
-	pio_write_8(ctl, reg);  /* Select register */
-	pio_write_8(ctl, val);  /* Write value */
-}
-
-static inline uint8_t z8530_read(ioport8_t *ctl, uint8_t reg) 
-{
-	/*
-	 * Registers 8-15 will automatically issue the Point High
-	 * command as their bit 3 is 1.
-	 */
-	pio_write_8(ctl, reg);   /* Select register */
-	return pio_read_8(ctl);
-}
-
-static irq_ownership_t z8530_claim(irq_t *irq)
-{
-	z8530_instance_t *instance = irq->instance;
-	z8530_t *dev = instance->z8530;
-	
-	if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA)
-		return IRQ_ACCEPT;
-	else
-		return IRQ_DECLINE;
-}
-
-static void z8530_irq_handler(irq_t *irq)
-{
-	z8530_instance_t *instance = irq->instance;
-	z8530_t *dev = instance->z8530;
-	
-	if (z8530_read(&dev->ctl_a, RR0) & RR0_RCA) {
-		uint8_t data = z8530_read(&dev->ctl_a, RR8);
-		indev_push_character(instance->kbrdin, data);
-	}
-}
-
-/** Initialize z8530. */
-z8530_instance_t *z8530_init(z8530_t *dev, inr_t inr, cir_t cir, void *cir_arg)
-{
-	z8530_instance_t *instance
-	    = malloc(sizeof(z8530_instance_t), FRAME_ATOMIC);
-	if (instance) {
-		instance->z8530 = dev;
-		instance->kbrdin = NULL;
-		
-		irq_initialize(&instance->irq);
-		instance->irq.devno = device_assign_devno();
-		instance->irq.inr = inr;
-		instance->irq.claim = z8530_claim;
-		instance->irq.handler = z8530_irq_handler;
-		instance->irq.instance = instance;
-		instance->irq.cir = cir;
-		instance->irq.cir_arg = cir_arg;
-	}
-	
-	return instance;
-}
-
-void z8530_wire(z8530_instance_t *instance, indev_t *kbrdin)
-{
-	ASSERT(instance);
-	ASSERT(kbrdin);
-	
-	instance->kbrdin = kbrdin;
-	
-	irq_register(&instance->irq);
-	
-	(void) z8530_read(&instance->z8530->ctl_a, RR8);
-	
-	/*
-	 * Clear any pending TX interrupts or we never manage
-	 * to set FHC UART interrupt state to idle.
-	 */
-	z8530_write(&instance->z8530->ctl_a, WR0, WR0_TX_IP_RST);
-	
-	/* interrupt on all characters */
-	z8530_write(&instance->z8530->ctl_a, WR1, WR1_IARCSC);
-	
-	/* 8 bits per character and enable receiver */
-	z8530_write(&instance->z8530->ctl_a, WR3, WR3_RX8BITSCH | WR3_RX_ENABLE);
-	
-	/* Master Interrupt Enable. */
-	z8530_write(&instance->z8530->ctl_a, WR9, WR9_MIE);
-}
-
-/** @}
- */
Index: kernel/genarch/src/fb/fb.c
===================================================================
--- kernel/genarch/src/fb/fb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/fb/fb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,5 +36,4 @@
 #include <genarch/fb/font-8x16.h>
 #include <genarch/fb/logo-196x66.h>
-#include <genarch/fb/visuals.h>
 #include <genarch/fb/fb.h>
 #include <console/chardev.h>
@@ -82,4 +81,6 @@
 	SPINLOCK_DECLARE(lock);
 	
+	parea_t parea;
+	
 	uint8_t *addr;
 	uint16_t *backbuf;
@@ -109,5 +110,5 @@
 } fb_instance_t;
 
-static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent);
+static void fb_putchar(outdev_t *dev, wchar_t ch);
 static void fb_redraw_internal(fb_instance_t *instance);
 static void fb_redraw(outdev_t *dev);
@@ -215,5 +216,5 @@
  *
  */
-static void logo_hide(fb_instance_t *instance, bool silent)
+static void logo_hide(fb_instance_t *instance)
 {
 	instance->ylogo = 0;
@@ -221,5 +222,5 @@
 	instance->rowtrim = instance->rows;
 	
-	if (!silent)
+	if ((!instance->parea.mapped) || (console_override))
 		fb_redraw_internal(instance);
 }
@@ -229,5 +230,5 @@
  */
 static void glyph_draw(fb_instance_t *instance, uint16_t glyph,
-    unsigned int col, unsigned int row, bool silent, bool overlay)
+    unsigned int col, unsigned int row, bool overlay)
 {
 	unsigned int x = COL2X(col);
@@ -236,10 +237,10 @@
 	
 	if (y >= instance->ytrim)
-		logo_hide(instance, silent);
+		logo_hide(instance);
 	
 	if (!overlay)
 		instance->backbuf[BB_POS(instance, col, row)] = glyph;
 	
-	if (!silent) {
+	if ((!instance->parea.mapped) || (console_override)) {
 		for (yd = 0; yd < FONT_SCANLINES; yd++)
 			memcpy(&instance->addr[FB_POS(instance, x, y + yd + instance->ylogo)],
@@ -253,12 +254,12 @@
  *
  */
-static void screen_scroll(fb_instance_t *instance, bool silent)
+static void screen_scroll(fb_instance_t *instance)
 {
 	if (instance->ylogo > 0) {
-		logo_hide(instance, silent);
+		logo_hide(instance);
 		return;
 	}
 	
-	if (!silent) {
+	if ((!instance->parea.mapped) || (console_override)) {
 		unsigned int row;
 		
@@ -298,13 +299,13 @@
 }
 
-static void cursor_put(fb_instance_t *instance, bool silent)
+static void cursor_put(fb_instance_t *instance)
 {
 	unsigned int col = instance->position % instance->cols;
 	unsigned int row = instance->position / instance->cols;
 	
-	glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, silent, true);
-}
-
-static void cursor_remove(fb_instance_t *instance, bool silent)
+	glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, true);
+}
+
+static void cursor_remove(fb_instance_t *instance)
 {
 	unsigned int col = instance->position % instance->cols;
@@ -312,5 +313,5 @@
 	
 	glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
-	    col, row, silent, true);
+	    col, row, true);
 }
 
@@ -362,5 +363,5 @@
  *
  */
-static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent)
+static void fb_putchar(outdev_t *dev, wchar_t ch)
 {
 	fb_instance_t *instance = (fb_instance_t *) dev->data;
@@ -369,23 +370,23 @@
 	switch (ch) {
 	case '\n':
-		cursor_remove(instance, silent);
+		cursor_remove(instance);
 		instance->position += instance->cols;
 		instance->position -= instance->position % instance->cols;
 		break;
 	case '\r':
-		cursor_remove(instance, silent);
+		cursor_remove(instance);
 		instance->position -= instance->position % instance->cols;
 		break;
 	case '\b':
-		cursor_remove(instance, silent);
+		cursor_remove(instance);
 		if (instance->position % instance->cols)
 			instance->position--;
 		break;
 	case '\t':
-		cursor_remove(instance, silent);
+		cursor_remove(instance);
 		do {
 			glyph_draw(instance, fb_font_glyph(' '),
 			    instance->position % instance->cols,
-			    instance->position / instance->cols, silent, false);
+			    instance->position / instance->cols, false);
 			instance->position++;
 		} while ((instance->position % 8)
@@ -395,5 +396,5 @@
 		glyph_draw(instance, fb_font_glyph(ch),
 		    instance->position % instance->cols,
-		    instance->position / instance->cols, silent, false);
+		    instance->position / instance->cols, false);
 		instance->position++;
 	}
@@ -401,8 +402,8 @@
 	if (instance->position >= instance->cols * instance->rows) {
 		instance->position -= instance->cols;
-		screen_scroll(instance, silent);
-	}
-	
-	cursor_put(instance, silent);
+		screen_scroll(instance);
+	}
+	
+	cursor_put(instance);
 	
 	spinlock_unlock(&instance->lock);
@@ -555,4 +556,5 @@
 	
 	spinlock_initialize(&instance->lock, "*fb.instance.lock");
+	
 	instance->rgb_conv = rgb_conv;
 	instance->pixelbytes = pixelbytes;
@@ -623,8 +625,16 @@
 	glyphs_render(instance);
 	
+	link_initialize(&instance->parea.link);
+	instance->parea.pbase = props->addr;
+	instance->parea.frames = SIZE2FRAMES(fbsize);
+	instance->parea.unpriv = false;
+	instance->parea.mapped = false;
+	ddi_parea_register(&instance->parea);
+	
 	if (!fb_exported) {
 		/*
-		 * This is the necessary evil until the userspace driver is entirely
-		 * self-sufficient.
+		 * We export the kernel framebuffer for uspace usage.
+		 * This is used in the case the uspace framebuffer
+		 * driver is not self-sufficient.
 		 */
 		sysinfo_set_item_val("fb", NULL, true);
Index: rnel/genarch/src/kbrd/kbrd_pl050.c
===================================================================
--- kernel/genarch/src/kbrd/kbrd_pl050.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,209 +1,0 @@
-/*
- * Copyright (c) 2009 Vineeth Pillai
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup genarch
- * @{
- */
-/**
- * @file
- * @brief pl050 Keyboard processing.
- */
-
-#include <genarch/kbrd/kbrd.h>
-#include <genarch/kbrd/scanc.h>
-
-#include <genarch/kbrd/scanc_pl050.h>
-
-#include <synch/spinlock.h>
-#include <console/chardev.h>
-#include <console/console.h>
-#include <proc/thread.h>
-#include <arch.h>
-#include <macros.h>
-
-#define PRESSED_SHIFT     (1 << 0)
-#define PRESSED_CAPSLOCK  (1 << 1)
-#define LOCKED_CAPSLOCK   (1 << 0)
-
-#define PL050_KEY_RELEASE 0xF0
-#define PL050_ESC_KEY   0xE0
-#define PL050_CAPS_SCAN_CODE   0x58
-#define PL050_NUM_SCAN_CODE   0x77
-#define PL050_SCROLL_SCAN_CODE   0x7E
-
-static bool is_lock_key(wchar_t);
-
-static indev_operations_t kbrd_raw_ops = {
-	.poll = NULL
-};
-
-/** Process release of key.
- *
- * @param sc Scancode of the key being released.
- */
-static void key_released(kbrd_instance_t *instance, wchar_t sc)
-{
-	spinlock_lock(&instance->keylock);
-	
-	switch (sc) {
-	case SC_LSHIFT:
-	case SC_RSHIFT:
-		instance->keyflags &= ~PRESSED_SHIFT;
-		break;
-	case SC_CAPSLOCK:
-		instance->keyflags &= ~PRESSED_CAPSLOCK;
-		if (instance->lockflags & LOCKED_CAPSLOCK)
-			instance->lockflags &= ~LOCKED_CAPSLOCK;
-		else
-			instance->lockflags |= LOCKED_CAPSLOCK;
-		break;
-	default:
-		break;
-	}
-	
-	spinlock_unlock(&instance->keylock);
-}
-
-/** Process keypress.
- *
- * @param sc Scancode of the key being pressed.
- */
-static void key_pressed(kbrd_instance_t *instance, wchar_t sc)
-{
-	bool letter;
-	bool shift;
-	bool capslock;
-	
-	spinlock_lock(&instance->keylock);
-	
-	switch (sc) {
-	case SC_LSHIFT:
-	case SC_RSHIFT:
-		instance->keyflags |= PRESSED_SHIFT;
-		break;
-	case SC_CAPSLOCK:
-		instance->keyflags |= PRESSED_CAPSLOCK;
-		break;
-	case SC_SCAN_ESCAPE:
-		break;
-	default:
-		letter = islower(sc_primary_map[sc]);
-		shift = instance->keyflags & PRESSED_SHIFT;
-		capslock = (instance->keyflags & PRESSED_CAPSLOCK) ||
-		    (instance->lockflags & LOCKED_CAPSLOCK);
-		
-		if ((letter) && (capslock))
-			shift = !shift;
-		
-		if (shift)
-			indev_push_character(instance->sink, sc_secondary_map[sc]);
-		else
-			indev_push_character(instance->sink, sc_primary_map[sc]);
-		break;
-	}
-	
-	spinlock_unlock(&instance->keylock);
-}
-
-static void kkbrd(void *arg)
-{
-	static int key_released_flag = 0;
-	static int is_locked = 0;
-	kbrd_instance_t *instance = (kbrd_instance_t *) arg;
-	
-	while (true) {
-		wchar_t sc = indev_pop_character(&instance->raw);
-
-		if (sc == PL050_KEY_RELEASE) {
-			key_released_flag = 1;
-		} else {
-			if (key_released_flag) {
-				key_released_flag = 0;
-				if (is_lock_key(sc)) {
-					if (!is_locked) {
-						is_locked = 1;
-					} else {
-						is_locked = 0;
-						continue;
-					}
-				}
-				key_released(instance, sc);
-
-			} else {
-				if (is_lock_key(sc) && is_locked)
-					continue;
-				key_pressed(instance, sc);
-			}
-		}
-		
-	}
-}
-
-kbrd_instance_t *kbrd_init(void)
-{
-	kbrd_instance_t *instance
-	    = malloc(sizeof(kbrd_instance_t), FRAME_ATOMIC);
-	if (instance) {
-		instance->thread
-			= thread_create(kkbrd, (void *) instance, TASK, 0, "kkbrd", false);
-		
-		if (!instance->thread) {
-			free(instance);
-			return NULL;
-		}
-		
-		instance->sink = NULL;
-		indev_initialize("kbrd", &instance->raw, &kbrd_raw_ops);
-		
-		spinlock_initialize(&instance->keylock, "kbrd_pl050.instance.keylock");
-		instance->keyflags = 0;
-		instance->lockflags = 0;
-	}
-	
-	return instance;
-}
-
-indev_t *kbrd_wire(kbrd_instance_t *instance, indev_t *sink)
-{
-	ASSERT(instance);
-	ASSERT(sink);
-	
-	instance->sink = sink;
-	thread_ready(instance->thread);
-	
-	return &instance->raw;
-}
-
-static bool is_lock_key(wchar_t sc)
-{
-	return ((sc == PL050_CAPS_SCAN_CODE) || (sc == PL050_NUM_SCAN_CODE) ||
-		(sc == PL050_SCROLL_SCAN_CODE));
-}
-
-/** @}
- */
Index: rnel/genarch/src/kbrd/scanc_pl050.c
===================================================================
--- kernel/genarch/src/kbrd/scanc_pl050.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,234 +1,0 @@
-/*
- * Copyright (c) 2009 Vineeth Pillai
- * 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, U_SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup genarch	
- * @{
- */
-/**
- * @file
- * @brief	Scan codes for pl050 keyboards.
- */
-#include <genarch/kbrd/scanc.h>
-#include <typedefs.h>
-#include <str.h>
-
-
-/** Primary meaning of scancodes. */
-wchar_t sc_primary_map[] = {
-	U_NULL, /* 0x00 */
-	U_SPECIAL, /* 0x01 - F9 */
-	U_SPECIAL, /* 0x02 - F7 */
-	U_SPECIAL, /* 0x03 - F5 */
-	U_SPECIAL, /* 0x04 - F3 */
-	U_SPECIAL, /* 0x05 - F1 */
-	U_SPECIAL, /* 0x06 - F2 */
-	U_SPECIAL, /* 0x07 - F12 */
-	U_SPECIAL, /* 0x08 -  */
-	U_SPECIAL, /* 0x09 - F10 */
-	U_SPECIAL, /* 0x0A - F8 */
-	U_SPECIAL, /* 0x0B - F10 */
-	U_SPECIAL, /* 0x0C - F4 */
-	'\t', /* 0x0D - Tab */
-	'`',
-	U_SPECIAL, /* 0x0F */
-	U_SPECIAL, /* 0x10 */
-	U_SPECIAL, /* 0x11 - LAlt */
-	U_SPECIAL, /* 0x12 - LShift */
-	U_SPECIAL, /* ox13 */
-	U_SPECIAL, /* 0x14 Ctrl */
-	'q', '1',
-	U_SPECIAL, /* 0x17 */
-	U_SPECIAL, /* 0x18 */
-	U_SPECIAL, /* 0x19 */
-	'z', 's', 'a', 'w', '2',
-	U_SPECIAL, /* 0x1F */
-	U_SPECIAL, /* 0x20 */
-	'c', 'x', 'd', 'e', '4', '3',
-	U_SPECIAL, /* 0x27 */
-	U_SPECIAL, /* 0x28 */
-	' ', 'v', 'f', 't', 'r', '5',
-	U_SPECIAL, /* 0x2F */
-	U_SPECIAL, /* 0x30 */
-	'n', 'b', 'h', 'g', 'y', '6',
-	U_SPECIAL, /* 0x37 */
-	U_SPECIAL, /* 0x38 */
-	U_SPECIAL, /* 0x39 */
-	'm', 'j', 'u', '7', '8',
-	U_SPECIAL, /* 0x3F */
-	U_SPECIAL, /* 0x40 */
-	',', 'k', 'i', 'o', '0', '9',
-	U_SPECIAL, /* 0x47 */
-	U_SPECIAL, /* 0x48 */
-	'.', '/', 'l', ';', 'p', '-',
-	U_SPECIAL, /* 0x4F */
-	U_SPECIAL, /* 0x50 */
-	U_SPECIAL, /* 0x51 */
-	'\'',
-	U_SPECIAL, /* 0x53 */
-	'[', '=',
-	U_SPECIAL, /* 0x56 */
-	U_SPECIAL, /* 0x57 */
-	U_SPECIAL, /* 0x58 - Caps Lock */
-	U_SPECIAL, /* 0x59 - RShift */
-	'\n', ']',
-	U_SPECIAL, /* 0x5C */
-	'\\',
-	U_SPECIAL, /* 0x5E */
-	U_SPECIAL, /* 0x5F */
-	U_SPECIAL, /* 0x60 */
-	U_SPECIAL, /* 0x61 */
-	U_SPECIAL, /* 0x62 */
-	U_SPECIAL, /* 0x63 */
-	U_SPECIAL, /* 0x64 */
-	U_SPECIAL, /* 0x65 */
-	'\b', /* 0x66  - backspace*/
-	U_SPECIAL, /* 0x67 */
-	U_SPECIAL, /* 0x68 */
-	U_END_ARROW, /* 0x69 */
-	U_SPECIAL, /* 0x6a */
-	U_LEFT_ARROW, /* 0x6b - Left Arrow */
-	U_SPECIAL, /* 0x6c */
-	U_SPECIAL, /* 0x6d */
-	U_SPECIAL, /* 0x6e */
-	U_SPECIAL, /* 0x6f */
-	U_SPECIAL, /* 0x70 */
-	U_DELETE, /* 0x71 - Del*/
-	U_DOWN_ARROW, /* 0x72 Down Arrow */
-	U_SPECIAL, /* 0x73 */
-	U_RIGHT_ARROW, /* 0x74  - Right Arrow */
-	U_UP_ARROW, /* 0x75  Up Arrow */
-	U_ESCAPE, /* 0x76 Esc */
-	U_SPECIAL, /* 0x77 - NumLock*/
-	U_SPECIAL, /* 0x78  F11*/
-	U_SPECIAL, /* 0x79 */
-	U_PAGE_DOWN, /* 0x7a */
-	U_SPECIAL, /* 0x7b */
-	U_SPECIAL, /* 0x7c */
-	U_PAGE_UP, /* 0x7d */
-	U_SPECIAL, /* 0x7e */
-	U_SPECIAL /* 0x7f */
-};
-
-/** Secondary meaning of scancodes. */
-wchar_t sc_secondary_map[] = {
-	U_NULL, /* 0x00 */
-	U_SPECIAL, /* 0x01 - F9 */
-	U_SPECIAL, /* 0x02 - F7 */
-	U_SPECIAL, /* 0x03 - F5 */
-	U_SPECIAL, /* 0x04 - F3 */
-	U_SPECIAL, /* 0x05 - F1 */
-	U_SPECIAL, /* 0x06 - F2 */
-	U_SPECIAL, /* 0x07 - F12 */
-	U_SPECIAL, /* 0x08 -  */
-	U_SPECIAL, /* 0x09 - F10 */
-	U_SPECIAL, /* 0x0A - F8 */
-	U_SPECIAL, /* 0x0B - F10 */
-	U_SPECIAL, /* 0x0C - F4 */
-	'\t', /* 0x0D - Tab */
-	'~',
-	U_SPECIAL, /* 0x0F */
-	U_SPECIAL, /* 0x10 */
-	U_SPECIAL, /* 0x11 - LAlt */
-	U_SPECIAL, /* 0x12 - LShift */
-	U_SPECIAL, /* ox13 */
-	U_SPECIAL, /* 0x14 Ctrl */
-	'Q', '!',
-	U_SPECIAL, /* 0x17 */
-	U_SPECIAL, /* 0x18 */
-	U_SPECIAL, /* 0x19 */
-	'Z', 'S', 'A', 'W', '@',
-	U_SPECIAL, /* 0x1F */
-	U_SPECIAL, /* 0x20 */
-	'C', 'X', 'D', 'E', '$', '#',
-	U_SPECIAL, /* 0x27 */
-	U_SPECIAL, /* 0x28 */
-	' ', 'V', 'F', 'T', 'R', '%',
-	U_SPECIAL, /* 0x2F */
-	U_SPECIAL, /* 0x30 */
-	'N', 'B', 'H', 'G', 'Y', '^',
-	U_SPECIAL, /* 0x37 */
-	U_SPECIAL, /* 0x38 */
-	U_SPECIAL, /* 0x39 */
-	'M', 'J', 'U', '&', '*',
-	U_SPECIAL, /* 0x3F */
-	U_SPECIAL, /* 0x40 */
-	'<', 'K', 'I', 'O', ')', '(',
-	U_SPECIAL, /* 0x47 */
-	U_SPECIAL, /* 0x48 */
-	'>', '?', 'L', ':', 'P', '_',
-	U_SPECIAL, /* 0x4F */
-	U_SPECIAL, /* 0x50 */
-	U_SPECIAL, /* 0x51 */
-	'"',
-	U_SPECIAL, /* 0x53 */
-	'{', '+',
-	U_SPECIAL, /* 0x56 */
-	U_SPECIAL, /* 0x57 */
-	U_SPECIAL, /* 0x58 - Caps Lock */
-	U_SPECIAL, /* 0x59 - RShift */
-	'\n', '}',
-	U_SPECIAL, /* 0x5C */
-	'|',
-	U_SPECIAL, /* 0x5E */
-	U_SPECIAL, /* 0x5F */
-	U_SPECIAL, /* 0x60 */
-	U_SPECIAL, /* 0x61 */
-	U_SPECIAL, /* 0x62 */
-	U_SPECIAL, /* 0x63 */
-	U_SPECIAL, /* 0x64 */
-	U_SPECIAL, /* 0x65 */
-	'\b', /* 0x66  - backspace*/
-	U_SPECIAL, /* 0x67 */
-	U_SPECIAL, /* 0x68 */
-	U_END_ARROW, /* 0x69 */
-	U_SPECIAL, /* 0x6a */
-	U_LEFT_ARROW, /* 0x6b - Left Arrow */
-	U_SPECIAL, /* 0x6c */
-	U_SPECIAL, /* 0x6d */
-	U_SPECIAL, /* 0x6e */
-	U_SPECIAL, /* 0x6f */
-	U_SPECIAL, /* 0x70 */
-	U_DELETE, /* 0x71 - Del*/
-	U_DOWN_ARROW, /* 0x72 Down Arrow */
-	U_SPECIAL, /* 0x73 */
-	U_RIGHT_ARROW, /* 0x74  - Right Arrow */
-	U_UP_ARROW, /* 0x75  Up Arrow */
-	U_ESCAPE, /* 0x76 Esc */
-	U_SPECIAL, /* 0x77 - NumLock*/
-	U_SPECIAL, /* 0x78  F11*/
-	U_SPECIAL, /* 0x79 */
-	U_PAGE_DOWN, /* 0x7a */
-	U_SPECIAL, /* 0x7b */
-	U_SPECIAL, /* 0x7c */
-	U_PAGE_UP, /* 0x7d */
-	U_SPECIAL, /* 0x7e */
-	U_SPECIAL /* 0x7f */
-};
-
-/** @}
- */
Index: kernel/genarch/src/mm/asid.c
===================================================================
--- kernel/genarch/src/mm/asid.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/mm/asid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -97,6 +97,6 @@
 		 * inactive address space.
 		 */
-		ASSERT(!list_empty(&inactive_as_with_asid_head));
-		tmp = inactive_as_with_asid_head.next;
+		tmp = list_first(&inactive_as_with_asid_list);
+		ASSERT(tmp != NULL);
 		list_remove(tmp);
 		
Index: kernel/genarch/src/mm/page_ht.c
===================================================================
--- kernel/genarch/src/mm/page_ht.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/mm/page_ht.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -58,5 +58,5 @@
 static void ht_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
 static void ht_mapping_remove(as_t *, uintptr_t);
-static pte_t *ht_mapping_find(as_t *, uintptr_t);
+static pte_t *ht_mapping_find(as_t *, uintptr_t, bool);
 
 /**
@@ -214,5 +214,5 @@
  * this call visible.
  *
- * @param as   Address space to wich page belongs.
+ * @param as   Address space to which page belongs.
  * @param page Virtual address of the page to be demapped.
  *
@@ -237,13 +237,12 @@
 /** Find mapping for virtual page in page hash table.
  *
- * Find mapping for virtual page.
- *
- * @param as   Address space to wich page belongs.
- * @param page Virtual page.
+ * @param as     Address space to which page belongs.
+ * @param page   Virtual page.
+ * @param nolock True if the page tables need not be locked.
  *
  * @return NULL if there is no such mapping; requested mapping otherwise.
  *
  */
-pte_t *ht_mapping_find(as_t *as, uintptr_t page)
+pte_t *ht_mapping_find(as_t *as, uintptr_t page, bool nolock)
 {
 	sysarg_t key[2] = {
@@ -252,5 +251,5 @@
 	};
 
-	ASSERT(page_table_locked(as));
+	ASSERT(nolock || page_table_locked(as));
 	
 	link_t *cur = hash_table_find(&page_ht, key);
Index: kernel/genarch/src/mm/page_pt.c
===================================================================
--- kernel/genarch/src/mm/page_pt.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/mm/page_pt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -48,5 +48,5 @@
 static void pt_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
 static void pt_mapping_remove(as_t *, uintptr_t);
-static pte_t *pt_mapping_find(as_t *, uintptr_t);
+static pte_t *pt_mapping_find(as_t *, uintptr_t, bool);
 
 page_mapping_operations_t pt_mapping_operations = {
@@ -238,8 +238,7 @@
 /** Find mapping for virtual page in hierarchical page tables.
  *
- * Find mapping for virtual page.
- *
- * @param as   Address space to which page belongs.
- * @param page Virtual page.
+ * @param as     Address space to which page belongs.
+ * @param page   Virtual page.
+ * @param nolock True if the page tables need not be locked.
  *
  * @return NULL if there is no such mapping; entry from PTL3 describing
@@ -247,7 +246,7 @@
  *
  */
-pte_t *pt_mapping_find(as_t *as, uintptr_t page)
+pte_t *pt_mapping_find(as_t *as, uintptr_t page, bool nolock)
 {
-	ASSERT(page_table_locked(as));
+	ASSERT(nolock || page_table_locked(as));
 
 	pte_t *ptl0 = (pte_t *) PA2KA((uintptr_t) as->genarch.page_table);
Index: kernel/genarch/src/ofw/ebus.c
===================================================================
--- kernel/genarch/src/ofw/ebus.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/ofw/ebus.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #include <genarch/ofw/ebus.h>
 #include <genarch/ofw/pci.h>
-#include <arch/memstr.h>
 #include <str.h>
 #include <panic.h>
Index: rnel/genarch/src/ofw/fhc.c
===================================================================
--- kernel/genarch/src/ofw/fhc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,138 +1,0 @@
-/*
- * Copyright (c) 2006 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 ofw
- * @{
- */
-/**
- * @file
- * @brief	FHC 'reg' and 'ranges' properties handling.
- *
- */
-
-#include <genarch/ofw/ofw_tree.h>
-#include <genarch/ofw/fhc.h>
-#include <arch/drivers/fhc.h>
-#include <arch/memstr.h>
-#include <str.h>
-#include <panic.h>
-#include <macros.h>
-
-bool ofw_fhc_apply_ranges(ofw_tree_node_t *node, ofw_fhc_reg_t *reg, uintptr_t *pa)
-{
-	ofw_tree_property_t *prop;
-	ofw_fhc_range_t *range;
-	size_t ranges;
-
-	prop = ofw_tree_getprop(node, "ranges");
-	if (!prop)
-		return false;
-		
-	ranges = prop->size / sizeof(ofw_fhc_range_t);
-	range = prop->value;
-	
-	unsigned int i;
-	
-	for (i = 0; i < ranges; i++) {
-		if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
-			uintptr_t addr;
-			
-			addr = range[i].parent_base + (reg->addr - range[i].child_base);
-			if (!node->parent->parent) {
-				*pa = addr;
-				return true;
-			}
-			if (str_cmp(ofw_tree_node_name(node->parent), "central") != 0)
-				panic("Unexpected parent node: %s.", ofw_tree_node_name(node->parent));
-			
-			ofw_central_reg_t central_reg;
-			
-			central_reg.addr = addr;
-			central_reg.size = reg->size;
-			
-			return ofw_central_apply_ranges(node->parent, &central_reg, pa);
-		}
-	}
-
-	return false;
-}
-
-bool ofw_central_apply_ranges(ofw_tree_node_t *node, ofw_central_reg_t *reg, uintptr_t *pa)
-{
-	if (node->parent->parent)
-		panic("Unexpected parent node: %s.", ofw_tree_node_name(node->parent));
-	
-	ofw_tree_property_t *prop;
-	ofw_central_range_t *range;
-	size_t ranges;
-	
-	prop = ofw_tree_getprop(node, "ranges");
-	if (!prop)
-		return false;
-		
-	ranges = prop->size / sizeof(ofw_central_range_t);
-	range = prop->value;
-	
-	unsigned int i;
-	
-	for (i = 0; i < ranges; i++) {
-		if (overlaps(reg->addr, reg->size, range[i].child_base, range[i].size)) {
-			*pa = range[i].parent_base + (reg->addr - range[i].child_base);
-			return true;
-		}
-	}
-	
-	return false;
-}
-
-bool
-ofw_fhc_map_interrupt(ofw_tree_node_t *node, ofw_fhc_reg_t *reg,
-    uint32_t interrupt, int *inr, cir_t *cir, void **cir_arg)
-{
-	fhc_t *fhc = NULL;
-	if (!node->device) {
-		fhc = fhc_init(node);
-		if (!fhc)
-			return false;
-		node->device = fhc;
-		central_fhc = fhc;
-	}
-	
-	/*
-	 * The interrupt controller for the interrupt is the FHC itself.
-	 */
-	fhc_enable_interrupt(fhc, interrupt);
-	
-	*inr = interrupt;
-	*cir = fhc_clear_interrupt;
-	*cir_arg = fhc;
-	return true;
-}
-
-/** @}
- */
Index: kernel/genarch/src/ofw/ofw_tree.c
===================================================================
--- kernel/genarch/src/ofw/ofw_tree.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/ofw/ofw_tree.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,6 +37,6 @@
 
 #include <genarch/ofw/ofw_tree.h>
-#include <arch/memstr.h>
 #include <mm/slab.h>
+#include <memstr.h>
 #include <str.h>
 #include <panic.h>
Index: kernel/genarch/src/ofw/pci.c
===================================================================
--- kernel/genarch/src/ofw/pci.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/ofw/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,5 +40,4 @@
 #include <arch/drivers/pci.h>
 #include <arch/trap/interrupt.h>
-#include <arch/memstr.h>
 #include <str.h>
 #include <panic.h>
Index: kernel/genarch/src/ofw/upa.c
===================================================================
--- kernel/genarch/src/ofw/upa.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/genarch/src/ofw/upa.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,4 @@
 #include <genarch/ofw/ofw_tree.h>
 #include <genarch/ofw/upa.h>
-#include <arch/memstr.h>
 #include <func.h>
 #include <panic.h>
Index: kernel/generic/include/adt/btree.h
===================================================================
--- kernel/generic/include/adt/btree.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/adt/btree.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -89,5 +89,5 @@
 typedef struct {
 	btree_node_t *root;	/**< B-tree root node pointer. */
-	link_t leaf_head;	/**< Leaf-level list head. */
+	list_t leaf_list;	/**< List of leaves. */
 } btree_t;
 
Index: kernel/generic/include/adt/hash_table.h
===================================================================
--- kernel/generic/include/adt/hash_table.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/adt/hash_table.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -68,5 +68,5 @@
 /** Hash table structure. */
 typedef struct {
-	link_t *entry;
+	list_t *entry;
 	size_t entries;
 	size_t max_keys;
Index: kernel/generic/include/adt/list.h
===================================================================
--- kernel/generic/include/adt/list.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/adt/list.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -39,16 +40,37 @@
 #include <trace.h>
 
-/** Doubly linked list head and link type. */
+/** Doubly linked list link. */
 typedef struct link {
-	struct link *prev;	/**< Pointer to the previous item in the list. */
-	struct link *next;	/**< Pointer to the next item in the list. */
+	struct link *prev;  /**< Pointer to the previous item in the list. */
+	struct link *next;  /**< Pointer to the next item in the list. */
 } link_t;
 
+/** Doubly linked list. */
+typedef struct list {
+	link_t head;  /**< List head. Does not have any data. */
+} list_t;
+
 /** Declare and initialize statically allocated list.
  *
  * @param name Name of the new statically allocated list.
+ *
  */
 #define LIST_INITIALIZE(name) \
-	link_t name = { .prev = &name, .next = &name }
+	list_t name = { \
+		.head = { \
+			.prev = &(name).head, \
+			.next = &(name).head \
+		} \
+	}
+
+#define list_get_instance(link, type, member) \
+	((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
+
+#define list_foreach(list, iterator) \
+	for (link_t *iterator = (list).head.next; \
+	    iterator != &(list).head; iterator = iterator->next)
+
+#define assert_link_not_used(link) \
+	ASSERT((link)->prev == NULL && (link)->next == NULL)
 
 /** Initialize doubly-linked circular list link
@@ -57,4 +79,5 @@
  *
  * @param link Pointer to link_t structure to be initialized.
+ *
  */
 NO_TRACE static inline void link_initialize(link_t *link)
@@ -68,10 +91,33 @@
  * Initialize doubly-linked circular list.
  *
- * @param head Pointer to link_t structure representing head of the list.
- */
-NO_TRACE static inline void list_initialize(link_t *head)
-{
-	head->prev = head;
-	head->next = head;
+ * @param list Pointer to list_t structure.
+ *
+ */
+NO_TRACE static inline void list_initialize(list_t *list)
+{
+	list->head.prev = &list->head;
+	list->head.next = &list->head;
+}
+
+/** Insert item before another item in doubly-linked circular list.
+ *
+ */
+static inline void list_insert_before(link_t *lnew, link_t *lold)
+{
+	lnew->next = lold;
+	lnew->prev = lold->prev;
+	lold->prev->next = lnew;
+	lold->prev = lnew;
+}
+
+/** Insert item after another item in doubly-linked circular list.
+ *
+ */
+static inline void list_insert_after(link_t *lnew, link_t *lold)
+{
+	lnew->prev = lold;
+	lnew->next = lold->next;
+	lold->next->prev = lnew;
+	lold->next = lnew;
 }
 
@@ -81,12 +127,10 @@
  *
  * @param link Pointer to link_t structure to be added.
- * @param head Pointer to link_t structure representing head of the list.
- */
-NO_TRACE static inline void list_prepend(link_t *link, link_t *head)
-{
-	link->next = head->next;
-	link->prev = head;
-	head->next->prev = link;
-	head->next = link;
+ * @param list Pointer to list_t structure.
+ *
+ */
+NO_TRACE static inline void list_prepend(link_t *link, list_t *list)
+{
+	list_insert_after(link, &list->head);
 }
 
@@ -96,12 +140,10 @@
  *
  * @param link Pointer to link_t structure to be added.
- * @param head Pointer to link_t structure representing head of the list.
- */
-NO_TRACE static inline void list_append(link_t *link, link_t *head)
-{
-	link->prev = head->prev;
-	link->next = head;
-	head->prev->next = link;
-	head->prev = link;
+ * @param list Pointer to list_t structure.
+ *
+ */
+NO_TRACE static inline void list_append(link_t *link, list_t *list)
+{
+	list_insert_before(link, &list->head);
 }
 
@@ -110,6 +152,7 @@
  * Remove item from doubly-linked circular list.
  *
- * @param link 	Pointer to link_t structure to be removed from the list it is
- * 		contained in.
+ * @param link Pointer to link_t structure to be removed from the list
+ *             it is contained in.
+ *
  */
 NO_TRACE static inline void list_remove(link_t *link)
@@ -124,11 +167,37 @@
  * Query emptiness of doubly-linked circular list.
  *
- * @param head Pointer to link_t structure representing head of the list.
- */
-NO_TRACE static inline bool list_empty(link_t *head)
-{
-	return head->next == head ? true : false;
-}
-
+ * @param list Pointer to lins_t structure.
+ *
+ */
+NO_TRACE static inline int list_empty(list_t *list)
+{
+	return (list->head.next == &list->head);
+}
+
+/** Get first item in list.
+ *
+ * @param list Pointer to list_t structure.
+ *
+ * @return Head item of the list.
+ * @return NULL if the list is empty.
+ *
+ */
+static inline link_t *list_first(list_t *list)
+{
+	return ((list->head.next == &list->head) ? NULL : list->head.next);
+}
+
+/** Get last item in list.
+ *
+ * @param list Pointer to list_t structure.
+ *
+ * @return Head item of the list.
+ * @return NULL if the list is empty.
+ *
+ */
+static inline link_t *list_last(list_t *list)
+{
+	return ((list->head.prev == &list->head) ? NULL : list->head.prev);
+}
 
 /** Split or concatenate headless doubly-linked circular list
@@ -139,29 +208,30 @@
  * concatenates splitted lists and splits concatenated lists.
  *
- * @param part1	Pointer to link_t structure leading the first (half of the
- *		headless) list.
- * @param part2	Pointer to link_t structure leading the second (half of the
- *		headless) list. 
+ * @param part1 Pointer to link_t structure leading the first
+ *              (half of the headless) list.
+ * @param part2 Pointer to link_t structure leading the second
+ *              (half of the headless) list.
+ *
  */
 NO_TRACE static inline void headless_list_split_or_concat(link_t *part1, link_t *part2)
 {
-	link_t *hlp;
-
 	part1->prev->next = part2;
-	part2->prev->next = part1;	
-	hlp = part1->prev;
+	part2->prev->next = part1;
+	
+	link_t *hlp = part1->prev;
+	
 	part1->prev = part2->prev;
 	part2->prev = hlp;
 }
 
-
 /** Split headless doubly-linked circular list
  *
  * Split headless doubly-linked circular list.
  *
- * @param part1	Pointer to link_t structure leading the first half of the
- *		headless list.
- * @param part2	Pointer to link_t structure leading the second half of the
- *		headless list. 
+ * @param part1 Pointer to link_t structure leading
+ *              the first half of the headless list.
+ * @param part2 Pointer to link_t structure leading
+ *              the second half of the headless list.
+ *
  */
 NO_TRACE static inline void headless_list_split(link_t *part1, link_t *part2)
@@ -174,6 +244,9 @@
  * Concatenate two headless doubly-linked circular lists.
  *
- * @param part1 Pointer to link_t structure leading the first headless list.
- * @param part2 Pointer to link_t structure leading the second headless list.
+ * @param part1 Pointer to link_t structure leading
+ *              the first headless list.
+ * @param part2 Pointer to link_t structure leading
+ *              the second headless list.
+ *
  */
 NO_TRACE static inline void headless_list_concat(link_t *part1, link_t *part2)
@@ -182,9 +255,30 @@
 }
 
-#define list_get_instance(link, type, member) \
-	((type *)(((uint8_t *)(link)) - ((uint8_t *)&(((type *)NULL)->member))))
-
-extern bool list_member(const link_t *link, const link_t *head);
-extern void list_concat(link_t *head1, link_t *head2);
+/** Get n-th item in a list.
+ *
+ * @param list Pointer to link_t structure representing the list.
+ * @param n    Item number (indexed from zero).
+ *
+ * @return n-th item of the list.
+ * @return NULL if no n-th item found.
+ *
+ */
+static inline link_t *list_nth(list_t *list, unsigned int n)
+{
+	unsigned int cnt = 0;
+	
+	list_foreach(*list, link) {
+		if (cnt == n)
+			return link;
+		
+		cnt++;
+	}
+	
+	return NULL;
+}
+
+extern int list_member(const link_t *, const list_t *);
+extern void list_concat(list_t *, list_t *);
+extern unsigned int list_count(const list_t *);
 
 #endif
Index: kernel/generic/include/arch.h
===================================================================
--- kernel/generic/include/arch.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/arch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,5 +41,11 @@
 #include <mm/as.h>
 
-#define DEFAULT_CONTEXT  0
+/*
+ * THE is not an abbreviation, but the English definite article written in
+ * capital letters. It means the current pointer to something, e.g. thread,
+ * processor or address space. Kind reader of this comment shall appreciate
+ * the wit of constructs like THE->thread and similar.
+ */
+#define THE  ((the_t * )(get_stack_base()))
 
 #define CPU                  THE->cpu
@@ -47,8 +53,12 @@
 #define TASK                 THE->task
 #define AS                   THE->as
-#define CONTEXT              (THE->task ? THE->task->context : DEFAULT_CONTEXT)
 #define PREEMPTION_DISABLED  THE->preemption_disabled
+#define MAGIC                UINT32_C(0xfacefeed)
 
-#define context_check(ctx1, ctx2)  ((ctx1) == (ctx2))
+#define container_check(ctn1, ctn2)  ((ctn1) == (ctn2))
+
+#define DEFAULT_CONTAINER  0
+#define CONTAINER \
+	((THE->task) ? (THE->task->container) : (DEFAULT_CONTAINER))
 
 /**
@@ -63,13 +73,6 @@
 	cpu_t *cpu;                  /**< Executing cpu. */
 	as_t *as;                    /**< Current address space. */
+	uint32_t magic;              /**< Magic value */
 } the_t;
-
-/*
- * THE is not an abbreviation, but the English definite article written in
- * capital letters. It means the current pointer to something, e.g. thread,
- * processor or address space. Kind reader of this comment shall appreciate
- * the wit of constructs like THE->thread and similar.
- */
-#define THE  ((the_t * )(get_stack_base()))
 
 extern void the_initialize(the_t *);
Index: kernel/generic/include/config.h
===================================================================
--- kernel/generic/include/config.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/config.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,11 +36,19 @@
 #define KERN_CONFIG_H_
 
-#include <typedefs.h>
 #include <arch/mm/page.h>
 
-#define STACK_SIZE  PAGE_SIZE
+#define ONE_FRAME    0
+#define TWO_FRAMES   1
+#define FOUR_FRAMES  2
+
+#define STACK_FRAMES  TWO_FRAMES
+#define STACK_SIZE    ((1 << STACK_FRAMES) << PAGE_WIDTH)
 
 #define CONFIG_INIT_TASKS        32
 #define CONFIG_TASK_NAME_BUFLEN  32
+
+#ifndef __ASM__
+
+#include <typedefs.h>
 
 typedef struct {
@@ -80,4 +88,6 @@
 extern ballocs_t ballocs;
 
+#endif /* __ASM__ */
+
 #endif
 
Index: kernel/generic/include/console/chardev.h
===================================================================
--- kernel/generic/include/console/chardev.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/console/chardev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -73,5 +73,5 @@
 typedef struct {
 	/** Write character to output. */
-	void (* write)(struct outdev *, wchar_t, bool);
+	void (* write)(struct outdev *, wchar_t);
 	
 	/** Redraw any previously cached characters. */
@@ -88,5 +88,5 @@
 	/** Fields suitable for multiplexing. */
 	link_t link;
-	link_t list;
+	list_t list;
 	
 	/** Implementation of outdev operations. */
Index: kernel/generic/include/console/console.h
===================================================================
--- kernel/generic/include/console/console.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/console/console.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -63,5 +63,5 @@
 
 extern void klog_init(void);
-extern void klog_update(void);
+extern void klog_update(void *);
 
 extern wchar_t getc(indev_t *indev);
@@ -72,6 +72,5 @@
 extern void release_console(void);
 
-extern sysarg_t sys_debug_enable_console(void);
-extern sysarg_t sys_debug_disable_console(void);
+extern sysarg_t sys_debug_activate_console(void);
 
 #endif /* KERN_CONSOLE_H_ */
Index: kernel/generic/include/console/kconsole.h
===================================================================
--- kernel/generic/include/console/kconsole.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/console/kconsole.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -91,5 +91,5 @@
 
 SPINLOCK_EXTERN(cmd_lock);
-extern link_t cmd_head;
+extern list_t cmd_list;
 
 extern void kconsole_init(void);
Index: kernel/generic/include/cpu.h
===================================================================
--- kernel/generic/include/cpu.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/cpu.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,6 +42,4 @@
 #include <arch/context.h>
 
-#define CPU_STACK_SIZE  STACK_SIZE
-
 /** CPU structure.
  *
@@ -61,5 +59,5 @@
 	
 	IRQ_SPINLOCK_DECLARE(timeoutlock);
-	link_t timeout_active_head;
+	list_t timeout_active_list;
 	
 	/**
Index: kernel/generic/include/ddi/ddi.h
===================================================================
--- kernel/generic/include/ddi/ddi.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/ddi/ddi.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,6 @@
 #define KERN_DDI_H_
 
-#include <ddi/ddi_arg.h>
 #include <typedefs.h>
+#include <abi/ddi/arg.h>
 #include <proc/task.h>
 #include <adt/list.h>
@@ -48,4 +48,6 @@
 	pfn_t frames;     /**< Number of frames in the area. */
 	bool unpriv;      /**< Allow mapping by unprivileged tasks. */
+	bool mapped;      /**< Indicate whether the area is actually
+	                       mapped. */
 } parea_t;
 
Index: rnel/generic/include/ddi/ddi_arg.h
===================================================================
--- kernel/generic/include/ddi/ddi_arg.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,68 +1,0 @@
-/*
- * Copyright (c) 2006 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 genericddi
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_DDI_ARG_H_
-#define KERN_DDI_ARG_H_
-
-#ifdef KERNEL
-
-#include <typedefs.h>
-
-#endif /* KERNEL */
-
-/** Structure encapsulating arguments for SYS_PHYSMEM_MAP syscall. */
-typedef struct {
-	/** ID of the destination task. */
-	uint64_t task_id;
-	/** Physical address of starting frame. */
-	void *phys_base;
-	/** Virtual address of starting page. */
-	void *virt_base;
-	/** Number of pages to map. */
-	size_t pages;
-	/** Address space area flags for the mapping. */
-	unsigned int flags;
-} ddi_memarg_t;
-
-/** Structure encapsulating arguments for SYS_ENABLE_IOSPACE syscall. */
-typedef struct {
-	uint64_t task_id;  /**< ID of the destination task. */
-	void *ioaddr;      /**< Starting I/O space address. */
-	size_t size;       /**< Number of bytes. */
-} ddi_ioarg_t;
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/ddi/irq.h
===================================================================
--- kernel/generic/include/ddi/irq.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/ddi/irq.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,10 +33,9 @@
  */
 
-#ifndef KERN_IRQ_H_
-#define KERN_IRQ_H_
-
-#ifdef KERNEL
+#ifndef KERN_DDI_IRQ_H_
+#define KERN_DDI_IRQ_H_
 
 #include <typedefs.h>
+#include <abi/ddi/irq.h>
 #include <adt/list.h>
 #include <adt/hash_table.h>
@@ -44,73 +43,4 @@
 #include <proc/task.h>
 #include <ipc/ipc.h>
-
-#endif /* KERNEL */
-
-typedef enum {
-	/** Read 1 byte from the I/O space. */
-	CMD_PIO_READ_8 = 1,
-	/** Read 2 bytes from the I/O space. */
-	CMD_PIO_READ_16,
-	/** Read 4 bytes from the I/O space. */
-	CMD_PIO_READ_32,
-	
-	/** Write 1 byte to the I/O space. */
-	CMD_PIO_WRITE_8,
-	/** Write 2 bytes to the I/O space. */
-	CMD_PIO_WRITE_16,
-	/** Write 4 bytes to the I/O space. */
-	CMD_PIO_WRITE_32,
-	
-	/**
-	 * Write 1 byte from the source argument
-	 * to the I/O space.
-	 */
-	CMD_PIO_WRITE_A_8,
-	/**
-	 * Write 2 bytes from the source argument
-	 * to the I/O space.
-	 */
-	CMD_PIO_WRITE_A_16,
-	/**
-	 * Write 4 bytes from the source argument
-	 * to the I/O space.
-	 */
-	CMD_PIO_WRITE_A_32,
-	
-	/**
-	 * Perform a bit masking on the source argument
-	 * and store the result into the destination argument.
-	 */
-	CMD_BTEST,
-	
-	/**
-	 * Predicate the execution of the following
-	 * N commands by the boolean value of the source
-	 * argument.
-	 */
-	CMD_PREDICATE,
-	
-	/** Accept the interrupt. */
-	CMD_ACCEPT,
-	
-	/** Decline the interrupt. */
-	CMD_DECLINE,
-	CMD_LAST
-} irq_cmd_type;
-
-typedef struct {
-	irq_cmd_type cmd;
-	void *addr;
-	uint32_t value;
-	uintptr_t srcarg;
-	uintptr_t dstarg;
-} irq_cmd_t;
-
-typedef struct {
-	size_t cmdcount;
-	irq_cmd_t *cmds;
-} irq_code_t;
-
-#ifdef KERNEL
 
 typedef enum {
@@ -125,4 +55,5 @@
 
 struct irq;
+
 typedef void (* irq_handler_t)(struct irq *);
 
@@ -203,4 +134,6 @@
 	/** Notification configuration structure. */
 	ipc_notif_cfg_t notif_cfg; 
+	
+	as_t *driver_as;
 } irq_t;
 
@@ -215,6 +148,4 @@
 extern irq_t *irq_dispatch_and_lock(inr_t);
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/generic/include/errno.h
===================================================================
--- kernel/generic/include/errno.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/errno.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup generic	
+/** @addtogroup generic
  * @{
  */
@@ -36,29 +36,5 @@
 #define KERN_ERRNO_H_
 
-/* 1-255 are kernel error codes, 256-512 are user error codes */
-
-#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 */
-#define EHANGUP		-7	/* Answerbox closed connection, call
-				 * sys_ipc_hangup() to close the connection.
-				 * Used by answerbox to close the connection.
-				 */
-#define EPARTY		-8	/* The other party encountered an error when
-				 * receiving the call.
-				 */
-#define EEXISTS		-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. */
+#include <abi/errno.h>
 
 #endif
Index: kernel/generic/include/ipc/event.h
===================================================================
--- kernel/generic/include/ipc/event.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/ipc/event.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,8 +36,12 @@
 #define KERN_EVENT_H_
 
-#include <ipc/event_types.h>
+#include <abi/ipc/event.h>
 #include <typedefs.h>
 #include <synch/spinlock.h>
 #include <ipc/ipc.h>
+
+struct task;
+
+typedef void (*event_callback_t)(void *);
 
 /** Event notification structure. */
@@ -51,26 +55,51 @@
 	/** Counter. */
 	size_t counter;
+	
+	/** Masked flag. */
+	bool masked;
+	/** Unmask callback. */
+	event_callback_t unmask_callback;
 } event_t;
 
 extern void event_init(void);
+extern void event_task_init(struct task *);
+extern void event_cleanup_answerbox(answerbox_t *);
+extern void event_set_unmask_callback(event_type_t, event_callback_t);
+extern void event_task_set_unmask_callback(struct task *, event_task_type_t,
+    event_callback_t);
+
+#define event_notify_0(e, m) \
+	event_notify((e), (m), 0, 0, 0, 0, 0)
+#define event_notify_1(e, m, a1) \
+	event_notify((e), (m), (a1), 0, 0, 0, 0)
+#define event_notify_2(e, m, a1, a2) \
+	event_notify((e), (m), (a1), (a2), 0, 0, 0)
+#define event_notify_3(e, m, a1, a2, a3) \
+	event_notify((e), (m), (a1), (a2), (a3), 0, 0)
+#define event_notify_4(e, m, a1, a2, a3, a4) \
+	event_notify((e), (m), (a1), (a2), (a3), (a4), 0)
+#define event_notify_5(e, m, a1, a2, a3, a4, a5) \
+	event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
+
+#define event_task_notify_0(t, e, m) \
+	event_task_notify((t), (e), (m), 0, 0, 0, 0, 0)
+#define event_task_notify_1(t, e, m, a1) \
+	event_task_notify((t), (e), (m), (a1), 0, 0, 0, 0)
+#define event_task_notify_2(t, e, m, a1, a2) \
+	event_task_notify((t), (e), (m), (a1), (a2), 0, 0, 0)
+#define event_task_notify_3(t, e, m, a1, a2, a3) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), 0, 0)
+#define event_task_notify_4(t, e, m, a1, a2, a3, a4) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), 0)
+#define event_task_notify_5(t, e, m, a1, a2, a3, a4, a5) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), (a5))
+
+extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t);
+extern int event_task_notify(struct task *, event_task_type_t, bool, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t);
+
 extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
-extern bool event_is_subscribed(event_type_t);
-extern void event_cleanup_answerbox(answerbox_t *);
-
-#define event_notify_0(e) \
-	event_notify((e), 0, 0, 0, 0, 0)
-#define event_notify_1(e, a1) \
-	event_notify((e), (a1), 0, 0, 0, 0)
-#define event_notify_2(e, a1, a2) \
-	event_notify((e), (a1), (a2), 0, 0, 0)
-#define event_notify_3(e, a1, a2, a3) \
-	event_notify((e), (a1), (a2), (a3), 0, 0)
-#define event_notify_4(e, a1, a2, a3, a4) \
-	event_notify((e), (a1), (a2), (a3), (a4), 0)
-#define event_notify_5(e, a1, a2, a3, a4, a5) \
-	event_notify((e), (a1), (a2), (a3), (a4), (a5))
-
-extern void event_notify(event_type_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t);
+extern sysarg_t sys_event_unmask(sysarg_t);
 
 #endif
Index: rnel/generic/include/ipc/event_types.h
===================================================================
--- kernel/generic/include/ipc/event_types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- * Copyright (c) 2009 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 KERN_EVENT_TYPES_H_
-#define KERN_EVENT_TYPES_H_
-
-typedef enum event_type {
-	/** New data available in kernel log */
-	EVENT_KLOG = 0,
-	/** Returning from kernel console to userspace */
-	EVENT_KCONSOLE,
-	/** A task/thread has faulted and will be terminated */
-	EVENT_FAULT,
-	EVENT_END
-} event_type_t;
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/ipc/ipc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,234 +36,11 @@
 #define KERN_IPC_H_
 
-/** Length of data being transfered with IPC call
- *
- * The uspace may not be able to utilize full length
- *
- */
-#define IPC_CALL_LEN  6
-
-/** Maximum active async calls per phone */
-#define IPC_MAX_ASYNC_CALLS  4
-
-/* Flags for calls */
-
-/** This is answer to a call */
-#define IPC_CALL_ANSWERED  (1 << 0)
-
-/** Answer will not be passed to userspace, will be discarded */
-#define IPC_CALL_DISCARD_ANSWER  (1 << 1)
-
-/** Call was forwarded */
-#define IPC_CALL_FORWARDED  (1 << 2)
-
-/** Identify connect_me_to answer */
-#define IPC_CALL_CONN_ME_TO  (1 << 3)
-
-/** Interrupt notification */
-#define IPC_CALL_NOTIF  (1 << 4)
-
-
-/** 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
-#define IPC_CALLRET_TEMPORARY  -2
-
-
-/* Macros for manipulating calling data */
-#define IPC_SET_RETVAL(data, retval)  ((data).args[0] = (retval))
-#define IPC_SET_IMETHOD(data, val)    ((data).args[0] = (val))
-#define IPC_SET_ARG1(data, val)       ((data).args[1] = (val))
-#define IPC_SET_ARG2(data, val)       ((data).args[2] = (val))
-#define IPC_SET_ARG3(data, val)       ((data).args[3] = (val))
-#define IPC_SET_ARG4(data, val)       ((data).args[4] = (val))
-#define IPC_SET_ARG5(data, val)       ((data).args[5] = (val))
-
-#define IPC_GET_IMETHOD(data)  ((data).args[0])
-#define IPC_GET_RETVAL(data)   ((data).args[0])
-
-#define IPC_GET_ARG1(data)  ((data).args[1])
-#define IPC_GET_ARG2(data)  ((data).args[2])
-#define IPC_GET_ARG3(data)  ((data).args[3])
-#define IPC_GET_ARG4(data)  ((data).args[4])
-#define IPC_GET_ARG5(data)  ((data).args[5])
-
-/* Well known phone descriptors */
-#define PHONE_NS  0
-
-/* Forwarding flags. */
-#define IPC_FF_NONE  0
-
-/**
- * The call will be routed as though it was initially sent via the phone used to
- * forward it. This feature is intended to support the situation in which the
- * forwarded call needs to be handled by the same connection fibril as any other
- * calls that were initially sent by the forwarder to the same destination. This
- * flag has no imapct on routing replies.
- *
- */
-#define IPC_FF_ROUTE_FROM_ME  (1 << 0)
-
-/** Kernel IPC interfaces
- *
- */
-#define IPC_IF_KERNEL  0
-
-/** System-specific methods - only through special syscalls
- *
- * These methods have special behaviour. These methods also
- * have the implicit kernel interface 0.
- *
- */
-
-/** Clone connection.
- *
- * The calling task clones one of its phones for the callee.
- *
- * - ARG1 - The caller sets ARG1 to the phone of the cloned connection.
- *        - The callee gets the new phone from ARG1.
- *
- * - on answer, the callee acknowledges the new connection by sending EOK back
- *   or the kernel closes it
- *
- */
-#define IPC_M_CONNECTION_CLONE  1
-
-/** Protocol for CONNECT - ME
- *
- * Through this call, the recipient learns about the new cloned connection. 
- *
- * - ARG5 - the kernel sets ARG5 to contain the hash of the used phone
- * - on asnwer, the callee acknowledges the new connection by sending EOK back
- *   or the kernel closes it
- *
- */
-#define IPC_M_CONNECT_ME  2
-
-/** Protocol for CONNECT - TO - ME
- *
- * Calling process asks the callee to create a callback connection,
- * so that it can start initiating new messages.
- *
- * The protocol for negotiating is:
- * - sys_connect_to_me - sends a message IPC_M_CONNECT_TO_ME
- * - recipient         - upon receipt tries to allocate new phone
- *                       - if it fails, responds with ELIMIT
- *                     - passes call to userspace. If userspace
- *                       responds with error, phone is deallocated and
- *                       error is sent back to caller. Otherwise 
- *                       the call is accepted and the response is sent back.
- *                     - the hash of the client task is passed to userspace
- *                       (on the receiving side) as ARG4 of the call.
- *                     - the hash of the allocated phone is passed to userspace
- *                       (on the receiving side) as ARG5 of the call.
- *
- */
-#define IPC_M_CONNECT_TO_ME  3
-
-/** Protocol for CONNECT - ME - TO
- *
- * Calling process asks the callee to create for him a new connection.
- * E.g. the caller wants a name server to connect him to print server.
- *
- * The protocol for negotiating is:
- * - sys_connect_me_to - send a synchronous message to name server
- *                       indicating that it wants to be connected to some
- *                       service
- *                     - arg1/2/3 are user specified, arg5 contains
- *                       address of the phone that should be connected
- *                       (TODO: it leaks to userspace)
- *  - recipient        -  if ipc_answer == 0, then accept connection
- *                     -  otherwise connection refused
- *                     -  recepient may forward message.
- *
- */
-#define IPC_M_CONNECT_ME_TO  4
-
-/** This message is sent to answerbox when the phone is hung up
- *
- */
-#define IPC_M_PHONE_HUNGUP  5
-
-/** Send as_area over IPC.
- * - ARG1 - source as_area base address
- * - ARG2 - size of source as_area (filled automatically by kernel)
- * - ARG3 - flags of the as_area being sent
- *
- * on answer, the recipient must set:
- * - ARG1 - dst as_area base adress
- *
- */
-#define IPC_M_SHARE_OUT  6
-
-/** Receive as_area over IPC.
- * - ARG1 - destination as_area base address
- * - ARG2 - destination as_area size
- * - ARG3 - user defined argument
- *
- * on answer, the recipient must set:
- *
- * - ARG1 - source as_area base address
- * - ARG2 - flags that will be used for sharing
- *
- */
-#define IPC_M_SHARE_IN  7
-
-/** Send data to another address space over IPC.
- * - ARG1 - source address space virtual address
- * - ARG2 - size of data to be copied, may be overriden by the recipient
- *
- * on answer, the recipient must set:
- *
- * - ARG1 - final destination address space virtual address
- * - ARG2 - final size of data to be copied
- *
- */
-#define IPC_M_DATA_WRITE  8
-
-/** Receive data from another address space over IPC.
- * - ARG1 - destination virtual address in the source address space
- * - ARG2 - size of data to be received, may be cropped by the recipient 
- *
- * on answer, the recipient must set:
- *
- * - ARG1 - source virtual address in the destination address space
- * - ARG2 - final size of data to be copied
- *
- */
-#define IPC_M_DATA_READ  9
-
-/** Debug the recipient.
- * - ARG1 - specifies the debug method (from udebug_method_t)
- * - other arguments are specific to the debug method
- *
- */
-#define IPC_M_DEBUG_ALL  10
-
-/* Well-known methods */
-#define IPC_M_LAST_SYSTEM  511
-#define IPC_M_PING         512
-
-/* User methods */
-#define IPC_FIRST_USER_METHOD  1024
-
-#ifdef KERNEL
-
-#define IPC_MAX_PHONES  32
-
+#include <abi/ipc/ipc.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
 #include <synch/waitq.h>
+#include <typedefs.h>
+
+#define IPC_MAX_PHONES  32
 
 struct answerbox;
@@ -303,24 +80,27 @@
 	
 	/** Phones connected to this answerbox. */
-	link_t connected_phones;
+	list_t connected_phones;
 	/** Received calls. */
-	link_t calls;
-	link_t dispatched_calls;  /* Should be hash table in the future */
+	list_t calls;
+	list_t dispatched_calls;  /* Should be hash table in the future */
 	
 	/** Answered calls. */
-	link_t answers;
+	list_t answers;
 	
 	IRQ_SPINLOCK_DECLARE(irq_lock);
 	
 	/** Notifications from IRQ handlers. */
-	link_t irq_notifs;
+	list_t irq_notifs;
 	/** IRQs with notifications to this answerbox. */
-	link_t irq_head;
+	list_t irq_list;
 } answerbox_t;
 
 typedef struct {
 	sysarg_t args[IPC_CALL_LEN];
-	/** Task which made or forwarded the call with IPC_FF_ROUTE_FROM_ME. */
-	struct task *task;
+	/**
+	 * Task which made or forwarded the call with IPC_FF_ROUTE_FROM_ME,
+	 * or the task which answered the call.
+	 */
+	task_id_t task_id;
 	/** Phone which made or last masqueraded this call. */
 	phone_t *phone;
@@ -380,9 +160,7 @@
 extern void ipc_backsend_err(phone_t *, call_t *, sysarg_t);
 extern void ipc_answerbox_slam_phones(answerbox_t *, bool);
-extern void ipc_cleanup_call_list(link_t *);
+extern void ipc_cleanup_call_list(list_t *);
 
 extern void ipc_print_task(task_id_t);
-
-#endif /* KERNEL */
 
 #endif
Index: kernel/generic/include/lib/elf.h
===================================================================
--- kernel/generic/include/lib/elf.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/lib/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,315 +36,7 @@
 #define KERN_ELF_H_
 
+#include <typedefs.h>
+#include <abi/elf.h>
 #include <arch/elf.h>
-#include <typedefs.h>
-
-/**
- * current ELF version
- */
-#define EV_CURRENT  1
-
-/**
- * ELF types
- */
-#define ET_NONE    0       /* No type */
-#define ET_REL     1       /* Relocatable file */
-#define ET_EXEC    2       /* Executable */
-#define ET_DYN     3       /* Shared object */
-#define ET_CORE    4       /* Core */
-#define ET_LOPROC  0xff00  /* Processor specific */
-#define ET_HIPROC  0xffff  /* Processor specific */
-
-/**
- * ELF machine types
- */
-#define EM_NO           0   /* No machine */
-#define EM_SPARC        2   /* SPARC */
-#define EM_386          3   /* i386 */
-#define EM_MIPS         8   /* MIPS RS3000 */
-#define EM_MIPS_RS3_LE  10  /* MIPS RS3000 LE */
-#define EM_PPC          20  /* PPC32 */
-#define EM_PPC64        21  /* PPC64 */
-#define EM_ARM          40  /* ARM */
-#define EM_SPARCV9      43  /* SPARC64 */
-#define EM_IA_64        50  /* IA-64 */
-#define EM_X86_64       62  /* AMD64/EMT64 */
-
-/**
- * ELF identification indexes
- */
-#define EI_MAG0        0
-#define EI_MAG1        1
-#define EI_MAG2        2
-#define EI_MAG3        3
-#define EI_CLASS       4   /* File class */
-#define EI_DATA        5   /* Data encoding */
-#define EI_VERSION     6   /* File version */
-#define EI_OSABI       7
-#define EI_ABIVERSION  8
-#define EI_PAD         9   /* Start of padding bytes */
-#define EI_NIDENT      16  /* ELF identification table size */
-
-/**
- * ELF magic number
- */
-#define ELFMAG0  0x7f
-#define ELFMAG1  'E'
-#define ELFMAG2  'L'
-#define ELFMAG3  'F'
-
-/**
- * ELF file classes
- */
-#define ELFCLASSNONE  0
-#define ELFCLASS32    1
-#define ELFCLASS64    2
-
-/**
- * ELF data encoding types
- */
-#define ELFDATANONE  0
-#define ELFDATA2LSB  1  /* Least significant byte first (little endian) */
-#define ELFDATA2MSB  2  /* Most signigicant byte first (big endian) */
-
-/**
- * ELF error return codes
- */
-#define EE_OK             0  /* No error */
-#define EE_INVALID        1  /* Invalid ELF image */
-#define EE_MEMORY         2  /* Cannot allocate address space */
-#define EE_INCOMPATIBLE   3  /* ELF image is not compatible with current architecture */
-#define EE_UNSUPPORTED    4  /* Non-supported ELF (e.g. dynamic ELFs) */
-#define EE_LOADER         5  /* The image is actually a program loader */
-#define EE_IRRECOVERABLE  6
-
-/**
- * ELF section types
- */
-#define SHT_NULL      0
-#define SHT_PROGBITS  1
-#define SHT_SYMTAB    2
-#define SHT_STRTAB    3
-#define SHT_RELA      4
-#define SHT_HASH      5
-#define SHT_DYNAMIC   6
-#define SHT_NOTE      7
-#define SHT_NOBITS    8
-#define SHT_REL       9
-#define SHT_SHLIB     10
-#define SHT_DYNSYM    11
-#define SHT_LOOS      0x60000000
-#define SHT_HIOS      0x6fffffff
-#define SHT_LOPROC    0x70000000
-#define SHT_HIPROC    0x7fffffff
-#define SHT_LOUSER    0x80000000
-#define SHT_HIUSER    0xffffffff
-
-/**
- * ELF section flags
- */
-#define SHF_WRITE      0x1
-#define SHF_ALLOC      0x2
-#define SHF_EXECINSTR  0x4
-#define SHF_TLS        0x400
-#define SHF_MASKPROC   0xf0000000
-
-/**
- * Symbol binding
- */
-#define STB_LOCAL   0
-#define STB_GLOBAL  1
-#define STB_WEAK    2
-#define STB_LOPROC  13
-#define STB_HIPROC  15
-
-/**
- * Symbol types
- */
-#define STT_NOTYPE   0
-#define STT_OBJECT   1
-#define STT_FUNC     2
-#define STT_SECTION  3
-#define STT_FILE     4
-#define STT_LOPROC   13
-#define STT_HIPROC   15
-
-/**
- * Program segment types
- */
-#define PT_NULL     0
-#define PT_LOAD     1
-#define PT_DYNAMIC  2
-#define PT_INTERP   3
-#define PT_NOTE     4
-#define PT_SHLIB    5
-#define PT_PHDR     6
-#define PT_LOPROC   0x70000000
-#define PT_HIPROC   0x7fffffff
-
-/**
- * Program segment attributes.
- */
-#define PF_X  1
-#define PF_W  2
-#define PF_R  4
-
-/**
- * ELF data types
- *
- * These types are found to be identical in both 32-bit and 64-bit
- * ELF object file specifications. They are the only types used
- * in ELF header.
- *
- */
-typedef uint64_t elf_xword;
-typedef int64_t elf_sxword;
-typedef uint32_t elf_word;
-typedef int32_t elf_sword;
-typedef uint16_t elf_half;
-
-/**
- * 32-bit ELF data types.
- *
- * These types are specific for 32-bit format.
- *
- */
-typedef uint32_t elf32_addr;
-typedef uint32_t elf32_off;
-
-/**
- * 64-bit ELF data types.
- *
- * These types are specific for 64-bit format.
- *
- */
-typedef uint64_t elf64_addr;
-typedef uint64_t elf64_off;
-
-/** ELF header */
-struct elf32_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf32_addr e_entry;
-	elf32_off e_phoff;
-	elf32_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-
-struct elf64_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf64_addr e_entry;
-	elf64_off e_phoff;
-	elf64_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-
-/**
- * ELF segment header.
- * Segments headers are also known as program headers.
- */
-struct elf32_segment_header {
-	elf_word p_type;
-	elf32_off p_offset;
-	elf32_addr p_vaddr;
-	elf32_addr p_paddr;
-	elf_word p_filesz;
-	elf_word p_memsz;
-	elf_word p_flags;
-	elf_word p_align;
-};
-
-struct elf64_segment_header {
-	elf_word p_type;
-	elf_word p_flags;
-	elf64_off p_offset;
-	elf64_addr p_vaddr;
-	elf64_addr p_paddr;
-	elf_xword p_filesz;
-	elf_xword p_memsz;
-	elf_xword p_align;
-};
-
-/**
- * ELF section header
- */
-struct elf32_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_word sh_flags;
-	elf32_addr sh_addr;
-	elf32_off sh_offset;
-	elf_word sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_word sh_addralign;
-	elf_word sh_entsize;
-};
-
-struct elf64_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_xword sh_flags;
-	elf64_addr sh_addr;
-	elf64_off sh_offset;
-	elf_xword sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_xword sh_addralign;
-	elf_xword sh_entsize;
-};
-
-/**
- * ELF symbol table entry
- */
-struct elf32_symbol {
-	elf_word st_name;
-	elf32_addr st_value;
-	elf_word st_size;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-};
-
-struct elf64_symbol {
-	elf_word st_name;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-	elf64_addr st_value;
-	elf_xword st_size;
-};
-
-#ifdef __32_BITS__
-typedef struct elf32_header elf_header_t;
-typedef struct elf32_segment_header elf_segment_header_t;
-typedef struct elf32_section_header elf_section_header_t;
-typedef struct elf32_symbol elf_symbol_t;
-#endif
-
-#ifdef __64_BITS__
-typedef struct elf64_header elf_header_t;
-typedef struct elf64_segment_header elf_segment_header_t;
-typedef struct elf64_section_header elf_section_header_t;
-typedef struct elf64_symbol elf_symbol_t;
-#endif
-
-extern const char *elf_error(unsigned int rc);
 
 /** Interpreter string used to recognize the program loader */
Index: kernel/generic/include/lib/elf_load.h
===================================================================
--- kernel/generic/include/lib/elf_load.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/generic/include/lib/elf_load.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * 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 KERN_ELF_LOAD_H_
+#define KERN_ELF_LOAD_H_
+
+#include <arch/elf.h>
+#include <typedefs.h>
+
+/**
+ * ELF error return codes
+ */
+#define EE_OK			0	/* No error */
+#define EE_INVALID		1	/* Invalid ELF image */
+#define	EE_MEMORY		2	/* Cannot allocate address space */
+#define EE_INCOMPATIBLE		3	/* ELF image is not compatible with current architecture */
+#define EE_UNSUPPORTED		4	/* Non-supported ELF (e.g. dynamic ELFs) */
+#define EE_LOADER		5	/* The image is actually a program loader. */
+#define EE_IRRECOVERABLE	6
+
+/**
+ * This flags is passed when running the loader, otherwise elf_load()
+ * would return with a EE_LOADER error code.
+ *
+ */
+#define ELD_F_NONE    0
+#define ELD_F_LOADER  1
+
+extern unsigned int elf_load(elf_header_t *, as_t *, unsigned int);
+extern const char *elf_error(unsigned int rc);
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/include/lib/memfnc.h
===================================================================
--- kernel/generic/include/lib/memfnc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/generic/include/lib/memfnc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_LIB_MEMFNC_H_
+#define KERN_LIB_MEMFNC_H_
+
+#include <typedefs.h>
+
+extern void *memset(void *, int, size_t);
+extern void *memcpy(void *, const void *, size_t);
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/include/macros.h
===================================================================
--- kernel/generic/include/macros.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/macros.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -95,9 +95,6 @@
 	overlaps(KA2PA((x)), (szx), KA2PA((y)), (szy))
 
-#define SIZE2KB(size)  ((size) >> 10)
-#define SIZE2MB(size)  ((size) >> 20)
-
-#define KB2SIZE(kb)  ((kb) << 10)
-#define MB2SIZE(mb)  ((mb) << 20)
+#define KiB2SIZE(kb)  ((kb) << 10)
+#define MiB2SIZE(mb)  ((mb) << 20)
 
 #define STRING(arg)      STRING_ARG(arg)
Index: kernel/generic/include/memstr.h
===================================================================
--- kernel/generic/include/memstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/memstr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,13 +37,11 @@
 
 #include <typedefs.h>
-#include <arch/memstr.h>
 
-/*
- * Architecture independent variants.
- */
-extern void *_memcpy(void *dst, const void *src, size_t cnt);
-extern void _memsetb(void *dst, size_t cnt, uint8_t x);
-extern void _memsetw(void *dst, size_t cnt, uint16_t x);
-extern void *memmove(void *dst, const void *src, size_t cnt);
+#define memset(dst, val, cnt)  __builtin_memset((dst), (val), (cnt))
+#define memcpy(dst, src, cnt)  __builtin_memcpy((dst), (src), (cnt))
+
+extern void memsetb(void *, size_t, uint8_t);
+extern void memsetw(void *, size_t, uint16_t);
+extern void *memmove(void *, const void *, size_t);
 
 #endif
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/mm/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,33 +36,10 @@
 #define KERN_AS_H_
 
-#ifdef KERNEL
-	#include <typedefs.h>
-#else
-	#include <sys/types.h>
-#endif
-
-/** Address space area flags. */
-#define AS_AREA_READ       1
-#define AS_AREA_WRITE      2
-#define AS_AREA_EXEC       4
-#define AS_AREA_CACHEABLE  8
-
-/** Address space area info exported to userspace. */
-typedef struct {
-	/** Starting address */
-	uintptr_t start_addr;
-	
-	/** Area size */
-	size_t size;
-	
-	/** Area flags */
-	unsigned int flags;
-} as_area_info_t;
-
-#ifdef KERNEL
-
+#include <typedefs.h>
+#include <abi/mm/as.h>
 #include <arch/mm/page.h>
 #include <arch/mm/as.h>
 #include <arch/mm/asid.h>
+#include <arch/istate.h>
 #include <typedefs.h>
 #include <synch/spinlock.h>
@@ -84,5 +61,9 @@
 #define USER_ADDRESS_SPACE_END      USER_ADDRESS_SPACE_END_ARCH
 
-#define USTACK_ADDRESS  USTACK_ADDRESS_ARCH
+#ifdef USTACK_ADDRESS_ARCH
+	#define USTACK_ADDRESS  USTACK_ADDRESS_ARCH
+#else
+	#define USTACK_ADDRESS  (USER_ADDRESS_SPACE_END - (STACK_SIZE - 1))
+#endif
 
 /** Kernel address space. */
@@ -238,7 +219,11 @@
 /** Address space area backend structure. */
 typedef struct mem_backend {
+	bool (* create)(as_area_t *);
+	bool (* resize)(as_area_t *, size_t);
+	void (* share)(as_area_t *);
+	void (* destroy)(as_area_t *);
+
 	int (* page_fault)(as_area_t *, uintptr_t, pf_access_t);
 	void (* frame_free)(as_area_t *, uintptr_t, uintptr_t);
-	void (* share)(as_area_t *);
 } mem_backend_t;
 
@@ -246,5 +231,5 @@
 
 extern as_operations_t *as_operations;
-extern link_t inactive_as_with_asid_head;
+extern list_t inactive_as_with_asid_list;
 
 extern void as_init(void);
@@ -298,14 +283,4 @@
 extern mem_backend_t phys_backend;
 
-/**
- * This flags is passed when running the loader, otherwise elf_load()
- * would return with a EE_LOADER error code.
- *
- */
-#define ELD_F_NONE    0
-#define ELD_F_LOADER  1
-
-extern unsigned int elf_load(elf_header_t *, as_t *, unsigned int);
-
 /* Address space area related syscalls. */
 extern sysarg_t sys_as_area_create(uintptr_t, size_t, unsigned int);
@@ -319,6 +294,4 @@
 extern void as_print(as_t *);
 
-#endif /* KERNEL */
-
 #endif
 
Index: kernel/generic/include/mm/buddy.h
===================================================================
--- kernel/generic/include/mm/buddy.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/mm/buddy.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -72,5 +72,5 @@
 	/** Maximal order of block which can be stored by buddy system. */
 	uint8_t max_order;
-	link_t *order;
+	list_t *order;
 	buddy_system_operations_t *op;
 	/** Pointer to be used by the implementation. */
Index: kernel/generic/include/mm/frame.h
===================================================================
--- kernel/generic/include/mm/frame.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/mm/frame.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,15 +45,4 @@
 #include <arch/mm/frame.h>
 
-#define ONE_FRAME    0
-#define TWO_FRAMES   1
-#define FOUR_FRAMES  2
-
-
-#ifdef ARCH_STACK_FRAMES
-	#define STACK_FRAMES  ARCH_STACK_FRAMES
-#else
-	#define STACK_FRAMES  ONE_FRAME
-#endif
-
 /** Maximum number of zones in the system. */
 #define ZONES_MAX  32
@@ -62,16 +51,18 @@
 
 /** Convert the frame address to kernel VA. */
-#define FRAME_KA          0x01
+#define FRAME_KA          0x1
 /** Do not panic and do not sleep on failure. */
-#define FRAME_ATOMIC      0x02
+#define FRAME_ATOMIC      0x2
 /** Do not start reclaiming when no free memory. */
-#define FRAME_NO_RECLAIM  0x04
+#define FRAME_NO_RECLAIM  0x4
+/** Do not reserve / unreserve memory. */
+#define FRAME_NO_RESERVE  0x8
 
 typedef uint8_t zone_flags_t;
 
 /** Available zone (free for allocation) */
-#define ZONE_AVAILABLE  0x00
+#define ZONE_AVAILABLE  0x0
 /** Zone is reserved (not available for allocation) */
-#define ZONE_RESERVED   0x08
+#define ZONE_RESERVED   0x8
 /** Zone is used by firmware (not available for allocation) */
 #define ZONE_FIRMWARE   0x10
@@ -85,5 +76,5 @@
 	uint8_t buddy_order;  /**< Buddy system block order */
 	link_t buddy_link;    /**< Link to the next free block inside
-                               one order */
+                                   one order */
 	void *parent;         /**< If allocated by slab, this points there */
 } frame_t;
@@ -91,14 +82,14 @@
 typedef struct {
 	pfn_t base;                    /**< Frame_no of the first frame
-                                        in the frames array */
+                                            in the frames array */
 	size_t count;                  /**< Size of zone */
 	size_t free_count;             /**< Number of free frame_t
-                                        structures */
+                                            structures */
 	size_t busy_count;             /**< Number of busy frame_t
-                                        structures */
+                                            structures */
 	zone_flags_t flags;            /**< Type of the zone */
 	
 	frame_t *frames;               /**< Array of frame_t structures
-                                        in this zone */
+                                            in this zone */
 	buddy_system_t *buddy_system;  /**< Buddy system for the zone */
 } zone_t;
@@ -146,21 +137,23 @@
     ((~(((sysarg_t) -1) << (order)) & (index)) == 0)
 #define IS_BUDDY_LEFT_BLOCK(zone, frame) \
-    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
+    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
 #define IS_BUDDY_RIGHT_BLOCK(zone, frame) \
-    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
+    (((frame_index((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
 #define IS_BUDDY_LEFT_BLOCK_ABS(zone, frame) \
-    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 0)
+    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 0)
 #define IS_BUDDY_RIGHT_BLOCK_ABS(zone, frame) \
-    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x01) == 1)
-
-#define frame_alloc(order, flags) \
-    frame_alloc_generic(order, flags, NULL)
+    (((frame_index_abs((zone), (frame)) >> (frame)->buddy_order) & 0x1) == 1)
 
 extern void frame_init(void);
 extern void *frame_alloc_generic(uint8_t, frame_flags_t, size_t *);
+extern void *frame_alloc(uint8_t, frame_flags_t);
+extern void *frame_alloc_noreserve(uint8_t, frame_flags_t);
+extern void frame_free_generic(uintptr_t, frame_flags_t);
 extern void frame_free(uintptr_t);
+extern void frame_free_noreserve(uintptr_t);
 extern void frame_reference_add(pfn_t);
+extern size_t frame_total_free_get(void);
 
-extern size_t find_zone(pfn_t frame, size_t count, size_t hint);
+extern size_t find_zone(pfn_t, size_t, size_t);
 extern size_t zone_create(pfn_t, size_t, pfn_t, zone_flags_t);
 extern void *frame_get_parent(pfn_t, size_t);
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/mm/page.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,6 +37,10 @@
 
 #include <typedefs.h>
+#include <proc/task.h>
 #include <mm/as.h>
-#include <memstr.h>
+#include <arch/mm/page.h>
+
+#define P2SZ(pages) \
+	((pages) << PAGE_WIDTH)	
 
 /** Operations to manipulate page mappings. */
@@ -44,5 +48,5 @@
 	void (* mapping_insert)(as_t *, uintptr_t, uintptr_t, unsigned int);
 	void (* mapping_remove)(as_t *, uintptr_t);
-	pte_t *(* mapping_find)(as_t *, uintptr_t);
+	pte_t *(* mapping_find)(as_t *, uintptr_t, bool);
 } page_mapping_operations_t;
 
@@ -55,5 +59,5 @@
 extern void page_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
 extern void page_mapping_remove(as_t *, uintptr_t);
-extern pte_t *page_mapping_find(as_t *, uintptr_t);
+extern pte_t *page_mapping_find(as_t *, uintptr_t, bool);
 extern pte_t *page_table_create(unsigned int);
 extern void page_table_destroy(pte_t *);
@@ -62,4 +66,6 @@
 extern uintptr_t hw_map(uintptr_t, size_t);
 
+extern sysarg_t sys_page_find_mapping(uintptr_t, uintptr_t *);
+
 #endif
 
Index: kernel/generic/include/mm/reserve.h
===================================================================
--- kernel/generic/include/mm/reserve.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/generic/include/mm/reserve.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genericmm
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_RESERVE_H_
+#define KERN_RESERVE_H_
+
+#include <typedefs.h>
+
+extern void reserve_init(void);
+extern bool reserve_try_alloc(size_t);
+extern void reserve_force_alloc(size_t);
+extern void reserve_free(size_t);
+
+#endif
+
+/** @}
+ */
Index: kernel/generic/include/mm/slab.h
===================================================================
--- kernel/generic/include/mm/slab.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/mm/slab.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -111,9 +111,9 @@
 	
 	/* Slabs */
-	link_t full_slabs;     /**< List of full slabs */
-	link_t partial_slabs;  /**< List of partial slabs */
+	list_t full_slabs;     /**< List of full slabs */
+	list_t partial_slabs;  /**< List of partial slabs */
 	SPINLOCK_DECLARE(slablock);
 	/* Magazines */
-	link_t magazines;  /**< List o full magazines */
+	list_t magazines;  /**< List o full magazines */
 	SPINLOCK_DECLARE(maglock);
 	
Index: kernel/generic/include/mm/tlb.h
===================================================================
--- kernel/generic/include/mm/tlb.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/mm/tlb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -86,4 +86,5 @@
 extern void tlb_invalidate_asid(asid_t);
 extern void tlb_invalidate_pages(asid_t, uintptr_t, size_t);
+
 #endif
 
Index: kernel/generic/include/panic.h
===================================================================
--- kernel/generic/include/panic.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/panic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -60,5 +60,5 @@
 struct istate;
 
-extern bool silent;
+extern bool console_override;
 
 extern void panic_common(panic_category_t, struct istate *, int,
Index: kernel/generic/include/proc/scheduler.h
===================================================================
--- kernel/generic/include/proc/scheduler.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/proc/scheduler.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -48,6 +48,6 @@
 typedef struct {
 	IRQ_SPINLOCK_DECLARE(lock);
-	link_t rq_head;              /**< List of ready threads. */
-	size_t n;                    /**< Number of threads in rq_ready. */
+	list_t rq;			/**< List of ready threads. */
+	size_t n;			/**< Number of threads in rq_ready. */
 } runq_t;
 
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/proc/task.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,6 @@
 #include <cpu.h>
 #include <ipc/ipc.h>
+#include <ipc/event.h>
+#include <ipc/kbox.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
@@ -53,7 +55,6 @@
 #include <proc/scheduler.h>
 #include <udebug/udebug.h>
-#include <ipc/kbox.h>
 #include <mm/as.h>
-#include <sysinfo/abi.h>
+#include <abi/sysinfo.h>
 
 struct thread;
@@ -73,11 +74,11 @@
 	char name[TASK_NAME_BUFLEN];
 	/** List of threads contained in this task. */
-	link_t th_head;
+	list_t threads;
 	/** Address space. */
 	as_t *as;
 	/** Unique identity of task. */
 	task_id_t taskid;
-	/** Task security context. */
-	context_id_t context;
+	/** Task security container. */
+	container_id_t container;
 	
 	/** Number of references (i.e. threads). */
@@ -93,6 +94,6 @@
 	phone_t phones[IPC_MAX_PHONES];
 	stats_ipc_t ipc_info;   /**< IPC statistics */
-	/** List of synchronous answerboxes. */
-	link_t sync_box_head;
+	list_t sync_boxes;      /**< List of synchronous answerboxes. */
+	event_t events[EVENT_TASK_END - EVENT_END];
 	
 #ifdef CONFIG_UDEBUG
Index: rnel/generic/include/proc/tasklet.h
===================================================================
--- kernel/generic/include/proc/tasklet.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * Copyright (c) 2007 Jan Hudecek
- * 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.
- */
-
-/** @addtogroup genericproc
- * @{
- */
-/** @file tasklet.h
- * @brief Tasklets declarations
- */
-
-#ifndef KERN_TASKLET_H_
-#define KERN_TASKLET_H_
-
-#include <adt/list.h>
-
-/** Tasklet callback type */
-typedef void (* tasklet_callback_t)(void *arg);
-
-/** Tasklet state */
-typedef enum {
-	NotActive,
-	Scheduled,
-	InProgress,
-	Disabled
-} tasklet_state_t;
-
-/** Structure describing a tasklet */
-typedef struct tasklet_descriptor {
-	link_t link;
-	
-	/** Callback to call */
-	tasklet_callback_t callback;
-	
-	/** Argument passed to the callback */
-	void *arg;
-	
-	/** State of the tasklet */
-	tasklet_state_t state;
-} tasklet_descriptor_t;
-
-
-extern void tasklet_init(void);
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/proc/thread.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,9 +45,8 @@
 #include <arch/cpu.h>
 #include <mm/tlb.h>
-#include <proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <udebug/udebug.h>
-#include <sysinfo/abi.h>
-
-#define THREAD_STACK_SIZE   STACK_SIZE
+#include <abi/sysinfo.h>
+
 #define THREAD_NAME_BUFLEN  20
 
@@ -157,4 +156,7 @@
 	int fpu_context_engaged;
 	
+	/* The thread will not be migrated if nomigrate is non-zero. */
+	int nomigrate;
+	
 	/** Thread's state. */
 	state_t state;
@@ -246,4 +248,7 @@
 extern bool thread_exists(thread_t *);
 
+extern void thread_migration_disable(void);
+extern void thread_migration_enable(void);
+
 #ifdef CONFIG_UDEBUG
 extern void thread_stack_trace(thread_id_t);
@@ -259,4 +264,5 @@
 extern sysarg_t sys_thread_get_id(thread_id_t *);
 extern sysarg_t sys_thread_usleep(uint32_t);
+extern sysarg_t sys_thread_udelay(uint32_t);
 
 #endif
Index: rnel/generic/include/proc/uarg.h
===================================================================
--- kernel/generic/include/proc/uarg.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2006 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 genericproc
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_UARG_H_
-#define KERN_UARG_H_
-
-/** Structure passed to uinit kernel thread as argument. */
-typedef struct uspace_arg {
-	void *uspace_entry;
-	void *uspace_stack;
-
-	void (* uspace_thread_function)();
-	void *uspace_thread_arg;
-	
-	struct uspace_arg *uspace_uarg;
-} uspace_arg_t;
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/str.h
===================================================================
--- kernel/generic/include/str.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/str.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -99,5 +99,6 @@
 extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *);
 
-extern void order_suffix(const uint64_t val, uint64_t *rv, char *suffix);
+extern void order_suffix(const uint64_t, uint64_t *, char *);
+extern void bin_order_suffix(const uint64_t, uint64_t *, const char **, bool);
 
 #endif
Index: kernel/generic/include/synch/condvar.h
===================================================================
--- kernel/generic/include/synch/condvar.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/synch/condvar.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,5 @@
 #include <synch/waitq.h>
 #include <synch/mutex.h>
-#include <synch/synch.h>
+#include <abi/synch.h>
 
 typedef struct {
Index: kernel/generic/include/synch/mutex.h
===================================================================
--- kernel/generic/include/synch/mutex.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/synch/mutex.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 #include <typedefs.h>
 #include <synch/semaphore.h>
-#include <synch/synch.h>
+#include <abi/synch.h>
 
 typedef enum {
Index: kernel/generic/include/synch/semaphore.h
===================================================================
--- kernel/generic/include/synch/semaphore.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/synch/semaphore.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 #include <typedefs.h>
 #include <synch/waitq.h>
-#include <synch/synch.h>
+#include <abi/synch.h>
 
 typedef struct {
Index: rnel/generic/include/synch/synch.h
===================================================================
--- kernel/generic/include/synch/synch.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * Copyright (c) 2001-2004 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 sync
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_SYNCH_H_
-#define KERN_SYNCH_H_
-
-/** Request with no timeout. */
-#define SYNCH_NO_TIMEOUT	0
-
-/** No flags specified. */
-#define SYNCH_FLAGS_NONE		0
-/** Non-blocking operation request. */
-#define SYNCH_FLAGS_NON_BLOCKING	(1 << 0)
-/** Interruptible operation. */
-#define SYNCH_FLAGS_INTERRUPTIBLE	(1 << 1)
-
-/** Could not satisfy the request without going to sleep. */
-#define ESYNCH_WOULD_BLOCK	1
-/** Timeout occurred. */
-#define ESYNCH_TIMEOUT		2
-/** Sleep was interrupted. */
-#define ESYNCH_INTERRUPTED	4
-/** Operation succeeded without sleeping. */
-#define ESYNCH_OK_ATOMIC	8
-/** Operation succeeded and did sleep. */
-#define ESYNCH_OK_BLOCKED	16
-
-#define SYNCH_FAILED(rc) \
-	((rc) & (ESYNCH_WOULD_BLOCK | ESYNCH_TIMEOUT | ESYNCH_INTERRUPTED))
-#define SYNCH_OK(rc) \
-	((rc) & (ESYNCH_OK_ATOMIC | ESYNCH_OK_BLOCKED))
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/synch/waitq.h
===================================================================
--- kernel/generic/include/synch/waitq.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/synch/waitq.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 #include <typedefs.h>
 #include <synch/spinlock.h>
-#include <synch/synch.h>
+#include <abi/synch.h>
 #include <adt/list.h>
 
@@ -62,6 +62,6 @@
 	int missed_wakeups;
 	
-	/** List of sleeping threads for wich there was no missed_wakeup. */
-	link_t head;
+	/** List of sleeping threads for which there was no missed_wakeup. */
+	list_t sleepers;
 } waitq_t;
 
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/syscall/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,67 +36,6 @@
 #define KERN_SYSCALL_H_
 
-typedef enum {
-	SYS_KLOG = 0,
-	SYS_TLS_SET = 1,  /* Hardcoded for AMD64, IA-32 (fibril.S in uspace) */
-	
-	SYS_THREAD_CREATE,
-	SYS_THREAD_EXIT,
-	SYS_THREAD_GET_ID,
-	SYS_THREAD_USLEEP,
-	
-	SYS_TASK_GET_ID,
-	SYS_TASK_SET_NAME,
-	SYS_TASK_KILL,
-	SYS_TASK_EXIT,
-	SYS_PROGRAM_SPAWN_LOADER,
-	
-	SYS_FUTEX_SLEEP,
-	SYS_FUTEX_WAKEUP,
-	SYS_SMC_COHERENCE,
-	
-	SYS_AS_AREA_CREATE,
-	SYS_AS_AREA_RESIZE,
-	SYS_AS_AREA_CHANGE_FLAGS,
-	SYS_AS_AREA_DESTROY,
-	SYS_AS_GET_UNMAPPED_AREA,
-	
-	SYS_IPC_CALL_SYNC_FAST,
-	SYS_IPC_CALL_SYNC_SLOW,
-	SYS_IPC_CALL_ASYNC_FAST,
-	SYS_IPC_CALL_ASYNC_SLOW,
-	SYS_IPC_ANSWER_FAST,
-	SYS_IPC_ANSWER_SLOW,
-	SYS_IPC_FORWARD_FAST,
-	SYS_IPC_FORWARD_SLOW,
-	SYS_IPC_WAIT,
-	SYS_IPC_POKE,
-	SYS_IPC_HANGUP,
-	SYS_IPC_CONNECT_KBOX,
-	
-	SYS_EVENT_SUBSCRIBE,
-	
-	SYS_CAP_GRANT,
-	SYS_CAP_REVOKE,
-	
-	SYS_DEVICE_ASSIGN_DEVNO,
-	SYS_PHYSMEM_MAP,
-	SYS_IOSPACE_ENABLE,
-	SYS_REGISTER_IRQ,
-	SYS_UNREGISTER_IRQ,
-	
-	SYS_SYSINFO_GET_TAG,
-	SYS_SYSINFO_GET_VALUE,
-	SYS_SYSINFO_GET_DATA_SIZE,
-	SYS_SYSINFO_GET_DATA,
-	
-	SYS_DEBUG_ENABLE_CONSOLE,
-	SYS_DEBUG_DISABLE_CONSOLE,
-	
-	SYSCALL_END
-} syscall_t;
-
-#ifdef KERNEL
-
 #include <typedefs.h>
+#include <abi/syscall.h>
 
 typedef sysarg_t (*syshandler_t)(sysarg_t, sysarg_t, sysarg_t, sysarg_t,
@@ -110,6 +49,4 @@
 #endif
 
-#endif
-
 /** @}
  */
Index: rnel/generic/include/sysinfo/abi.h
===================================================================
--- kernel/generic/include/sysinfo/abi.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,144 +1,0 @@
-/*
- * Copyright (c) 2010 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.
- */
-
-/** @addtogroup generic
- * @{
- */
-/** @file
- * Data structures passed between kernel sysinfo and user space.
- */
-
-#ifndef KERN_ABI_H_
-#define KERN_ABI_H_
-
-/** Number of load components */
-#define LOAD_STEPS  3
-
-/** Maximum name sizes */
-#define TASK_NAME_BUFLEN  20
-#define EXC_NAME_BUFLEN   20
-
-/** Thread states */
-typedef enum {
-	/** It is an error, if thread is found in this state. */
-	Invalid,
-	/** State of a thread that is currently executing on some CPU. */
-	Running,
-	/** Thread in this state is waiting for an event. */
-	Sleeping,
-	/** State of threads in a run queue. */
-	Ready,
-	/** Threads are in this state before they are first readied. */
-	Entering,
-	/** After a thread calls thread_exit(), it is put into Exiting state. */
-	Exiting,
-	/** Threads that were not detached but exited are Lingering. */
-	Lingering
-} state_t;
-
-/** Statistics about a single CPU
- *
- */
-typedef struct {
-	unsigned int id;         /**< CPU ID as stored by kernel */
-	bool active;             /**< CPU is activate */
-	uint16_t frequency_mhz;  /**< Frequency in MHz */
-	uint64_t idle_cycles;    /**< Number of idle cycles */
-	uint64_t busy_cycles;    /**< Number of busy cycles */
-} stats_cpu_t;
-
-/** Physical memory statistics
- *
- */
-typedef struct {
-	uint64_t total;    /**< Total physical memory (bytes) */
-	uint64_t unavail;  /**< Unavailable (reserved, firmware) bytes */
-	uint64_t used;     /**< Allocated physical memory (bytes) */
-	uint64_t free;     /**< Free physical memory (bytes) */
-} stats_physmem_t;
-
-/** IPC statistics
- *
- * Associated with a task.
- *
- */
-typedef struct {
-	uint64_t call_sent;           /**< IPC calls sent */
-	uint64_t call_received;       /**< IPC calls received */
-	uint64_t answer_sent;         /**< IPC answers sent */
-	uint64_t answer_received;     /**< IPC answers received */
-	uint64_t irq_notif_received;  /**< IPC IRQ notifications */
-	uint64_t forwarded;           /**< IPC messages forwarded */
-} stats_ipc_t;
-
-/** Statistics about a single task
- *
- */
-typedef struct {
-	task_id_t task_id;            /**< Task ID */
-	char name[TASK_NAME_BUFLEN];  /**< Task name (in kernel) */
-	size_t virtmem;               /**< Size of VAS (bytes) */
-	size_t resmem;                /**< Size of resident (used) memory (bytes) */
-	size_t threads;               /**< Number of threads */
-	uint64_t ucycles;             /**< Number of CPU cycles in user space */
-	uint64_t kcycles;             /**< Number of CPU cycles in kernel */
-	stats_ipc_t ipc_info;         /**< IPC statistics */
-} stats_task_t;
-
-/** Statistics about a single thread
- *
- */
-typedef struct {
-	thread_id_t thread_id;  /**< Thread ID */
-	task_id_t task_id;      /**< Associated task ID */
-	state_t state;          /**< Thread state */
-	int priority;           /**< Thread priority */
-	uint64_t ucycles;       /**< Number of CPU cycles in user space */
-	uint64_t kcycles;       /**< Number of CPU cycles in kernel */
-	bool on_cpu;            /**< Associated with a CPU */
-	unsigned int cpu;       /**< Associated CPU ID (if on_cpu is true) */
-} stats_thread_t;
-
-/** Statistics about a single exception
- *
- */
-typedef struct {
-	unsigned int id;             /**< Exception ID */
-	char desc[EXC_NAME_BUFLEN];  /**< Description */
-	bool hot;                    /**< Active or inactive exception */
-	uint64_t cycles;             /**< Number of CPU cycles in the handler */
-	uint64_t count;              /**< Number of handled exceptions */
-} stats_exc_t;
-
-/** Load fixed-point value */
-typedef uint32_t load_t;
-
-#endif
-
-/** @}
- */
Index: kernel/generic/include/typedefs.h
===================================================================
--- kernel/generic/include/typedefs.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/typedefs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -64,5 +64,5 @@
 typedef uint64_t thread_id_t;
 typedef uint64_t task_id_t;
-typedef uint32_t context_id_t;
+typedef uint32_t container_id_t;
 
 typedef int32_t inr_t;
Index: kernel/generic/include/udebug/udebug.h
===================================================================
--- kernel/generic/include/udebug/udebug.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/include/udebug/udebug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,149 +36,5 @@
 #define KERN_UDEBUG_H_
 
-#define UDEBUG_EVMASK(event)  (1 << ((event) - 1))
-
-typedef enum { /* udebug_method_t */
-	
-	/** Start debugging the recipient.
-	 *
-	 * Causes all threads in the receiving task to stop. When they
-	 * are all stoped, an answer with retval 0 is generated.
-	 *
-	 */
-	UDEBUG_M_BEGIN = 1,
-	
-	/** Finish debugging the recipient.
-	 *
-	 * Answers all pending GO and GUARD messages.
-	 *
-	 */
-	UDEBUG_M_END,
-	
-	/** Set which events should be captured. */
-	UDEBUG_M_SET_EVMASK,
-	
-	/** Make sure the debugged task is still there.
-	 *
-	 * This message is answered when the debugged task dies
-	 * or the debugging session ends.
-	 *
-	 */
-	UDEBUG_M_GUARD,
-	
-	/** Run a thread until a debugging event occurs.
-	 *
-	 * This message is answered when the thread stops
-	 * in a debugging event.
-	 *
-	 * - ARG2 - id of the thread to run
-	 *
-	 */
-	UDEBUG_M_GO,
-	
-	/** Stop a thread being debugged.
-	 *
-	 * Creates a special STOP event in the thread, causing
-	 * it to answer a pending GO message (if any).
-	 *
-	 */
-	UDEBUG_M_STOP,
-	
-	/** Read arguments of a syscall.
-	 *
-	 * - ARG2 - thread identification
-	 * - ARG3 - destination address in the caller's address space
-	 *
-	 */
-	UDEBUG_M_ARGS_READ,
-	
-	/** Read thread's userspace register state (istate_t).
-	 *
-	 * - ARG2 - thread identification
-	 * - ARG3 - destination address in the caller's address space
-	 *
-	 * or, on error, retval will be
-	 * - ENOENT - thread does not exist
-	 * - EBUSY - register state not available
-	 */
-	UDEBUG_M_REGS_READ,
-	
-	/** Read the list of the debugged tasks's threads.
-	 *
-	 * - ARG2 - destination address in the caller's address space
-	 * - ARG3 - size of receiving buffer in bytes
-	 *
-	 * The kernel fills the buffer with a series of sysarg_t values
-	 * (thread ids). On answer, the kernel will set:
-	 *
-	 * - ARG2 - number of bytes that were actually copied
-	 * - ARG3 - number of bytes of the complete data
-	 *
-	 */
-	UDEBUG_M_THREAD_READ,
-	
-	/** Read the name of the debugged task.
-	 *
-	 * - ARG2 - destination address in the caller's address space
-	 * - ARG3 - size of receiving buffer in bytes
-	 *
-	 * The kernel fills the buffer with a non-terminated string.
-	 *
-	 * - ARG2 - number of bytes that were actually copied
-	 * - ARG3 - number of bytes of the complete data
-	 *
-	 */
-	UDEBUG_M_NAME_READ,
-	
-	/** Read the list of the debugged task's address space areas.
-	 *
-	 * - ARG2 - destination address in the caller's address space
-	 * - ARG3 - size of receiving buffer in bytes
-	 *
-	 * The kernel fills the buffer with a series of as_area_info_t structures.
-	 * Upon answer, the kernel will set:
-	 *
-	 * - ARG2 - number of bytes that were actually copied
-	 * - ARG3 - number of bytes of the complete data
-	 *
-	 */
-	UDEBUG_M_AREAS_READ,
-	
-	/** Read the debugged tasks's memory.
-	 *
-	 * - ARG2 - destination address in the caller's address space
-	 * - ARG3 - source address in the recipient's address space
-	 * - ARG4 - size of receiving buffer in bytes
-	 *
-	 */
-	UDEBUG_M_MEM_READ
-} udebug_method_t;
-
-typedef enum {
-	UDEBUG_EVENT_FINISHED = 1,  /**< Debuging session has finished */
-	UDEBUG_EVENT_STOP,          /**< Stopped on DEBUG_STOP request */
-	UDEBUG_EVENT_SYSCALL_B,     /**< Before beginning syscall execution */
-	UDEBUG_EVENT_SYSCALL_E,     /**< After finishing syscall execution */
-	UDEBUG_EVENT_THREAD_B,      /**< The task created a new thread */
-	UDEBUG_EVENT_THREAD_E       /**< A thread exited */
-} udebug_event_t;
-
-typedef enum {
-	UDEBUG_EM_FINISHED = UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED),
-	UDEBUG_EM_STOP = UDEBUG_EVMASK(UDEBUG_EVENT_STOP),
-	UDEBUG_EM_SYSCALL_B = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B),
-	UDEBUG_EM_SYSCALL_E = UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E),
-	UDEBUG_EM_THREAD_B = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B),
-	UDEBUG_EM_THREAD_E = UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E),
-	UDEBUG_EM_ALL =
-	    (UDEBUG_EVMASK(UDEBUG_EVENT_FINISHED) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_STOP) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_B) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_SYSCALL_E) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_B) |
-	    UDEBUG_EVMASK(UDEBUG_EVENT_THREAD_E))
-} udebug_evmask_t;
-
-#ifdef KERNEL
-
+#include <abi/udebug.h>
 #include <ipc/ipc.h>
 #include <synch/mutex.h>
@@ -251,6 +107,4 @@
 #endif
 
-#endif
-
 /** @}
  */
Index: kernel/generic/src/adt/btree.c
===================================================================
--- kernel/generic/src/adt/btree.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/adt/btree.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -108,8 +108,8 @@
 void btree_create(btree_t *t)
 {
-	list_initialize(&t->leaf_head);
+	list_initialize(&t->leaf_list);
 	t->root = (btree_node_t *) slab_alloc(btree_node_slab, 0);
 	node_initialize(t->root);
-	list_append(&t->root->leaf_link, &t->leaf_head);
+	list_append(&t->root->leaf_link, &t->leaf_list);
 }
 
@@ -588,5 +588,5 @@
 		
 		if (LEAF_NODE(node)) {
-			list_prepend(&rnode->leaf_link, &node->leaf_link);
+			list_insert_after(&rnode->leaf_link, &node->leaf_link);
 		}
 		
@@ -953,5 +953,5 @@
 	ASSERT(LEAF_NODE(node));
 	
-	if (node->leaf_link.prev != &t->leaf_head)
+	if (node->leaf_link.prev != &t->leaf_list.head)
 		return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link);
 	else
@@ -972,5 +972,5 @@
 	ASSERT(LEAF_NODE(node));
 	
-	if (node->leaf_link.next != &t->leaf_head)
+	if (node->leaf_link.next != &t->leaf_list.head)
 		return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link);
 	else
@@ -987,9 +987,9 @@
 	size_t i;
 	int depth = t->root->depth;
-	link_t head, *cur;
+	list_t list;
 	
 	printf("Printing B-tree:\n");
-	list_initialize(&head);
-	list_append(&t->root->bfs_link, &head);
+	list_initialize(&list);
+	list_append(&t->root->bfs_link, &list);
 	
 	/*
@@ -997,10 +997,10 @@
 	 * Levels are distinguished from one another by node->depth.
 	 */
-	while (!list_empty(&head)) {
+	while (!list_empty(&list)) {
 		link_t *hlp;
 		btree_node_t *node;
 		
-		hlp = head.next;
-		ASSERT(hlp != &head);
+		hlp = list_first(&list);
+		ASSERT(hlp != NULL);
 		node = list_get_instance(hlp, btree_node_t, bfs_link);
 		list_remove(hlp);
@@ -1018,10 +1018,10 @@
 			printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : "");
 			if (node->depth && node->subtree[i]) {
-				list_append(&node->subtree[i]->bfs_link, &head);
+				list_append(&node->subtree[i]->bfs_link, &list);
 			}
 		}
 		
 		if (node->depth && node->subtree[i])
-			list_append(&node->subtree[i]->bfs_link, &head);
+			list_append(&node->subtree[i]->bfs_link, &list);
 		
 		printf(")");
@@ -1031,5 +1031,5 @@
 	
 	printf("Printing list of leaves:\n");
-	for (cur = t->leaf_head.next; cur != &t->leaf_head; cur = cur->next) {
+	list_foreach(t->leaf_list, cur) {
 		btree_node_t *node;
 		
Index: kernel/generic/src/adt/hash_table.c
===================================================================
--- kernel/generic/src/adt/hash_table.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/adt/hash_table.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -62,9 +62,9 @@
 	ASSERT(max_keys > 0);
 	
-	h->entry = (link_t *) malloc(m * sizeof(link_t), 0);
+	h->entry = (list_t *) malloc(m * sizeof(list_t), 0);
 	if (!h->entry)
 		panic("Cannot allocate memory for hash table.");
 	
-	memsetb(h->entry, m * sizeof(link_t), 0);
+	memsetb(h->entry, m * sizeof(list_t), 0);
 	
 	for (i = 0; i < m; i++)
@@ -107,5 +107,4 @@
 link_t *hash_table_find(hash_table_t *h, sysarg_t key[])
 {
-	link_t *cur;
 	size_t chain;
 	
@@ -118,5 +117,5 @@
 	ASSERT(chain < h->entries);
 	
-	for (cur = h->entry[chain].next; cur != &h->entry[chain]; cur = cur->next) {
+	list_foreach(h->entry[chain], cur) {
 		if (h->op->compare(key, h->max_keys, cur)) {
 			/*
@@ -141,5 +140,4 @@
 {
 	size_t chain;
-	link_t *cur;
 	
 	ASSERT(h);
@@ -149,6 +147,8 @@
 	ASSERT(keys <= h->max_keys);
 	
+	
 	if (keys == h->max_keys) {
-	
+		link_t *cur;
+		
 		/*
 		 * All keys are known, hash_table_find() can be used to find the entry.
@@ -169,5 +169,7 @@
 	 */
 	for (chain = 0; chain < h->entries; chain++) {
-		for (cur = h->entry[chain].next; cur != &h->entry[chain]; cur = cur->next) {
+		link_t *cur;
+		for (cur = h->entry[chain].head.next; cur != &h->entry[chain].head;
+		    cur = cur->next) {
 			if (h->op->compare(key, keys, cur)) {
 				link_t *hlp;
Index: kernel/generic/src/adt/list.c
===================================================================
--- kernel/generic/src/adt/list.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/adt/list.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,19 +43,19 @@
 /** Check for membership
  *
- * Check whether link is contained in the list head.
- * The membership is defined as pointer equivalence.
+ * Check whether link is contained in a list.
+ * Membership is defined as pointer equivalence.
  *
- * @param link Item to look for.
- * @param head List to look in.
+ * @param link	Item to look for.
+ * @param list	List to look in.
  *
  * @return true if link is contained in head, false otherwise.
  *
  */
-bool list_member(const link_t *link, const link_t *head)
+int list_member(const link_t *link, const list_t *list)
 {
 	bool found = false;
-	link_t *hlp = head->next;
+	link_t *hlp = list->head.next;
 	
-	while (hlp != head) {
+	while (hlp != &list->head) {
 		if (hlp == link) {
 			found = true;
@@ -68,25 +68,42 @@
 }
 
-
 /** Concatenate two lists
  *
- * Concatenate lists head1 and head2, producing a single
- * list head1 containing items from both (in head1, head2
- * order) and empty list head2.
+ * Concatenate lists @a list1 and @a list2, producing a single
+ * list @a list1 containing items from both (in @a list1, @a list2
+ * order) and empty list @a list2.
  *
- * @param head1 First list and concatenated output
- * @param head2 Second list and empty output.
+ * @param list1		First list and concatenated output
+ * @param list2 	Second list and empty output.
  *
  */
-void list_concat(link_t *head1, link_t *head2)
+void list_concat(list_t *list1, list_t *list2)
 {
-	if (list_empty(head2))
+	if (list_empty(list2))
 		return;
 
-	head2->next->prev = head1->prev;
-	head2->prev->next = head1;	
-	head1->prev->next = head2->next;
-	head1->prev = head2->prev;
-	list_initialize(head2);
+	list2->head.next->prev = list1->head.prev;
+	list2->head.prev->next = &list1->head;
+	list1->head.prev->next = list2->head.next;
+	list1->head.prev = list2->head.prev;
+	list_initialize(list2);
+}
+
+/** Count list items
+ *
+ * Return the number of items in the list.
+ *
+ * @param list		List to count.
+ * @return		Number of items in the list.
+ */
+unsigned int list_count(const list_t *list)
+{
+	unsigned int count = 0;
+	
+	list_foreach(*list, link) {
+		count++;
+	}
+	
+	return count;
 }
 
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/console/cmd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -573,7 +573,6 @@
 	spinlock_lock(&cmd_lock);
 	
-	link_t *cur;
 	size_t len = 0;
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp;
 		hlp = list_get_instance(cur, cmd_info_t, link);
@@ -591,5 +590,5 @@
 	}
 	
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp;
 		hlp = list_get_instance(cur, cmd_info_t, link);
@@ -646,9 +645,7 @@
 int cmd_desc(cmd_arg_t *argv)
 {
-	link_t *cur;
-	
 	spinlock_lock(&cmd_lock);
 	
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp;
 		
@@ -1107,5 +1104,5 @@
 	release_console();
 	
-	event_notify_0(EVENT_KCONSOLE);
+	event_notify_0(EVENT_KCONSOLE, false);
 	indev_pop_character(stdin);
 	
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/console/console.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -53,7 +53,6 @@
 #include <str.h>
 
-#define KLOG_PAGES    4
+#define KLOG_PAGES    8
 #define KLOG_LENGTH   (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t))
-#define KLOG_LATENCY  8
 
 /** Kernel log cyclic buffer */
@@ -61,5 +60,5 @@
 
 /** Kernel log initialized */
-static bool klog_inited = false;
+static atomic_t klog_inited = {false};
 
 /** First kernel log characters */
@@ -76,5 +75,5 @@
 
 /** Kernel log spinlock */
-SPINLOCK_STATIC_INITIALIZE_NAME(klog_lock, "*klog_lock");
+SPINLOCK_STATIC_INITIALIZE_NAME(klog_lock, "klog_lock");
 
 /** Physical memory area used for klog buffer */
@@ -88,5 +87,5 @@
 };
 
-static void stdout_write(outdev_t *, wchar_t, bool);
+static void stdout_write(outdev_t *, wchar_t);
 static void stdout_redraw(outdev_t *);
 
@@ -96,6 +95,6 @@
 };
 
-/** Silence output */
-bool silent = false;
+/** Override kernel console lockout */
+bool console_override = false;
 
 /** Standard input and output character devices */
@@ -123,12 +122,10 @@
 }
 
-static void stdout_write(outdev_t *dev, wchar_t ch, bool silent)
-{
-	link_t *cur;
-	
-	for (cur = dev->list.next; cur != &dev->list; cur = cur->next) {
+static void stdout_write(outdev_t *dev, wchar_t ch)
+{
+	list_foreach(dev->list, cur) {
 		outdev_t *sink = list_get_instance(cur, outdev_t, link);
 		if ((sink) && (sink->op->write))
-			sink->op->write(sink, ch, silent);
+			sink->op->write(sink, ch);
 	}
 }
@@ -136,7 +133,5 @@
 static void stdout_redraw(outdev_t *dev)
 {
-	link_t *cur;
-	
-	for (cur = dev->list.next; cur != &dev->list; cur = cur->next) {
+	list_foreach(dev->list, cur) {
 		outdev_t *sink = list_get_instance(cur, outdev_t, link);
 		if ((sink) && (sink->op->redraw))
@@ -161,4 +156,5 @@
 	klog_parea.frames = SIZE2FRAMES(sizeof(klog));
 	klog_parea.unpriv = false;
+	klog_parea.mapped = false;
 	ddi_parea_register(&klog_parea);
 	
@@ -166,18 +162,17 @@
 	sysinfo_set_item_val("klog.pages", NULL, KLOG_PAGES);
 	
-	spinlock_lock(&klog_lock);
-	klog_inited = true;
-	spinlock_unlock(&klog_lock);
+	event_set_unmask_callback(EVENT_KLOG, klog_update);
+	atomic_set(&klog_inited, true);
 }
 
 void grab_console(void)
 {
-	bool prev = silent;
-	
-	silent = false;
+	bool prev = console_override;
+	
+	console_override = true;
 	if ((stdout) && (stdout->op->redraw))
 		stdout->op->redraw(stdout);
 	
-	if ((stdin) && (prev)) {
+	if ((stdin) && (!prev)) {
 		/*
 		 * Force the console to print the prompt.
@@ -189,10 +184,9 @@
 void release_console(void)
 {
-	// FIXME arch_release_console
-	silent = true;
-}
-
-/** Tell kernel to get keyboard/console access again */
-sysarg_t sys_debug_enable_console(void)
+	console_override = false;
+}
+
+/** Activate kernel console override */
+sysarg_t sys_debug_activate_console(void)
 {
 #ifdef CONFIG_KCONSOLE
@@ -202,11 +196,4 @@
 	return false;
 #endif
-}
-
-/** Tell kernel to relinquish keyboard/console access */
-sysarg_t sys_debug_disable_console(void)
-{
-	release_console();
-	return true;
 }
 
@@ -261,11 +248,15 @@
 }
 
-void klog_update(void)
-{
+void klog_update(void *event)
+{
+	if (!atomic_get(&klog_inited))
+		return;
+	
 	spinlock_lock(&klog_lock);
 	
-	if ((klog_inited) && (event_is_subscribed(EVENT_KLOG)) && (klog_uspace > 0)) {
-		event_notify_3(EVENT_KLOG, klog_start, klog_len, klog_uspace);
-		klog_uspace = 0;
+	if (klog_uspace > 0) {
+		if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len,
+		    klog_uspace) == EOK)
+			klog_uspace = 0;
 	}
 	
@@ -275,12 +266,23 @@
 void putchar(const wchar_t ch)
 {
+	bool ordy = ((stdout) && (stdout->op->write));
+	
 	spinlock_lock(&klog_lock);
 	
-	if ((klog_stored > 0) && (stdout) && (stdout->op->write)) {
-		/* Print charaters stored in kernel log */
-		size_t i;
-		for (i = klog_len - klog_stored; i < klog_len; i++)
-			stdout->op->write(stdout, klog[(klog_start + i) % KLOG_LENGTH], silent);
-		klog_stored = 0;
+	/* Print charaters stored in kernel log */
+	if (ordy) {
+		while (klog_stored > 0) {
+			wchar_t tmp = klog[(klog_start + klog_len - klog_stored) % KLOG_LENGTH];
+			klog_stored--;
+			
+			/*
+			 * We need to give up the spinlock for
+			 * the physical operation of writting out
+			 * the character.
+			 */
+			spinlock_unlock(&klog_lock);
+			stdout->op->write(stdout, tmp);
+			spinlock_lock(&klog_lock);
+		}
 	}
 	
@@ -292,7 +294,22 @@
 		klog_start = (klog_start + 1) % KLOG_LENGTH;
 	
-	if ((stdout) && (stdout->op->write))
-		stdout->op->write(stdout, ch, silent);
-	else {
+	if (!ordy) {
+		if (klog_stored < klog_len)
+			klog_stored++;
+	}
+	
+	/* The character is stored for uspace */
+	if (klog_uspace < klog_len)
+		klog_uspace++;
+	
+	spinlock_unlock(&klog_lock);
+	
+	if (ordy) {
+		/*
+		 * Output the character. In this case
+		 * it should be no longer buffered.
+		 */
+		stdout->op->write(stdout, ch);
+	} else {
 		/*
 		 * No standard output routine defined yet.
@@ -304,27 +321,11 @@
 		 * Note that the early_putc() function might be
 		 * a no-op on certain hardware configurations.
-		 *
 		 */
 		early_putchar(ch);
-		
-		if (klog_stored < klog_len)
-			klog_stored++;
-	}
-	
-	/* The character is stored for uspace */
-	if (klog_uspace < klog_len)
-		klog_uspace++;
-	
-	/* Check notify uspace to update */
-	bool update;
-	if ((klog_uspace > KLOG_LATENCY) || (ch == '\n'))
-		update = true;
-	else
-		update = false;
-	
-	spinlock_unlock(&klog_lock);
-	
-	if (update)
-		klog_update();
+	}
+	
+	/* Force notification on newline */
+	if (ch == '\n')
+		klog_update(NULL);
 }
 
@@ -357,5 +358,5 @@
 		free(data);
 	} else
-		klog_update();
+		klog_update(NULL);
 	
 	return size;
Index: kernel/generic/src/console/kconsole.c
===================================================================
--- kernel/generic/src/console/kconsole.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/console/kconsole.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -84,5 +84,5 @@
 
 SPINLOCK_INITIALIZE(cmd_lock);  /**< Lock protecting command list. */
-LIST_INITIALIZE(cmd_head);      /**< Command list. */
+LIST_INITIALIZE(cmd_list);      /**< Command list. */
 
 static wchar_t history[KCONSOLE_HISTORY][MAX_CMDLINE] = {};
@@ -113,6 +113,4 @@
 bool cmd_register(cmd_info_t *cmd)
 {
-	link_t *cur;
-	
 	spinlock_lock(&cmd_lock);
 	
@@ -120,5 +118,5 @@
 	 * Make sure the command is not already listed.
 	 */
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link);
 		
@@ -153,5 +151,5 @@
 	 * Now the command can be added.
 	 */
-	list_append(&cmd->link, &cmd_head);
+	list_append(&cmd->link, &cmd_list);
 	
 	spinlock_unlock(&cmd_lock);
@@ -176,7 +174,7 @@
 	
 	if (*startpos == NULL)
-		*startpos = cmd_head.next;
-	
-	for (; *startpos != &cmd_head; *startpos = (*startpos)->next) {
+		*startpos = cmd_list.head.next;
+	
+	for (; *startpos != &cmd_list.head; *startpos = (*startpos)->next) {
 		cmd_info_t *hlp = list_get_instance(*startpos, cmd_info_t, link);
 		
@@ -559,7 +557,6 @@
 	
 	cmd_info_t *cmd = NULL;
-	link_t *cur;
-	
-	for (cur = cmd_head.next; cur != &cmd_head; cur = cur->next) {
+	
+	list_foreach(cmd_list, cur) {
 		cmd_info_t *hlp = list_get_instance(cur, cmd_info_t, link);
 		spinlock_lock(&hlp->lock);
Index: kernel/generic/src/cpu/cpu.c
===================================================================
--- kernel/generic/src/cpu/cpu.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/cpu/cpu.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -82,5 +82,5 @@
 			for (j = 0; j < RQ_COUNT; j++) {
 				irq_spinlock_initialize(&cpus[i].rq[j].lock, "cpus[].rq[].lock");
-				list_initialize(&cpus[i].rq[j].rq_head);
+				list_initialize(&cpus[i].rq[j].rq);
 			}
 		}
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/ddi/ddi.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,5 +41,4 @@
 
 #include <ddi/ddi.h>
-#include <ddi/ddi_arg.h>
 #include <proc/task.h>
 #include <security/cap.h>
@@ -122,5 +121,31 @@
 	backend_data.frames = pages;
 	
-	/* Find the zone of the physical memory */
+	/*
+	 * Check if the memory region is explicitly enabled
+	 * for mapping by any parea structure.
+	 */
+	
+	mutex_lock(&parea_lock);
+	btree_node_t *nodep;
+	parea_t *parea = (parea_t *) btree_search(&parea_btree,
+	    (btree_key_t) pf, &nodep);
+	
+	if ((parea != NULL) && (parea->frames >= pages)) {
+		if ((!priv) && (!parea->unpriv)) {
+			mutex_unlock(&parea_lock);
+			return EPERM;
+		}
+		
+		goto map;
+	}
+	
+	parea = NULL;
+	mutex_unlock(&parea_lock);
+	
+	/*
+	 * Check if the memory region is part of physical
+	 * memory generally enabled for mapping.
+	 */
+	
 	irq_spinlock_lock(&zones.lock, true);
 	size_t znum = find_zone(ADDR2PFN(pf), pages, 0);
@@ -153,32 +178,4 @@
 	}
 	
-	if (zone_flags_available(zones.info[znum].flags)) {
-		/*
-		 * Frames are part of physical memory, check
-		 * if the memory region is enabled for mapping.
-		 */
-		irq_spinlock_unlock(&zones.lock, true);
-		
-		mutex_lock(&parea_lock);
-		btree_node_t *nodep;
-		parea_t *parea = (parea_t *) btree_search(&parea_btree,
-		    (btree_key_t) pf, &nodep);
-		
-		if ((!parea) || (parea->frames < pages)) {
-			mutex_unlock(&parea_lock);
-			return ENOENT;
-		}
-		
-		if (!priv) {
-			if (!parea->unpriv) {
-				mutex_unlock(&parea_lock);
-				return EPERM;
-			}
-		}
-		
-		mutex_unlock(&parea_lock);
-		goto map;
-	}
-	
 	irq_spinlock_unlock(&zones.lock, true);
 	return ENOENT;
@@ -188,7 +185,11 @@
 	    AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
 		/*
-		 * The address space area could not have been created.
+		 * The address space area was not created.
 		 * We report it using ENOMEM.
 		 */
+		
+		if (parea != NULL)
+			mutex_unlock(&parea_lock);
+		
 		return ENOMEM;
 	}
@@ -197,5 +198,11 @@
 	 * Mapping is created on-demand during page fault.
 	 */
-	return 0;
+	
+	if (parea != NULL) {
+		parea->mapped = true;
+		mutex_unlock(&parea_lock);
+	}
+	
+	return EOK;
 }
 
@@ -224,5 +231,5 @@
 	task_t *task = task_find_by_id(id);
 	
-	if ((!task) || (!context_check(CONTEXT, task->context))) {
+	if ((!task) || (!container_check(CONTAINER, task->container))) {
 		/*
 		 * There is no task with the specified ID
Index: kernel/generic/src/ddi/irq.c
===================================================================
--- kernel/generic/src/ddi/irq.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/ddi/irq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -275,24 +275,26 @@
 {
 	/*
-	 * If the kernel console is silenced,
-	 * then try first the uspace handlers,
-	 * eventually fall back to kernel handlers.
+	 * If the kernel console override is on,
+	 * then try first the kernel handlers
+	 * and eventually fall back to uspace
+	 * handlers.
 	 *
-	 * If the kernel console is active,
-	 * then do it the other way around.
+	 * In the usual case the uspace handlers
+	 * have precedence.
 	 */
-	if (silent) {
-		irq_t *irq = irq_dispatch_and_lock_uspace(inr);
+	
+	if (console_override) {
+		irq_t *irq = irq_dispatch_and_lock_kernel(inr);
 		if (irq)
 			return irq;
 		
-		return irq_dispatch_and_lock_kernel(inr);
-	}
-	
-	irq_t *irq = irq_dispatch_and_lock_kernel(inr);
+		return irq_dispatch_and_lock_uspace(inr);
+	}
+	
+	irq_t *irq = irq_dispatch_and_lock_uspace(inr);
 	if (irq)
 		return irq;
 	
-	return irq_dispatch_and_lock_uspace(inr);
+	return irq_dispatch_and_lock_kernel(inr);
 }
 
Index: kernel/generic/src/debug/panic.c
===================================================================
--- kernel/generic/src/debug/panic.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/debug/panic.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -48,7 +48,5 @@
     uintptr_t address, const char *fmt, ...)
 {
-	va_list args;
-	
-	silent = false;
+	console_override = true;
 	
 	printf("\n%s Kernel panic ", BANNER_LEFT);
@@ -57,4 +55,5 @@
 	printf("due to ");
 	
+	va_list args;
 	va_start(args, fmt);
 	if (cat == PANIC_ASSERT) {
@@ -95,4 +94,12 @@
 	printf("\n");
 	
+	printf("THE=%p: ", THE);
+	if (THE != NULL) {
+		printf("pe=%" PRIun " thr=%p task=%p cpu=%p as=%p"
+		    " magic=%#" PRIx32 "\n", THE->preemption_disabled,
+		    THE->thread, THE->task, THE->cpu, THE->as, THE->magic);
+	} else
+		printf("invalid\n");
+	
 	if (istate) {
 		istate_decode(istate);
Index: kernel/generic/src/interrupt/interrupt.c
===================================================================
--- kernel/generic/src/interrupt/interrupt.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/interrupt/interrupt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -177,4 +177,5 @@
 	    (void *) istate_get_pc(istate));
 	
+	istate_decode(istate);
 	stack_trace_istate(istate);
 	
@@ -205,6 +206,6 @@
 	 * stack.
 	 */
-	return (istate_t *) ((uint8_t *) thread->kstack + THREAD_STACK_SIZE -
-	    sizeof(istate_t));
+	return (istate_t *) ((uint8_t *)
+	    thread->kstack + STACK_SIZE - sizeof(istate_t));
 }
 
Index: kernel/generic/src/ipc/event.c
===================================================================
--- kernel/generic/src/ipc/event.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/ipc/event.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,9 +36,9 @@
 
 #include <ipc/event.h>
-#include <ipc/event_types.h>
 #include <mm/slab.h>
 #include <typedefs.h>
 #include <synch/spinlock.h>
 #include <console/console.h>
+#include <proc/task.h>
 #include <memstr.h>
 #include <errno.h>
@@ -48,101 +48,291 @@
 static event_t events[EVENT_END];
 
-/** Initialize kernel events. */
+static void event_initialize(event_t *event)
+{
+	spinlock_initialize(&event->lock, "event.lock");
+	event->answerbox = NULL;
+	event->counter = 0;
+	event->imethod = 0;
+	event->masked = false;
+	event->unmask_callback = NULL;
+}
+
+static event_t *evno2event(int evno, task_t *t)
+{
+	ASSERT(evno < EVENT_TASK_END);
+
+	event_t *event;
+
+	if (evno < EVENT_END)
+		event = &events[(event_type_t) evno];
+	else
+		event = &t->events[(event_task_type_t) evno - EVENT_END];
+
+	return event;
+}
+
+/** Initialize kernel events.
+ *
+ */
 void event_init(void)
 {
-	unsigned int i;
-	
-	for (i = 0; i < EVENT_END; i++) {
-		spinlock_initialize(&events[i].lock, "event.lock");
-		events[i].answerbox = NULL;
-		events[i].counter = 0;
-		events[i].imethod = 0;
-	}
-}
-
-static int event_subscribe(event_type_t evno, sysarg_t imethod,
-    answerbox_t *answerbox)
-{
-	if (evno >= EVENT_END)
-		return ELIMIT;
-	
-	spinlock_lock(&events[evno].lock);
-	
-	int res;
-	
-	if (events[evno].answerbox == NULL) {
-		events[evno].answerbox = answerbox;
-		events[evno].imethod = imethod;
-		events[evno].counter = 0;
-		res = EOK;
-	} else
-		res = EEXISTS;
-	
-	spinlock_unlock(&events[evno].lock);
-	
-	return res;
-}
-
-sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
-{
-	return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
-	    imethod, &TASK->answerbox);
-}
-
-bool event_is_subscribed(event_type_t evno)
-{
-	bool res;
-	
-	ASSERT(evno < EVENT_END);
-	
-	spinlock_lock(&events[evno].lock);
-	res = events[evno].answerbox != NULL;
-	spinlock_unlock(&events[evno].lock);
-	
-	return res;
-}
-
-
+	for (unsigned int i = 0; i < EVENT_END; i++)
+		event_initialize(evno2event(i, NULL));
+}
+
+void event_task_init(task_t *task)
+{
+	for (unsigned int i = EVENT_END; i < EVENT_TASK_END; i++)
+		event_initialize(evno2event(i, task));
+}
+
+
+/** Unsubscribe kernel events associated with an answerbox
+ *
+ * @param answerbox Answerbox to be unsubscribed.
+ *
+ */
 void event_cleanup_answerbox(answerbox_t *answerbox)
 {
-	unsigned int i;
-	
-	for (i = 0; i < EVENT_END; i++) {
+	for (unsigned int i = 0; i < EVENT_END; i++) {
 		spinlock_lock(&events[i].lock);
+		
 		if (events[i].answerbox == answerbox) {
 			events[i].answerbox = NULL;
 			events[i].counter = 0;
 			events[i].imethod = 0;
+			events[i].masked = false;
 		}
+		
 		spinlock_unlock(&events[i].lock);
 	}
 }
 
-void event_notify(event_type_t evno, sysarg_t a1, sysarg_t a2, sysarg_t a3,
-    sysarg_t a4, sysarg_t a5)
+static void _event_set_unmask_callback(event_t *event, event_callback_t callback)
+{
+	spinlock_lock(&event->lock);
+	event->unmask_callback = callback;
+	spinlock_unlock(&event->lock);
+}
+
+/** Define a callback function for the event unmask event.
+ *
+ * @param evno     Event type.
+ * @param callback Callback function to be called when
+ *                 the event is unmasked.
+ *
+ */
+void event_set_unmask_callback(event_type_t evno, event_callback_t callback)
 {
 	ASSERT(evno < EVENT_END);
 	
-	spinlock_lock(&events[evno].lock);
-	if (events[evno].answerbox != NULL) {
-		call_t *call = ipc_call_alloc(FRAME_ATOMIC);
-		if (call) {
-			call->flags |= IPC_CALL_NOTIF;
-			call->priv = ++events[evno].counter;
-			IPC_SET_IMETHOD(call->data, events[evno].imethod);
-			IPC_SET_ARG1(call->data, a1);
-			IPC_SET_ARG2(call->data, a2);
-			IPC_SET_ARG3(call->data, a3);
-			IPC_SET_ARG4(call->data, a4);
-			IPC_SET_ARG5(call->data, a5);
+	_event_set_unmask_callback(evno2event(evno, NULL), callback);
+}
+
+void event_task_set_unmask_callback(task_t *task, event_task_type_t evno,
+    event_callback_t callback)
+{
+	ASSERT(evno >= (int) EVENT_END);
+	ASSERT(evno < EVENT_TASK_END);
+		
+	_event_set_unmask_callback(evno2event(evno, task), callback);
+}
+
+static int event_enqueue(event_t *event, bool mask, sysarg_t a1, sysarg_t a2,
+    sysarg_t a3, sysarg_t a4, sysarg_t a5)
+{
+	int res;
+
+	spinlock_lock(&event->lock);
+	
+	if (event->answerbox != NULL) {
+		if (!event->masked) {
+			call_t *call = ipc_call_alloc(FRAME_ATOMIC);
 			
-			irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
-			list_append(&call->link, &events[evno].answerbox->irq_notifs);
-			irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
-			
-			waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
-		}
-	}
-	spinlock_unlock(&events[evno].lock);
+			if (call) {
+				call->flags |= IPC_CALL_NOTIF;
+				call->priv = ++event->counter;
+				
+				IPC_SET_IMETHOD(call->data, event->imethod);
+				IPC_SET_ARG1(call->data, a1);
+				IPC_SET_ARG2(call->data, a2);
+				IPC_SET_ARG3(call->data, a3);
+				IPC_SET_ARG4(call->data, a4);
+				IPC_SET_ARG5(call->data, a5);
+				
+				call->data.task_id = TASK ? TASK->taskid : 0;
+				
+				irq_spinlock_lock(&event->answerbox->irq_lock, true);
+				list_append(&call->link, &event->answerbox->irq_notifs);
+				irq_spinlock_unlock(&event->answerbox->irq_lock, true);
+				
+				waitq_wakeup(&event->answerbox->wq, WAKEUP_FIRST);
+				
+				if (mask)
+					event->masked = true;
+				
+				res = EOK;
+			} else
+				res = ENOMEM;
+		} else
+			res = EBUSY;
+	} else
+		res = ENOENT;
+	
+	spinlock_unlock(&event->lock);
+	return res;
+}
+
+/** Send kernel notification event
+ *
+ * @param evno Event type.
+ * @param mask Mask further notifications after a successful
+ *             sending.
+ * @param a1   First argument.
+ * @param a2   Second argument.
+ * @param a3   Third argument.
+ * @param a4   Fourth argument.
+ * @param a5   Fifth argument.
+ *
+ * @return EOK if notification was successfully sent.
+ * @return ENOMEM if the notification IPC message failed to allocate.
+ * @return EBUSY if the notifications of the given type are
+ *         currently masked.
+ * @return ENOENT if the notifications of the given type are
+ *         currently not subscribed.
+ *
+ */
+int event_notify(event_type_t evno, bool mask, sysarg_t a1, sysarg_t a2,
+    sysarg_t a3, sysarg_t a4, sysarg_t a5)
+{
+	ASSERT(evno < EVENT_END);
+	
+	return event_enqueue(evno2event(evno, NULL), mask, a1, a2, a3, a4, a5);
+}
+
+/** Send per-task kernel notification event
+ *
+ * @param task Destination task.
+ * @param evno Event type.
+ * @param mask Mask further notifications after a successful
+ *             sending.
+ * @param a1   First argument.
+ * @param a2   Second argument.
+ * @param a3   Third argument.
+ * @param a4   Fourth argument.
+ * @param a5   Fifth argument.
+ *
+ * @return EOK if notification was successfully sent.
+ * @return ENOMEM if the notification IPC message failed to allocate.
+ * @return EBUSY if the notifications of the given type are
+ *         currently masked.
+ * @return ENOENT if the notifications of the given type are
+ *         currently not subscribed.
+ *
+ */
+int event_task_notify(task_t *task, event_task_type_t evno, bool mask,
+    sysarg_t a1, sysarg_t a2, sysarg_t a3, sysarg_t a4, sysarg_t a5)
+{
+	ASSERT(evno >= (int) EVENT_END);
+	ASSERT(evno < EVENT_TASK_END);
+	
+	return event_enqueue(evno2event(evno, task), mask, a1, a2, a3, a4, a5);
+}
+
+/** Subscribe event notifications
+ *
+ * @param evno      Event type.
+ * @param imethod   IPC interface and method to be used for
+ *                  the notifications.
+ * @param answerbox Answerbox to send the notifications to.
+ *
+ * @return EOK if the subscription was successful.
+ * @return EEXISTS if the notifications of the given type are
+ *         already subscribed.
+ *
+ */
+static int event_subscribe(event_t *event, sysarg_t imethod,
+    answerbox_t *answerbox)
+{
+	int res;
+
+	spinlock_lock(&event->lock);
+	
+	if (event->answerbox == NULL) {
+		event->answerbox = answerbox;
+		event->imethod = imethod;
+		event->counter = 0;
+		event->masked = false;
+		res = EOK;
+	} else
+		res = EEXISTS;
+	
+	spinlock_unlock(&event->lock);
+	
+	return res;
+}
+
+/** Unmask event notifications
+ *
+ * @param evno Event type to unmask.
+ *
+ */
+static void event_unmask(event_t *event)
+{
+	spinlock_lock(&event->lock);
+	event->masked = false;
+	event_callback_t callback = event->unmask_callback;
+	spinlock_unlock(&event->lock);
+	
+	/*
+	 * Check if there is an unmask callback
+	 * function defined for this event.
+	 */
+	if (callback != NULL)
+		callback(event);
+}
+
+/** Event notification syscall wrapper
+ *
+ * @param evno    Event type to subscribe.
+ * @param imethod IPC interface and method to be used for
+ *                the notifications.
+ *
+ * @return EOK on success.
+ * @return ELIMIT on unknown event type.
+ * @return EEXISTS if the notifications of the given type are
+ *         already subscribed.
+ *
+ */
+sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
+{
+	if (evno >= EVENT_TASK_END)
+		return ELIMIT;
+	
+	return (sysarg_t) event_subscribe(evno2event(evno, TASK),
+	    (sysarg_t) imethod, &TASK->answerbox);
+}
+
+/** Event notification unmask syscall wrapper
+ *
+ * Note that currently no tests are performed whether the calling
+ * task is entitled to unmask the notifications. However, thanks
+ * to the fact that notification masking is only a performance
+ * optimization, this has probably no security implications.
+ *
+ * @param evno Event type to unmask.
+ *
+ * @return EOK on success.
+ * @return ELIMIT on unknown event type.
+ *
+ */
+sysarg_t sys_event_unmask(sysarg_t evno)
+{
+	if (evno >= EVENT_TASK_END)
+		return ELIMIT;
+	
+	event_unmask(evno2event(evno, TASK));
+
+	return EOK;
 }
 
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/ipc/ipc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,10 +38,9 @@
  */
 
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
 #include <synch/waitq.h>
-#include <synch/synch.h>
 #include <ipc/ipc.h>
+#include <abi/ipc/methods.h>
 #include <ipc/kbox.h>
 #include <ipc/event.h>
@@ -127,5 +126,5 @@
 	list_initialize(&box->answers);
 	list_initialize(&box->irq_notifs);
-	list_initialize(&box->irq_head);
+	list_initialize(&box->irq_list);
 	box->task = task;
 }
@@ -182,5 +181,5 @@
 	 */
 	irq_spinlock_lock(&TASK->lock, true);
-	list_append(&sync_box->sync_box_link, &TASK->sync_box_head);
+	list_append(&sync_box->sync_box_link, &TASK->sync_boxes);
 	irq_spinlock_unlock(&TASK->lock, true);
 	
@@ -231,4 +230,6 @@
 		}
 	}
+
+	call->data.task_id = TASK->taskid;
 	
 	if (do_lock)
@@ -295,5 +296,5 @@
 		atomic_inc(&phone->active_calls);
 		call->data.phone = phone;
-		call->data.task = TASK;
+		call->data.task_id = TASK->taskid;
 	}
 	
@@ -407,5 +408,5 @@
 			call->caller_phone = call->data.phone;
 		call->data.phone = newphone;
-		call->data.task = TASK;
+		call->data.task_id = TASK->taskid;
 	}
 	
@@ -449,5 +450,6 @@
 		irq_spinlock_lock(&box->irq_lock, false);
 		
-		request = list_get_instance(box->irq_notifs.next, call_t, link);
+		request = list_get_instance(list_first(&box->irq_notifs),
+		    call_t, link);
 		list_remove(&request->link);
 		
@@ -458,5 +460,6 @@
 		
 		/* Handle asynchronous answers */
-		request = list_get_instance(box->answers.next, call_t, link);
+		request = list_get_instance(list_first(&box->answers),
+		    call_t, link);
 		list_remove(&request->link);
 		atomic_dec(&request->data.phone->active_calls);
@@ -466,5 +469,6 @@
 		
 		/* Handle requests */
-		request = list_get_instance(box->calls.next, call_t, link);
+		request = list_get_instance(list_first(&box->calls),
+		    call_t, link);
 		list_remove(&request->link);
 		
@@ -493,8 +497,8 @@
  *
  */
-void ipc_cleanup_call_list(link_t *lst)
+void ipc_cleanup_call_list(list_t *lst)
 {
 	while (!list_empty(lst)) {
-		call_t *call = list_get_instance(lst->next, call_t, link);
+		call_t *call = list_get_instance(list_first(lst), call_t, link);
 		if (call->buffer)
 			free(call->buffer);
@@ -525,5 +529,5 @@
 	irq_spinlock_lock(&box->lock, true);
 	while (!list_empty(&box->connected_phones)) {
-		phone = list_get_instance(box->connected_phones.next,
+		phone = list_get_instance(list_first(&box->connected_phones),
 		    phone_t, link);
 		if (SYNCH_FAILED(mutex_trylock(&phone->lock))) {
@@ -605,7 +609,7 @@
 	/* Wait for all answers to interrupted synchronous calls to arrive */
 	ipl_t ipl = interrupts_disable();
-	while (!list_empty(&TASK->sync_box_head)) {
-		answerbox_t *box = list_get_instance(TASK->sync_box_head.next,
-		    answerbox_t, sync_box_link);
+	while (!list_empty(&TASK->sync_boxes)) {
+		answerbox_t *box = list_get_instance(
+		    list_first(&TASK->sync_boxes), answerbox_t, sync_box_link);
 		
 		list_remove(&box->sync_box_link);
@@ -742,9 +746,6 @@
 #endif
 	
-	link_t *cur;
-	
 	printf(" --- incomming calls ---\n");
-	for (cur = task->answerbox.calls.next; cur != &task->answerbox.calls;
-	    cur = cur->next) {
+	list_foreach(task->answerbox.calls, cur) {
 		call_t *call = list_get_instance(cur, call_t, link);
 		
@@ -766,7 +767,5 @@
 	
 	printf(" --- dispatched calls ---\n");
-	for (cur = task->answerbox.dispatched_calls.next;
-	    cur != &task->answerbox.dispatched_calls;
-	    cur = cur->next) {
+	list_foreach(task->answerbox.dispatched_calls, cur) {
 		call_t *call = list_get_instance(cur, call_t, link);
 		
@@ -788,7 +787,5 @@
 	
 	printf(" --- incoming answers ---\n");
-	for (cur = task->answerbox.answers.next;
-	    cur != &task->answerbox.answers;
-	    cur = cur->next) {
+	list_foreach(task->answerbox.answers, cur) {
 		call_t *call = list_get_instance(cur, call_t, link);
 		
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -146,10 +146,9 @@
 call_t *get_call(sysarg_t callid)
 {
-	link_t *lst;
 	call_t *result = NULL;
 	
 	irq_spinlock_lock(&TASK->answerbox.lock, true);
-	for (lst = TASK->answerbox.dispatched_calls.next;
-	    lst != &TASK->answerbox.dispatched_calls; lst = lst->next) {
+	
+	list_foreach(TASK->answerbox.dispatched_calls, lst) {
 		call_t *call = list_get_instance(lst, call_t, link);
 		if ((sysarg_t) call == callid) {
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/ipc/irq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -174,4 +174,5 @@
 	irq->notif_cfg.code = code;
 	irq->notif_cfg.counter = 0;
+	irq->driver_as = AS;
 	
 	/*
@@ -199,5 +200,5 @@
 	
 	hash_table_insert(&irq_uspace_hash_table, key, &irq->link);
-	list_append(&irq->notif_cfg.link, &box->irq_head);
+	list_append(&irq->notif_cfg.link, &box->irq_list);
 	
 	irq_spinlock_unlock(&box->irq_lock, false);
@@ -281,8 +282,8 @@
 	irq_spinlock_lock(&box->irq_lock, false);
 	
-	while (box->irq_head.next != &box->irq_head) {
+	while (!list_empty(&box->irq_list)) {
 		DEADLOCK_PROBE_INIT(p_irqlock);
 		
-		irq_t *irq = list_get_instance(box->irq_head.next, irq_t,
+		irq_t *irq = list_get_instance(list_first(&box->irq_list), irq_t,
 		    notif_cfg.link);
 		
@@ -364,4 +365,23 @@
 		return IRQ_DECLINE;
 	
+#define CMD_MEM_READ(target) \
+do { \
+	void *va = code->cmds[i].addr; \
+	if (AS != irq->driver_as) \
+		as_switch(AS, irq->driver_as); \
+	memcpy_from_uspace(&target, va, (sizeof(target))); \
+	if (dstarg) \
+		scratch[dstarg] = target; \
+} while(0)
+
+#define CMD_MEM_WRITE(val) \
+do { \
+	void *va = code->cmds[i].addr; \
+	if (AS != irq->driver_as) \
+		as_switch(AS, irq->driver_as); \
+	memcpy_to_uspace(va, &val, sizeof(val)); \
+} while (0)
+
+	as_t *current_as = AS;
 	size_t i;
 	for (i = 0; i < code->cmdcount; i++) {
@@ -422,4 +442,52 @@
 			}
 			break;
+		case CMD_MEM_READ_8: {
+			uint8_t val;
+			CMD_MEM_READ(val);
+			break;
+			}
+		case CMD_MEM_READ_16: {
+			uint16_t val;
+			CMD_MEM_READ(val);
+			break;
+			}
+		case CMD_MEM_READ_32: {
+			uint32_t val;
+			CMD_MEM_READ(val);
+			break;
+			}
+		case CMD_MEM_WRITE_8: {
+			uint8_t val = code->cmds[i].value;
+			CMD_MEM_WRITE(val);
+			break;
+			}
+		case CMD_MEM_WRITE_16: {
+			uint16_t val = code->cmds[i].value;
+			CMD_MEM_WRITE(val);
+			break;
+			}
+		case CMD_MEM_WRITE_32: {
+			uint32_t val = code->cmds[i].value;
+			CMD_MEM_WRITE(val);
+			break;
+			}
+		case CMD_MEM_WRITE_A_8:
+			if (srcarg) {
+				uint8_t val = scratch[srcarg];
+				CMD_MEM_WRITE(val);
+			}
+			break;
+		case CMD_MEM_WRITE_A_16:
+			if (srcarg) {
+				uint16_t val = scratch[srcarg];
+				CMD_MEM_WRITE(val);
+			}
+			break;
+		case CMD_MEM_WRITE_A_32:
+			if (srcarg) {
+				uint32_t val = scratch[srcarg];
+				CMD_MEM_WRITE(val);
+			}
+			break;
 		case CMD_BTEST:
 			if ((srcarg) && (dstarg)) {
@@ -435,10 +503,16 @@
 			break;
 		case CMD_ACCEPT:
+			if (AS != current_as)
+				as_switch(AS, current_as);
 			return IRQ_ACCEPT;
 		case CMD_DECLINE:
 		default:
+			if (AS != current_as)
+				as_switch(AS, current_as);
 			return IRQ_DECLINE;
 		}
 	}
+	if (AS != current_as)
+		as_switch(AS, current_as);
 	
 	return IRQ_DECLINE;
Index: kernel/generic/src/ipc/kbox.c
===================================================================
--- kernel/generic/src/ipc/kbox.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/ipc/kbox.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,8 +33,8 @@
  */
 
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
 #include <ipc/ipc.h>
+#include <abi/ipc/methods.h>
 #include <ipc/ipcrsc.h>
 #include <arch.h>
@@ -169,5 +169,5 @@
 		switch (IPC_GET_IMETHOD(call->data)) {
 		
-		case IPC_M_DEBUG_ALL:
+		case IPC_M_DEBUG:
 			/* Handle debug call. */
 			udebug_call_receive(call);
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/ipc/sysipc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,7 +40,9 @@
 #include <debug.h>
 #include <ipc/ipc.h>
+#include <abi/ipc/methods.h>
 #include <ipc/sysipc.h>
 #include <ipc/irq.h>
 #include <ipc/ipcrsc.h>
+#include <ipc/event.h>
 #include <ipc/kbox.h>
 #include <synch/waitq.h>
@@ -52,4 +54,5 @@
 #include <mm/as.h>
 #include <print.h>
+#include <macros.h>
 
 /**
@@ -133,4 +136,5 @@
 	case IPC_M_DATA_WRITE:
 	case IPC_M_DATA_READ:
+	case IPC_M_STATE_CHANGE_AUTHORIZE:
 		return true;
 	default:
@@ -163,4 +167,5 @@
 	case IPC_M_DATA_WRITE:
 	case IPC_M_DATA_READ:
+	case IPC_M_STATE_CHANGE_AUTHORIZE:
 		return true;
 	default:
@@ -248,6 +253,4 @@
 			/* The connection was accepted */
 			phone_connect(phoneid, &answer->sender->answerbox);
-			/* Set 'task hash' as arg4 of response */
-			IPC_SET_ARG4(answer->data, (sysarg_t) TASK);
 			/* Set 'phone hash' as arg5 of response */
 			IPC_SET_ARG5(answer->data,
@@ -333,4 +336,50 @@
 		free(answer->buffer);
 		answer->buffer = NULL;
+	} else if (IPC_GET_IMETHOD(*olddata) == IPC_M_STATE_CHANGE_AUTHORIZE) {
+		if (!IPC_GET_RETVAL(answer->data)) {
+			/* The recipient authorized the change of state. */
+			phone_t *recipient_phone;
+			task_t *other_task_s;
+			task_t *other_task_r;
+			int rc;
+
+			rc = phone_get(IPC_GET_ARG1(answer->data),
+			    &recipient_phone);
+			if (rc != EOK) {
+				IPC_SET_RETVAL(answer->data, ENOENT);
+				return ENOENT;
+			}
+
+			mutex_lock(&recipient_phone->lock);
+			if (recipient_phone->state != IPC_PHONE_CONNECTED) {
+				mutex_unlock(&recipient_phone->lock);
+				IPC_SET_RETVAL(answer->data, EINVAL);
+				return EINVAL;
+			}
+
+			other_task_r = recipient_phone->callee->task;
+			other_task_s = (task_t *) IPC_GET_ARG5(*olddata);
+
+			/*
+			 * See if both the sender and the recipient meant the
+			 * same third party task.
+			 */
+			if (other_task_r != other_task_s) {
+				IPC_SET_RETVAL(answer->data, EINVAL);
+				rc = EINVAL;
+			} else {
+				rc = event_task_notify_5(other_task_r,
+				    EVENT_TASK_STATE_CHANGE, false,
+				    IPC_GET_ARG1(*olddata),
+				    IPC_GET_ARG2(*olddata),
+				    IPC_GET_ARG3(*olddata),
+				    LOWER32(olddata->task_id),
+				    UPPER32(olddata->task_id));
+				IPC_SET_RETVAL(answer->data, rc);
+			}
+
+			mutex_unlock(&recipient_phone->lock);
+			return rc;
+		}
 	}
 	
@@ -426,7 +475,11 @@
 	case IPC_M_DATA_READ: {
 		size_t size = IPC_GET_ARG2(call->data);
-		if ((size <= 0 || (size > DATA_XFER_LIMIT)))
-			return ELIMIT;
-		
+		if (size > DATA_XFER_LIMIT) {
+			int flags = IPC_GET_ARG3(call->data);
+			if (flags & IPC_XF_RESTRICT)
+				IPC_SET_ARG2(call->data, DATA_XFER_LIMIT);
+			else
+				return ELIMIT;
+		}
 		break;
 	}
@@ -435,6 +488,12 @@
 		size_t size = IPC_GET_ARG2(call->data);
 		
-		if (size > DATA_XFER_LIMIT)
-			return ELIMIT;
+		if (size > DATA_XFER_LIMIT) {
+			int flags = IPC_GET_ARG3(call->data);
+			if (flags & IPC_XF_RESTRICT) {
+				size = DATA_XFER_LIMIT;
+				IPC_SET_ARG2(call->data, size);
+			} else
+				return ELIMIT;
+		}
 		
 		call->buffer = (uint8_t *) malloc(size, 0);
@@ -447,6 +506,27 @@
 		break;
 	}
+	case IPC_M_STATE_CHANGE_AUTHORIZE: {
+		phone_t *sender_phone;
+		task_t *other_task_s;
+
+		if (phone_get(IPC_GET_ARG5(call->data), &sender_phone) != EOK)
+			return ENOENT;
+
+		mutex_lock(&sender_phone->lock);
+		if (sender_phone->state != IPC_PHONE_CONNECTED) {
+			mutex_unlock(&sender_phone->lock);
+			return EINVAL;
+		}
+
+		other_task_s = sender_phone->callee->task;
+
+		mutex_unlock(&sender_phone->lock);
+
+		/* Remember the third party task hash. */
+		IPC_SET_ARG5(call->data, (sysarg_t) other_task_s);
+		break;
+	}
 #ifdef CONFIG_UDEBUG
-	case IPC_M_DEBUG_ALL:
+	case IPC_M_DEBUG:
 		return udebug_request_preprocess(call, phone);
 #endif
@@ -483,5 +563,5 @@
 		/*
 		 * This must be an affirmative answer to IPC_M_DATA_READ
-		 * or IPC_M_DEBUG_ALL/UDEBUG_M_MEM_READ...
+		 * or IPC_M_DEBUG/UDEBUG_M_MEM_READ...
 		 *
 		 */
@@ -519,5 +599,5 @@
 	
 	switch (IPC_GET_IMETHOD(call->data)) {
-	case IPC_M_DEBUG_ALL:
+	case IPC_M_DEBUG:
 		return -1;
 	default:
Index: kernel/generic/src/lib/elf.c
===================================================================
--- kernel/generic/src/lib/elf.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/lib/elf.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -48,4 +48,6 @@
 #include <arch.h>
 
+#include <lib/elf_load.h>
+
 static const char *error_codes[] = {
 	"no error",
@@ -114,5 +116,5 @@
 	}
 	
-	/* Inspect all section headers and proccess them. */
+	/* Inspect all section headers and process them. */
 	for (i = 0; i < header->e_shnum; i++) {
 		elf_section_header_t *sechdr =
Index: kernel/generic/src/lib/memfnc.c
===================================================================
--- kernel/generic/src/lib/memfnc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/generic/src/lib/memfnc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,90 @@
+	/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+
+/**
+ * @file
+ * @brief Memory string functions.
+ *
+ * This file provides architecture independent functions to manipulate blocks
+ * of memory. These functions are optimized as much as generic functions of
+ * this type can be.
+ */
+
+#include <lib/memfnc.h>
+#include <typedefs.h>
+
+/** Fill block of memory.
+ *
+ * Fill cnt bytes at dst address with the value val.
+ *
+ * @param dst Destination address to fill.
+ * @param val Value to fill.
+ * @param cnt Number of bytes to fill.
+ *
+ * @return Destination address.
+ *
+ */
+void *memset(void *dst, int val, size_t cnt)
+{
+	uint8_t *dp = (uint8_t *) dst;
+	
+	while (cnt-- != 0)
+		*dp++ = val;
+	
+	return dst;
+}
+
+/** Move memory block without overlapping.
+ *
+ * Copy cnt bytes from src address to dst address. The source
+ * and destination memory areas cannot overlap.
+ *
+ * @param dst Destination address to copy to.
+ * @param src Source address to copy from.
+ * @param cnt Number of bytes to copy.
+ *
+ * @return Destination address.
+ *
+ */
+void *memcpy(void *dst, const void *src, size_t cnt)
+{
+	uint8_t *dp = (uint8_t *) dst;
+	const uint8_t *sp = (uint8_t *) src;
+	
+	while (cnt-- != 0)
+		*dp++ = *sp++;
+	
+	return dst;
+}
+
+/** @}
+ */
Index: kernel/generic/src/lib/memstr.c
===================================================================
--- kernel/generic/src/lib/memstr.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/lib/memstr.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -28,5 +28,5 @@
  */
 
-/** @addtogroup generic	
+/** @addtogroup generic
  * @{
  */
@@ -34,129 +34,90 @@
 /**
  * @file
- * @brief	Memory string operations.
+ * @brief Memory string operations.
  *
- * This file provides architecture independent functions to manipulate blocks of
- * memory. These functions are optimized as much as generic functions of this
- * type can be. However, architectures are free to provide even more optimized
- * versions of these functions.
+ * This file provides architecture independent functions to manipulate blocks
+ * of memory. These functions are optimized as much as generic functions of
+ * this type can be.
  */
 
 #include <memstr.h>
 #include <typedefs.h>
-#include <align.h>
 
-/** Copy block of memory.
+/** Fill block of memory.
  *
- * Copy cnt bytes from src address to dst address.  The copying is done
- * word-by-word and then byte-by-byte.  The source and destination memory areas
- * cannot overlap.
+ * Fill cnt bytes at dst address with the value val.
  *
- * @param src		Source address to copy from.
- * @param dst		Destination address to copy to.
- * @param cnt		Number of bytes to copy.
+ * @param dst Destination address to fill.
+ * @param cnt Number of bytes to fill.
+ * @param val Value to fill.
  *
- * @return		Destination address.
  */
-void *_memcpy(void *dst, const void *src, size_t cnt)
+void memsetb(void *dst, size_t cnt, uint8_t val)
 {
-	unsigned int i, j;
+	memset(dst, val, cnt);
+}
+
+/** Fill block of memory.
+ *
+ * Fill cnt words at dst address with the value val. The filling
+ * is done word-by-word.
+ *
+ * @param dst Destination address to fill.
+ * @param cnt Number of words to fill.
+ * @param val Value to fill.
+ *
+ */
+void memsetw(void *dst, size_t cnt, uint16_t val)
+{
+	size_t i;
+	uint16_t *ptr = (uint16_t *) dst;
 	
-	if (ALIGN_UP((uintptr_t) src, sizeof(sysarg_t)) != (uintptr_t) src ||
-	    ALIGN_UP((uintptr_t) dst, sizeof(sysarg_t)) != (uintptr_t) dst) {
-		for (i = 0; i < cnt; i++)
-			((uint8_t *) dst)[i] = ((uint8_t *) src)[i];
-	} else { 
-		for (i = 0; i < cnt / sizeof(sysarg_t); i++)
-			((sysarg_t *) dst)[i] = ((sysarg_t *) src)[i];
-		
-		for (j = 0; j < cnt % sizeof(sysarg_t); j++)
-			((uint8_t *)(((sysarg_t *) dst) + i))[j] =
-			    ((uint8_t *)(((sysarg_t *) src) + i))[j];
-	}
-		
-	return (char *) dst;
+	for (i = 0; i < cnt; i++)
+		ptr[i] = val;
 }
 
 /** Move memory block with possible overlapping.
  *
- * Copy cnt bytes from src address to dst address. The source and destination
- * memory areas may overlap.
+ * Copy cnt bytes from src address to dst address. The source
+ * and destination memory areas may overlap.
  *
- * @param src		Source address to copy from.
- * @param dst		Destination address to copy to.
- * @param cnt		Number of bytes to copy.
+ * @param dst Destination address to copy to.
+ * @param src Source address to copy from.
+ * @param cnt Number of bytes to copy.
  *
- * @return		Destination address.
+ * @return Destination address.
+ *
  */
-void *memmove(void *dst, const void *src, size_t n)
+void *memmove(void *dst, const void *src, size_t cnt)
 {
-	const uint8_t *sp;
-	uint8_t *dp;
-
 	/* Nothing to do? */
 	if (src == dst)
 		return dst;
-
+	
 	/* Non-overlapping? */
-	if (dst >= src + n || src >= dst + n) {	
-		return memcpy(dst, src, n);
-	}
-
+	if ((dst >= src + cnt) || (src >= dst + cnt))
+		return memcpy(dst, src, cnt);
+	
+	uint8_t *dp;
+	const uint8_t *sp;
+	
 	/* Which direction? */
 	if (src > dst) {
 		/* Forwards. */
+		dp = dst;
 		sp = src;
-		dp = dst;
-
-		while (n-- != 0)
+		
+		while (cnt-- != 0)
 			*dp++ = *sp++;
 	} else {
 		/* Backwards. */
-		sp = src + (n - 1);
-		dp = dst + (n - 1);
-
-		while (n-- != 0)
+		dp = dst + (cnt - 1);
+		sp = src + (cnt - 1);
+		
+		while (cnt-- != 0)
 			*dp-- = *sp--;
 	}
-
+	
 	return dst;
-}
-
-/** Fill block of memory
- *
- * Fill cnt bytes at dst address with the value x.  The filling is done
- * byte-by-byte.
- *
- * @param dst		Destination address to fill.
- * @param cnt		Number of bytes to fill.
- * @param x		Value to fill.
- *
- */
-void _memsetb(void *dst, size_t cnt, uint8_t x)
-{
-	unsigned int i;
-	uint8_t *p = (uint8_t *) dst;
-	
-	for (i = 0; i < cnt; i++)
-		p[i] = x;
-}
-
-/** Fill block of memory.
- *
- * Fill cnt words at dst address with the value x.  The filling is done
- * word-by-word.
- *
- * @param dst		Destination address to fill.
- * @param cnt		Number of words to fill.
- * @param x		Value to fill.
- *
- */
-void _memsetw(void *dst, size_t cnt, uint16_t x)
-{
-	unsigned int i;
-	uint16_t *p = (uint16_t *) dst;
-	
-	for (i = 0; i < cnt; i++)
-		p[i] = x;	
 }
 
Index: kernel/generic/src/lib/rd.c
===================================================================
--- kernel/generic/src/lib/rd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/lib/rd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -91,4 +91,5 @@
 	rd_parea.frames = SIZE2FRAMES(dsize);
 	rd_parea.unpriv = false;
+	rd_parea.mapped = false;
 	ddi_parea_register(&rd_parea);
 
Index: kernel/generic/src/lib/str.c
===================================================================
--- kernel/generic/src/lib/str.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/lib/str.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -922,21 +922,21 @@
 void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
 {
-	if (val > 10000000000000000000ULL) {
-		*rv = val / 1000000000000000000ULL;
+	if (val > UINT64_C(10000000000000000000)) {
+		*rv = val / UINT64_C(1000000000000000000);
 		*suffix = 'Z';
-	} else if (val > 1000000000000000000ULL) {
-		*rv = val / 1000000000000000ULL;
+	} else if (val > UINT64_C(1000000000000000000)) {
+		*rv = val / UINT64_C(1000000000000000);
 		*suffix = 'E';
-	} else if (val > 1000000000000000ULL) {
-		*rv = val / 1000000000000ULL;
+	} else if (val > UINT64_C(1000000000000000)) {
+		*rv = val / UINT64_C(1000000000000);
 		*suffix = 'T';
-	} else if (val > 1000000000000ULL) {
-		*rv = val / 1000000000ULL;
+	} else if (val > UINT64_C(1000000000000)) {
+		*rv = val / UINT64_C(1000000000);
 		*suffix = 'G';
-	} else if (val > 1000000000ULL) {
-		*rv = val / 1000000ULL;
+	} else if (val > UINT64_C(1000000000)) {
+		*rv = val / UINT64_C(1000000);
 		*suffix = 'M';
-	} else if (val > 1000000ULL) {
-		*rv = val / 1000ULL;
+	} else if (val > UINT64_C(1000000)) {
+		*rv = val / UINT64_C(1000);
 		*suffix = 'k';
 	} else {
@@ -946,4 +946,31 @@
 }
 
+void bin_order_suffix(const uint64_t val, uint64_t *rv, const char **suffix,
+    bool fixed)
+{
+	if (val > UINT64_C(1152921504606846976)) {
+		*rv = val / UINT64_C(1125899906842624);
+		*suffix = "EiB";
+	} else if (val > UINT64_C(1125899906842624)) {
+		*rv = val / UINT64_C(1099511627776);
+		*suffix = "TiB";
+	} else if (val > UINT64_C(1099511627776)) {
+		*rv = val / UINT64_C(1073741824);
+		*suffix = "GiB";
+	} else if (val > UINT64_C(1073741824)) {
+		*rv = val / UINT64_C(1048576);
+		*suffix = "MiB";
+	} else if (val > UINT64_C(1048576)) {
+		*rv = val / UINT64_C(1024);
+		*suffix = "KiB";
+	} else {
+		*rv = val;
+		if (fixed)
+			*suffix = "B  ";
+		else
+			*suffix = "B";
+	}
+}
+
 /** @}
  */
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/main/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -58,5 +58,4 @@
 #include <proc/thread.h>
 #include <proc/task.h>
-#include <proc/tasklet.h>
 #include <main/kinit.h>
 #include <main/version.h>
@@ -72,4 +71,5 @@
 #include <mm/as.h>
 #include <mm/slab.h>
+#include <mm/reserve.h>
 #include <synch/waitq.h>
 #include <synch/futex.h>
@@ -118,6 +118,4 @@
 #endif
 
-#define CONFIG_STACK_SIZE  ((1 << STACK_FRAMES) * STACK_SIZE)
-
 /** Main kernel routine for bootstrap CPU.
  *
@@ -139,5 +137,5 @@
 	config.kernel_size = ALIGN_UP(hardcoded_ktext_size +
 	    hardcoded_kdata_size, PAGE_SIZE);
-	config.stack_size = CONFIG_STACK_SIZE;
+	config.stack_size = STACK_SIZE;
 	
 	/* Initialy the stack is placed just after the kernel */
@@ -165,6 +163,6 @@
 	
 	context_save(&ctx);
-	context_set(&ctx, FADDR(main_bsp_separated_stack), config.stack_base,
-	    THREAD_STACK_SIZE);
+	context_set(&ctx, FADDR(main_bsp_separated_stack),
+	    config.stack_base, STACK_SIZE);
 	context_restore(&ctx);
 	/* not reached */
@@ -217,6 +215,6 @@
 	tlb_init();
 	ddi_init();
-	tasklet_init();
 	arch_post_mm_init();
+	reserve_init();
 	arch_pre_smp_init();
 	smp_init();
@@ -225,6 +223,9 @@
 	slab_enable_cpucache();
 	
-	printf("Detected %u CPU(s), %" PRIu64 " MiB free memory\n",
-	    config.cpu_count, SIZE2MB(zones_total_size()));
+	uint64_t size;
+	const char *size_suffix;
+	bin_order_suffix(zones_total_size(), &size, &size_suffix, false);
+	printf("Detected %u CPU(s), %" PRIu64 " %s free memory\n",
+	    config.cpu_count, size, size_suffix);
 	
 	cpu_init();
@@ -320,5 +321,5 @@
 	context_save(&CPU->saved_context);
 	context_set(&CPU->saved_context, FADDR(main_ap_separated_stack),
-	    (uintptr_t) CPU->stack, CPU_STACK_SIZE);
+	    (uintptr_t) CPU->stack, STACK_SIZE);
 	context_restore(&CPU->saved_context);
 	/* not reached */
Index: kernel/generic/src/main/uinit.c
===================================================================
--- kernel/generic/src/main/uinit.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/main/uinit.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,5 +33,5 @@
 /**
  * @file
- * @brief	Userspace bootstrap thread.
+ * @brief Userspace bootstrap thread.
  *
  * This file contains uinit kernel thread wich is used to start every
@@ -40,5 +40,5 @@
  * @see SYS_THREAD_CREATE
  */
- 
+
 #include <main/uinit.h>
 #include <typedefs.h>
@@ -48,5 +48,4 @@
 #include <arch.h>
 #include <udebug/udebug.h>
-
 
 /** Thread used to bring up userspace thread.
@@ -58,5 +57,5 @@
 {
 	uspace_arg_t uarg;
-
+	
 	/*
 	 * So far, we don't have a use for joining userspace threads so we
@@ -68,5 +67,5 @@
 	 */
 	thread_detach(THREAD);
-
+	
 #ifdef CONFIG_UDEBUG
 	udebug_stoppable_end();
@@ -78,5 +77,5 @@
 	uarg.uspace_thread_function = NULL;
 	uarg.uspace_thread_arg = NULL;
-
+	
 	free((uspace_arg_t *) arg);
 	
Index: kernel/generic/src/main/version.c
===================================================================
--- kernel/generic/src/main/version.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/main/version.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 
 static const char *project = "SPARTAN kernel";
-static const char *copyright = "Copyright (c) 2001-2010 HelenOS project";
+static const char *copyright = "Copyright (c) 2001-2011 HelenOS project";
 static const char *release = STRING(RELEASE);
 static const char *name = STRING(NAME);
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/mm/as.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -80,8 +80,4 @@
 #include <arch/interrupt.h>
 
-#ifdef CONFIG_VIRT_IDX_DCACHE
-#include <arch/mm/cache.h>
-#endif /* CONFIG_VIRT_IDX_DCACHE */
-
 /**
  * Each architecture decides what functions will be used to carry out
@@ -98,5 +94,5 @@
  *
  * This lock protects:
- * - inactive_as_with_asid_head list
+ * - inactive_as_with_asid_list
  * - as->asid for each as of the as_t type
  * - asids_allocated counter
@@ -109,5 +105,5 @@
  * that have valid ASID.
  */
-LIST_INITIALIZE(inactive_as_with_asid_head);
+LIST_INITIALIZE(inactive_as_with_asid_list);
 
 /** Kernel address space. */
@@ -239,8 +235,8 @@
 	bool cond = true;
 	while (cond) {
-		ASSERT(!list_empty(&as->as_area_btree.leaf_head));
+		ASSERT(!list_empty(&as->as_area_btree.leaf_list));
 		
 		btree_node_t *node =
-		    list_get_instance(as->as_area_btree.leaf_head.next,
+		    list_get_instance(list_first(&as->as_area_btree.leaf_list),
 		    btree_node_t, leaf_link);
 		
@@ -306,5 +302,5 @@
 	 * We don't want any area to have conflicts with NULL page.
 	 */
-	if (overlaps(addr, count << PAGE_WIDTH, (uintptr_t) NULL, PAGE_SIZE))
+	if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
 		return false;
 	
@@ -333,6 +329,6 @@
 			mutex_lock(&area->lock);
 			
-			if (overlaps(addr, count << PAGE_WIDTH,
-			    area->base, area->pages << PAGE_WIDTH)) {
+			if (overlaps(addr, P2SZ(count), area->base,
+			    P2SZ(area->pages))) {
 				mutex_unlock(&area->lock);
 				return false;
@@ -350,6 +346,6 @@
 			mutex_lock(&area->lock);
 			
-			if (overlaps(addr, count << PAGE_WIDTH,
-			    area->base, area->pages << PAGE_WIDTH)) {
+			if (overlaps(addr, P2SZ(count), area->base,
+			    P2SZ(area->pages))) {
 				mutex_unlock(&area->lock);
 				return false;
@@ -370,6 +366,6 @@
 		mutex_lock(&area->lock);
 		
-		if (overlaps(addr, count << PAGE_WIDTH,
-		    area->base, area->pages << PAGE_WIDTH)) {
+		if (overlaps(addr, P2SZ(count), area->base,
+		    P2SZ(area->pages))) {
 			mutex_unlock(&area->lock);
 			return false;
@@ -384,6 +380,5 @@
 	 */
 	if (!KERNEL_ADDRESS_SPACE_SHADOWED) {
-		return !overlaps(addr, count << PAGE_WIDTH,
-		    KERNEL_ADDRESS_SPACE_START,
+		return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START,
 		    KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);
 	}
@@ -448,4 +443,12 @@
 		memsetb(&area->backend_data, sizeof(area->backend_data), 0);
 	
+	if (area->backend && area->backend->create) {
+		if (!area->backend->create(area)) {
+			free(area);
+			mutex_unlock(&as->lock);
+			return NULL;
+		}
+	}
+	
 	btree_create(&area->used_space);
 	btree_insert(&as->as_area_btree, base, (void *) area, NULL);
@@ -470,5 +473,6 @@
 	
 	btree_node_t *leaf;
-	as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);
+	as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va,
+	    &leaf);
 	if (area) {
 		/* va is the base address of an address space area */
@@ -478,5 +482,5 @@
 	
 	/*
-	 * Search the leaf node and the righmost record of its left neighbour
+	 * Search the leaf node and the rightmost record of its left neighbour
 	 * to find out whether this is a miss or va belongs to an address
 	 * space area found there.
@@ -490,7 +494,7 @@
 		
 		mutex_lock(&area->lock);
-		
+
 		if ((area->base <= va) &&
-		    (va < area->base + (area->pages << PAGE_WIDTH)))
+		    (va <= area->base + (P2SZ(area->pages) - 1)))
 			return area;
 		
@@ -502,5 +506,6 @@
 	 * Because of its position in the B+tree, it must have base < va.
 	 */
-	btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);
+	btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree,
+	    leaf);
 	if (lnode) {
 		area = (as_area_t *) lnode->value[lnode->keys - 1];
@@ -508,5 +513,5 @@
 		mutex_lock(&area->lock);
 		
-		if (va < area->base + (area->pages << PAGE_WIDTH))
+		if (va <= area->base + (P2SZ(area->pages) - 1))
 			return area;
 		
@@ -573,5 +578,5 @@
 	
 	if (pages < area->pages) {
-		uintptr_t start_free = area->base + (pages << PAGE_WIDTH);
+		uintptr_t start_free = area->base + P2SZ(pages);
 		
 		/*
@@ -586,5 +591,5 @@
 		 */
 		ipl_t ipl = tlb_shootdown_start(TLB_INVL_PAGES, as->asid,
-		    area->base + (pages << PAGE_WIDTH), area->pages - pages);
+		    area->base + P2SZ(pages), area->pages - pages);
 		
 		/*
@@ -597,8 +602,8 @@
 		bool cond = true;
 		while (cond) {
-			ASSERT(!list_empty(&area->used_space.leaf_head));
+			ASSERT(!list_empty(&area->used_space.leaf_list));
 			
 			btree_node_t *node =
-			    list_get_instance(area->used_space.leaf_head.prev,
+			    list_get_instance(list_last(&area->used_space.leaf_list),
 			    btree_node_t, leaf_link);
 			
@@ -609,8 +614,8 @@
 				size_t i = 0;
 				
-				if (overlaps(ptr, size << PAGE_WIDTH, area->base,
-				    pages << PAGE_WIDTH)) {
+				if (overlaps(ptr, P2SZ(size), area->base,
+				    P2SZ(pages))) {
 					
-					if (ptr + (size << PAGE_WIDTH) <= start_free) {
+					if (ptr + P2SZ(size) <= start_free) {
 						/*
 						 * The whole interval fits
@@ -643,6 +648,6 @@
 				
 				for (; i < size; i++) {
-					pte_t *pte = page_mapping_find(as, ptr +
-					    (i << PAGE_WIDTH));
+					pte_t *pte = page_mapping_find(as,
+					    ptr + P2SZ(i), false);
 					
 					ASSERT(pte);
@@ -653,10 +658,9 @@
 					    (area->backend->frame_free)) {
 						area->backend->frame_free(area,
-						    ptr + (i << PAGE_WIDTH),
+						    ptr + P2SZ(i),
 						    PTE_GET_FRAME(pte));
 					}
 					
-					page_mapping_remove(as, ptr +
-					    (i << PAGE_WIDTH));
+					page_mapping_remove(as, ptr + P2SZ(i));
 				}
 			}
@@ -667,12 +671,13 @@
 		 */
 		
-		tlb_invalidate_pages(as->asid, area->base + (pages << PAGE_WIDTH),
+		tlb_invalidate_pages(as->asid, area->base + P2SZ(pages),
 		    area->pages - pages);
 		
 		/*
-		 * Invalidate software translation caches (e.g. TSB on sparc64).
-		 */
-		as_invalidate_translation_cache(as, area->base +
-		    (pages << PAGE_WIDTH), area->pages - pages);
+		 * Invalidate software translation caches
+		 * (e.g. TSB on sparc64, PHT on ppc32).
+		 */
+		as_invalidate_translation_cache(as, area->base + P2SZ(pages),
+		    area->pages - pages);
 		tlb_shootdown_finalize(ipl);
 		
@@ -690,4 +695,12 @@
 	}
 	
+	if (area->backend && area->backend->resize) {
+		if (!area->backend->resize(area, pages)) {
+			mutex_unlock(&area->lock);
+			mutex_unlock(&as->lock);
+			return ENOMEM;
+		}
+	}
+	
 	area->pages = pages;
 	
@@ -714,5 +727,4 @@
 	if (--sh_info->refcount == 0) {
 		dealloc = true;
-		link_t *cur;
 		
 		/*
@@ -720,6 +732,5 @@
 		 * reference from all frames found there.
 		 */
-		for (cur = sh_info->pagemap.leaf_head.next;
-		    cur != &sh_info->pagemap.leaf_head; cur = cur->next) {
+		list_foreach(sh_info->pagemap.leaf_list, cur) {
 			btree_node_t *node
 			    = list_get_instance(cur, btree_node_t, leaf_link);
@@ -756,4 +767,7 @@
 		return ENOENT;
 	}
+
+	if (area->backend && area->backend->destroy)
+		area->backend->destroy(area);
 	
 	uintptr_t base = area->base;
@@ -770,7 +784,5 @@
 	 * Visit only the pages mapped by used_space B+tree.
 	 */
-	link_t *cur;
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
+	list_foreach(area->used_space.leaf_list, cur) {
 		btree_node_t *node;
 		btree_key_t i;
@@ -782,6 +794,6 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte =
-				    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
+				pte_t *pte = page_mapping_find(as,
+				     ptr + P2SZ(size), false);
 				
 				ASSERT(pte);
@@ -792,8 +804,9 @@
 				    (area->backend->frame_free)) {
 					area->backend->frame_free(area,
-					    ptr + (size << PAGE_WIDTH), PTE_GET_FRAME(pte));
+					    ptr + P2SZ(size),
+					    PTE_GET_FRAME(pte));
 				}
 				
-				page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
+				page_mapping_remove(as, ptr + P2SZ(size));
 			}
 		}
@@ -807,6 +820,6 @@
 	
 	/*
-	 * Invalidate potential software translation caches (e.g. TSB on
-	 * sparc64).
+	 * Invalidate potential software translation caches
+	 * (e.g. TSB on sparc64, PHT on ppc32).
 	 */
 	as_invalidate_translation_cache(as, area->base, area->pages);
@@ -882,5 +895,5 @@
 	}
 	
-	size_t src_size = src_area->pages << PAGE_WIDTH;
+	size_t src_size = P2SZ(src_area->pages);
 	unsigned int src_flags = src_area->flags;
 	mem_backend_t *src_backend = src_area->backend;
@@ -1048,8 +1061,6 @@
 	 */
 	size_t used_pages = 0;
-	link_t *cur;
-	
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
+	
+	list_foreach(area->used_space.leaf_list, cur) {
 		btree_node_t *node
 		    = list_get_instance(cur, btree_node_t, leaf_link);
@@ -1077,8 +1088,7 @@
 	size_t frame_idx = 0;
 	
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
-		btree_node_t *node
-		    = list_get_instance(cur, btree_node_t, leaf_link);
+	list_foreach(area->used_space.leaf_list, cur) {
+		btree_node_t *node = list_get_instance(cur, btree_node_t,
+		    leaf_link);
 		btree_key_t i;
 		
@@ -1088,6 +1098,6 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte =
-				    page_mapping_find(as, ptr + (size << PAGE_WIDTH));
+				pte_t *pte = page_mapping_find(as,
+				    ptr + P2SZ(size), false);
 				
 				ASSERT(pte);
@@ -1098,5 +1108,5 @@
 				
 				/* Remove old mapping */
-				page_mapping_remove(as, ptr + (size << PAGE_WIDTH));
+				page_mapping_remove(as, ptr + P2SZ(size));
 			}
 		}
@@ -1110,6 +1120,6 @@
 	
 	/*
-	 * Invalidate potential software translation caches (e.g. TSB on
-	 * sparc64).
+	 * Invalidate potential software translation caches
+	 * (e.g. TSB on sparc64, PHT on ppc32).
 	 */
 	as_invalidate_translation_cache(as, area->base, area->pages);
@@ -1130,6 +1140,5 @@
 	frame_idx = 0;
 	
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
+	list_foreach(area->used_space.leaf_list, cur) {
 		btree_node_t *node
 		    = list_get_instance(cur, btree_node_t, leaf_link);
@@ -1144,5 +1153,5 @@
 				
 				/* Insert the new mapping */
-				page_mapping_insert(as, ptr + (size << PAGE_WIDTH),
+				page_mapping_insert(as, ptr + P2SZ(size),
 				    old_frame[frame_idx++], page_flags);
 				
@@ -1225,5 +1234,5 @@
 	 */
 	pte_t *pte;
-	if ((pte = page_mapping_find(AS, page))) {
+	if ((pte = page_mapping_find(AS, page, false))) {
 		if (PTE_PRESENT(pte)) {
 			if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) ||
@@ -1275,5 +1284,5 @@
  * thing which is forbidden in this context is locking the address space.
  *
- * When this function is enetered, no spinlocks may be held.
+ * When this function is entered, no spinlocks may be held.
  *
  * @param old Old address space or NULL.
@@ -1317,5 +1326,5 @@
 			
 			list_append(&old_as->inactive_as_with_asid_link,
-			    &inactive_as_with_asid_head);
+			    &inactive_as_with_asid_list);
 		}
 		
@@ -1466,5 +1475,5 @@
 	
 	if (src_area) {
-		size = src_area->pages << PAGE_WIDTH;
+		size = P2SZ(src_area->pages);
 		mutex_unlock(&src_area->lock);
 	} else
@@ -1521,14 +1530,14 @@
 		if (page >= right_pg) {
 			/* Do nothing. */
-		} else if (overlaps(page, count << PAGE_WIDTH, left_pg,
-		    left_cnt << PAGE_WIDTH)) {
+		} else if (overlaps(page, P2SZ(count), left_pg,
+		    P2SZ(left_cnt))) {
 			/* The interval intersects with the left interval. */
 			return false;
-		} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
-		    right_cnt << PAGE_WIDTH)) {
+		} else if (overlaps(page, P2SZ(count), right_pg,
+		    P2SZ(right_cnt))) {
 			/* The interval intersects with the right interval. */
 			return false;
-		} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
-		    (page + (count << PAGE_WIDTH) == right_pg)) {
+		} else if ((page == left_pg + P2SZ(left_cnt)) &&
+		    (page + P2SZ(count) == right_pg)) {
 			/*
 			 * The interval can be added by merging the two already
@@ -1538,5 +1547,5 @@
 			btree_remove(&area->used_space, right_pg, leaf);
 			goto success;
-		} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
+		} else if (page == left_pg + P2SZ(left_cnt)) {
 			/*
 			 * The interval can be added by simply growing the left
@@ -1545,5 +1554,5 @@
 			node->value[node->keys - 1] += count;
 			goto success;
-		} else if (page + (count << PAGE_WIDTH) == right_pg) {
+		} else if (page + P2SZ(count) == right_pg) {
 			/*
 			 * The interval can be addded by simply moving base of
@@ -1572,9 +1581,8 @@
 		 */
 		
-		if (overlaps(page, count << PAGE_WIDTH, right_pg,
-		    right_cnt << PAGE_WIDTH)) {
+		if (overlaps(page, P2SZ(count), right_pg, P2SZ(right_cnt))) {
 			/* The interval intersects with the right interval. */
 			return false;
-		} else if (page + (count << PAGE_WIDTH) == right_pg) {
+		} else if (page + P2SZ(count) == right_pg) {
 			/*
 			 * The interval can be added by moving the base of the
@@ -1611,14 +1619,14 @@
 		if (page < left_pg) {
 			/* Do nothing. */
-		} else if (overlaps(page, count << PAGE_WIDTH, left_pg,
-		    left_cnt << PAGE_WIDTH)) {
+		} else if (overlaps(page, P2SZ(count), left_pg,
+		    P2SZ(left_cnt))) {
 			/* The interval intersects with the left interval. */
 			return false;
-		} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
-		    right_cnt << PAGE_WIDTH)) {
+		} else if (overlaps(page, P2SZ(count), right_pg,
+		    P2SZ(right_cnt))) {
 			/* The interval intersects with the right interval. */
 			return false;
-		} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
-		    (page + (count << PAGE_WIDTH) == right_pg)) {
+		} else if ((page == left_pg + P2SZ(left_cnt)) &&
+		    (page + P2SZ(count) == right_pg)) {
 			/*
 			 * The interval can be added by merging the two already
@@ -1628,5 +1636,5 @@
 			btree_remove(&area->used_space, right_pg, node);
 			goto success;
-		} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
+		} else if (page == left_pg + P2SZ(left_cnt)) {
 			/*
 			 * The interval can be added by simply growing the left
@@ -1635,5 +1643,5 @@
 			leaf->value[leaf->keys - 1] += count;
 			goto success;
-		} else if (page + (count << PAGE_WIDTH) == right_pg) {
+		} else if (page + P2SZ(count) == right_pg) {
 			/*
 			 * The interval can be addded by simply moving base of
@@ -1662,9 +1670,8 @@
 		 */
 		
-		if (overlaps(page, count << PAGE_WIDTH, left_pg,
-		    left_cnt << PAGE_WIDTH)) {
+		if (overlaps(page, P2SZ(count), left_pg, P2SZ(left_cnt))) {
 			/* The interval intersects with the left interval. */
 			return false;
-		} else if (left_pg + (left_cnt << PAGE_WIDTH) == page) {
+		} else if (left_pg + P2SZ(left_cnt) == page) {
 			/*
 			 * The interval can be added by growing the left
@@ -1701,6 +1708,6 @@
 			 */
 			
-			if (overlaps(page, count << PAGE_WIDTH, left_pg,
-			    left_cnt << PAGE_WIDTH)) {
+			if (overlaps(page, P2SZ(count), left_pg,
+			    P2SZ(left_cnt))) {
 				/*
 				 * The interval intersects with the left
@@ -1708,6 +1715,6 @@
 				 */
 				return false;
-			} else if (overlaps(page, count << PAGE_WIDTH, right_pg,
-			    right_cnt << PAGE_WIDTH)) {
+			} else if (overlaps(page, P2SZ(count), right_pg,
+			    P2SZ(right_cnt))) {
 				/*
 				 * The interval intersects with the right
@@ -1715,6 +1722,6 @@
 				 */
 				return false;
-			} else if ((page == left_pg + (left_cnt << PAGE_WIDTH)) &&
-			    (page + (count << PAGE_WIDTH) == right_pg)) {
+			} else if ((page == left_pg + P2SZ(left_cnt)) &&
+			    (page + P2SZ(count) == right_pg)) {
 				/*
 				 * The interval can be added by merging the two
@@ -1724,5 +1731,5 @@
 				btree_remove(&area->used_space, right_pg, leaf);
 				goto success;
-			} else if (page == left_pg + (left_cnt << PAGE_WIDTH)) {
+			} else if (page == left_pg + P2SZ(left_cnt)) {
 				/*
 				 * The interval can be added by simply growing
@@ -1731,5 +1738,5 @@
 				leaf->value[i - 1] += count;
 				goto success;
-			} else if (page + (count << PAGE_WIDTH) == right_pg) {
+			} else if (page + P2SZ(count) == right_pg) {
 				/*
 				 * The interval can be addded by simply moving
@@ -1797,5 +1804,5 @@
 			for (i = 0; i < leaf->keys; i++) {
 				if (leaf->key[i] == page) {
-					leaf->key[i] += count << PAGE_WIDTH;
+					leaf->key[i] += P2SZ(count);
 					leaf->value[i] -= count;
 					goto success;
@@ -1807,13 +1814,12 @@
 	}
 	
-	btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space, leaf);
+	btree_node_t *node = btree_leaf_node_left_neighbour(&area->used_space,
+	    leaf);
 	if ((node) && (page < leaf->key[0])) {
 		uintptr_t left_pg = node->key[node->keys - 1];
 		size_t left_cnt = (size_t) node->value[node->keys - 1];
 		
-		if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
-		    count << PAGE_WIDTH)) {
-			if (page + (count << PAGE_WIDTH) ==
-			    left_pg + (left_cnt << PAGE_WIDTH)) {
+		if (overlaps(left_pg, P2SZ(left_cnt), page, P2SZ(count))) {
+			if (page + P2SZ(count) == left_pg + P2SZ(left_cnt)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1824,6 +1830,8 @@
 				node->value[node->keys - 1] -= count;
 				goto success;
-			} else if (page + (count << PAGE_WIDTH) <
-			    left_pg + (left_cnt << PAGE_WIDTH)) {
+			} else if (page + P2SZ(count) <
+			    left_pg + P2SZ(left_cnt)) {
+				size_t new_cnt;
+
 				/*
 				 * The interval is contained in the rightmost
@@ -1833,9 +1841,9 @@
 				 * new interval.
 				 */
-				size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
-				    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
+				new_cnt = ((left_pg + P2SZ(left_cnt)) -
+				    (page + P2SZ(count))) >> PAGE_WIDTH;
 				node->value[node->keys - 1] -= count + new_cnt;
 				btree_insert(&area->used_space, page +
-				    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
+				    P2SZ(count), (void *) new_cnt, leaf);
 				goto success;
 			}
@@ -1850,8 +1858,6 @@
 		size_t left_cnt = (size_t) leaf->value[leaf->keys - 1];
 		
-		if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
-		    count << PAGE_WIDTH)) {
-			if (page + (count << PAGE_WIDTH) ==
-			    left_pg + (left_cnt << PAGE_WIDTH)) {
+		if (overlaps(left_pg, P2SZ(left_cnt), page, P2SZ(count))) {
+			if (page + P2SZ(count) == left_pg + P2SZ(left_cnt)) {
 				/*
 				 * The interval is contained in the rightmost
@@ -1861,6 +1867,8 @@
 				leaf->value[leaf->keys - 1] -= count;
 				goto success;
-			} else if (page + (count << PAGE_WIDTH) < left_pg +
-			    (left_cnt << PAGE_WIDTH)) {
+			} else if (page + P2SZ(count) < left_pg +
+			    P2SZ(left_cnt)) {
+				size_t new_cnt;
+
 				/*
 				 * The interval is contained in the rightmost
@@ -1870,9 +1878,9 @@
 				 * interval.
 				 */
-				size_t new_cnt = ((left_pg + (left_cnt << PAGE_WIDTH)) -
-				    (page + (count << PAGE_WIDTH))) >> PAGE_WIDTH;
+				new_cnt = ((left_pg + P2SZ(left_cnt)) -
+				    (page + P2SZ(count))) >> PAGE_WIDTH;
 				leaf->value[leaf->keys - 1] -= count + new_cnt;
 				btree_insert(&area->used_space, page +
-				    (count << PAGE_WIDTH), (void *) new_cnt, leaf);
+				    P2SZ(count), (void *) new_cnt, leaf);
 				goto success;
 			}
@@ -1896,8 +1904,8 @@
 			 * to (i - 1) and i.
 			 */
-			if (overlaps(left_pg, left_cnt << PAGE_WIDTH, page,
-			    count << PAGE_WIDTH)) {
-				if (page + (count << PAGE_WIDTH) ==
-				    left_pg + (left_cnt << PAGE_WIDTH)) {
+			if (overlaps(left_pg, P2SZ(left_cnt), page,
+			    P2SZ(count))) {
+				if (page + P2SZ(count) ==
+				    left_pg + P2SZ(left_cnt)) {
 					/*
 					 * The interval is contained in the
@@ -1908,6 +1916,8 @@
 					leaf->value[i - 1] -= count;
 					goto success;
-				} else if (page + (count << PAGE_WIDTH) <
-				    left_pg + (left_cnt << PAGE_WIDTH)) {
+				} else if (page + P2SZ(count) <
+				    left_pg + P2SZ(left_cnt)) {
+					size_t new_cnt;
+
 					/*
 					 * The interval is contained in the
@@ -1917,11 +1927,10 @@
 					 * also inserting a new interval.
 					 */
-					size_t new_cnt = ((left_pg +
-					    (left_cnt << PAGE_WIDTH)) -
-					    (page + (count << PAGE_WIDTH))) >>
+					new_cnt = ((left_pg + P2SZ(left_cnt)) -
+					    (page + P2SZ(count))) >>
 					    PAGE_WIDTH;
 					leaf->value[i - 1] -= count + new_cnt;
 					btree_insert(&area->used_space, page +
-					    (count << PAGE_WIDTH), (void *) new_cnt,
+					    P2SZ(count), (void *) new_cnt,
 					    leaf);
 					goto success;
@@ -2010,8 +2019,8 @@
 	
 	/* Eventually check the addresses behind each area */
-	link_t *cur;
-	for (cur = AS->as_area_btree.leaf_head.next;
-	    (ret == 0) && (cur != &AS->as_area_btree.leaf_head);
-	    cur = cur->next) {
+	list_foreach(AS->as_area_btree.leaf_list, cur) {
+		if (ret != 0)
+			break;
+
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
@@ -2019,10 +2028,11 @@
 		btree_key_t i;
 		for (i = 0; (ret == 0) && (i < node->keys); i++) {
+			uintptr_t addr;
+
 			as_area_t *area = (as_area_t *) node->value[i];
 			
 			mutex_lock(&area->lock);
 			
-			uintptr_t addr =
-			    ALIGN_UP(area->base + (area->pages << PAGE_WIDTH),
+			addr = ALIGN_UP(area->base + P2SZ(area->pages),
 			    PAGE_SIZE);
 			
@@ -2054,8 +2064,6 @@
 	
 	size_t area_cnt = 0;
-	link_t *cur;
-	
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
@@ -2070,6 +2078,5 @@
 	size_t area_idx = 0;
 	
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
@@ -2083,5 +2090,5 @@
 			
 			info[area_idx].start_addr = area->base;
-			info[area_idx].size = FRAMES2SIZE(area->pages);
+			info[area_idx].size = P2SZ(area->pages);
 			info[area_idx].flags = area->flags;
 			++area_idx;
@@ -2107,7 +2114,5 @@
 	
 	/* Print out info about address space areas */
-	link_t *cur;
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node
 		    = list_get_instance(cur, btree_node_t, leaf_link);
@@ -2121,5 +2126,5 @@
 			    " (%p - %p)\n", area, (void *) area->base,
 			    area->pages, (void *) area->base,
-			    (void *) (area->base + FRAMES2SIZE(area->pages)));
+			    (void *) (area->base + P2SZ(area->pages)));
 			mutex_unlock(&area->lock);
 		}
Index: kernel/generic/src/mm/backend_anon.c
===================================================================
--- kernel/generic/src/mm/backend_anon.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/mm/backend_anon.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,4 +39,5 @@
 #include <mm/as.h>
 #include <mm/page.h>
+#include <mm/reserve.h>
 #include <genarch/mm/page_pt.h>
 #include <genarch/mm/page_ht.h>
@@ -49,19 +50,95 @@
 #include <typedefs.h>
 #include <align.h>
+#include <memstr.h>
 #include <arch.h>
 
-#ifdef CONFIG_VIRT_IDX_DCACHE
-#include <arch/mm/cache.h>
-#endif
-
-static int anon_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
-static void anon_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame);
-static void anon_share(as_area_t *area);
+static bool anon_create(as_area_t *);
+static bool anon_resize(as_area_t *, size_t);
+static void anon_share(as_area_t *);
+static void anon_destroy(as_area_t *);
+
+static int anon_page_fault(as_area_t *, uintptr_t, pf_access_t);
+static void anon_frame_free(as_area_t *, uintptr_t, uintptr_t);
 
 mem_backend_t anon_backend = {
+	.create = anon_create,
+	.resize = anon_resize,
+	.share = anon_share,
+	.destroy = anon_destroy,
+
 	.page_fault = anon_page_fault,
 	.frame_free = anon_frame_free,
-	.share = anon_share
 };
+
+bool anon_create(as_area_t *area)
+{
+	return reserve_try_alloc(area->pages);
+}
+
+bool anon_resize(as_area_t *area, size_t new_pages)
+{
+	if (new_pages > area->pages)
+		return reserve_try_alloc(new_pages - area->pages);
+	else if (new_pages < area->pages)
+		reserve_free(area->pages - new_pages);
+
+	return true;
+}
+
+/** Share the anonymous address space area.
+ *
+ * Sharing of anonymous area is done by duplicating its entire mapping
+ * to the pagemap. Page faults will primarily search for frames there.
+ *
+ * The address space and address space area must be already locked.
+ *
+ * @param area Address space area to be shared.
+ */
+void anon_share(as_area_t *area)
+{
+	ASSERT(mutex_locked(&area->as->lock));
+	ASSERT(mutex_locked(&area->lock));
+
+	/*
+	 * Copy used portions of the area to sh_info's page map.
+	 */
+	mutex_lock(&area->sh_info->lock);
+	list_foreach(area->used_space.leaf_list, cur) {
+		btree_node_t *node;
+		unsigned int i;
+		
+		node = list_get_instance(cur, btree_node_t, leaf_link);
+		for (i = 0; i < node->keys; i++) {
+			uintptr_t base = node->key[i];
+			size_t count = (size_t) node->value[i];
+			unsigned int j;
+			
+			for (j = 0; j < count; j++) {
+				pte_t *pte;
+			
+				page_table_lock(area->as, false);
+				pte = page_mapping_find(area->as,
+				    base + P2SZ(j), false);
+				ASSERT(pte && PTE_VALID(pte) &&
+				    PTE_PRESENT(pte));
+				btree_insert(&area->sh_info->pagemap,
+				    (base + P2SZ(j)) - area->base,
+				    (void *) PTE_GET_FRAME(pte), NULL);
+				page_table_unlock(area->as, false);
+
+				pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
+				frame_reference_add(pfn);
+			}
+
+		}
+	}
+	mutex_unlock(&area->sh_info->lock);
+}
+
+void anon_destroy(as_area_t *area)
+{
+	reserve_free(area->pages);
+}
+
 
 /** Service a page fault in the anonymous memory address space area.
@@ -115,5 +192,6 @@
 			}
 			if (allocate) {
-				frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
+				frame = (uintptr_t) frame_alloc_noreserve(
+				    ONE_FRAME, 0);
 				memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
 				
@@ -145,5 +223,5 @@
 		 *   the different causes
 		 */
-		frame = (uintptr_t) frame_alloc(ONE_FRAME, 0);
+		frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
 		memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
 	}
@@ -174,58 +252,5 @@
 	ASSERT(mutex_locked(&area->lock));
 
-	frame_free(frame);
-}
-
-/** Share the anonymous address space area.
- *
- * Sharing of anonymous area is done by duplicating its entire mapping
- * to the pagemap. Page faults will primarily search for frames there.
- *
- * The address space and address space area must be already locked.
- *
- * @param area Address space area to be shared.
- */
-void anon_share(as_area_t *area)
-{
-	link_t *cur;
-
-	ASSERT(mutex_locked(&area->as->lock));
-	ASSERT(mutex_locked(&area->lock));
-
-	/*
-	 * Copy used portions of the area to sh_info's page map.
-	 */
-	mutex_lock(&area->sh_info->lock);
-	for (cur = area->used_space.leaf_head.next;
-	    cur != &area->used_space.leaf_head; cur = cur->next) {
-		btree_node_t *node;
-		unsigned int i;
-		
-		node = list_get_instance(cur, btree_node_t, leaf_link);
-		for (i = 0; i < node->keys; i++) {
-			uintptr_t base = node->key[i];
-			size_t count = (size_t) node->value[i];
-			unsigned int j;
-			
-			for (j = 0; j < count; j++) {
-				pte_t *pte;
-			
-				page_table_lock(area->as, false);
-				pte = page_mapping_find(area->as,
-				    base + j * PAGE_SIZE);
-				ASSERT(pte && PTE_VALID(pte) &&
-				    PTE_PRESENT(pte));
-				btree_insert(&area->sh_info->pagemap,
-				    (base + j * PAGE_SIZE) - area->base,
-				    (void *) PTE_GET_FRAME(pte), NULL);
-				page_table_unlock(area->as, false);
-
-				pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
-				frame_reference_add(pfn);
-			}
-
-		}
-	}
-	mutex_unlock(&area->sh_info->lock);
+	frame_free_noreserve(frame);
 }
 
Index: kernel/generic/src/mm/backend_elf.c
===================================================================
--- kernel/generic/src/mm/backend_elf.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/mm/backend_elf.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,4 +43,5 @@
 #include <mm/slab.h>
 #include <mm/page.h>
+#include <mm/reserve.h>
 #include <genarch/mm/page_pt.h>
 #include <genarch/mm/page_ht.h>
@@ -51,17 +52,163 @@
 #include <arch/barrier.h>
 
-#ifdef CONFIG_VIRT_IDX_DCACHE
-#include <arch/mm/cache.h>
-#endif
-
-static int elf_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
-static void elf_frame_free(as_area_t *area, uintptr_t page, uintptr_t frame);
-static void elf_share(as_area_t *area);
+static bool elf_create(as_area_t *);
+static bool elf_resize(as_area_t *, size_t);
+static void elf_share(as_area_t *);
+static void elf_destroy(as_area_t *);
+
+static int elf_page_fault(as_area_t *, uintptr_t, pf_access_t);
+static void elf_frame_free(as_area_t *, uintptr_t, uintptr_t);
 
 mem_backend_t elf_backend = {
+	.create = elf_create,
+	.resize = elf_resize,
+	.share = elf_share,
+	.destroy = elf_destroy,
+
 	.page_fault = elf_page_fault,
 	.frame_free = elf_frame_free,
-	.share = elf_share
 };
+
+static size_t elf_nonanon_pages_get(as_area_t *area)
+{
+	elf_segment_header_t *entry = area->backend_data.segment;
+	uintptr_t first = ALIGN_UP(entry->p_vaddr, PAGE_SIZE);
+	uintptr_t last = ALIGN_DOWN(entry->p_vaddr + entry->p_filesz,
+	    PAGE_SIZE);
+
+	if (entry->p_flags & PF_W)
+		return 0;
+
+	if (last < first)
+		return 0;
+
+	return last - first;
+}
+
+bool elf_create(as_area_t *area)
+{
+	size_t nonanon_pages = elf_nonanon_pages_get(area);
+
+	if (area->pages <= nonanon_pages)
+		return true;
+	
+	return reserve_try_alloc(area->pages - nonanon_pages);
+}
+
+bool elf_resize(as_area_t *area, size_t new_pages)
+{
+	size_t nonanon_pages = elf_nonanon_pages_get(area);
+
+	if (new_pages > area->pages) {
+		/* The area is growing. */
+		if (area->pages >= nonanon_pages)
+			return reserve_try_alloc(new_pages - area->pages);
+		else if (new_pages > nonanon_pages)
+			return reserve_try_alloc(new_pages - nonanon_pages);
+	} else if (new_pages < area->pages) {
+		/* The area is shrinking. */
+		if (new_pages >= nonanon_pages)
+			reserve_free(area->pages - new_pages);
+		else if (area->pages > nonanon_pages)
+			reserve_free(nonanon_pages - new_pages);
+	}
+	
+	return true;
+}
+
+/** Share ELF image backed address space area.
+ *
+ * If the area is writable, then all mapped pages are duplicated in the pagemap.
+ * Otherwise only portions of the area that are not backed by the ELF image
+ * are put into the pagemap.
+ *
+ * @param area		Address space area.
+ */
+void elf_share(as_area_t *area)
+{
+	elf_segment_header_t *entry = area->backend_data.segment;
+	link_t *cur;
+	btree_node_t *leaf, *node;
+	uintptr_t start_anon = entry->p_vaddr + entry->p_filesz;
+
+	ASSERT(mutex_locked(&area->as->lock));
+	ASSERT(mutex_locked(&area->lock));
+
+	/*
+	 * Find the node in which to start linear search.
+	 */
+	if (area->flags & AS_AREA_WRITE) {
+		node = list_get_instance(list_first(&area->used_space.leaf_list),
+		    btree_node_t, leaf_link);
+	} else {
+		(void) btree_search(&area->sh_info->pagemap, start_anon, &leaf);
+		node = btree_leaf_node_left_neighbour(&area->sh_info->pagemap,
+		    leaf);
+		if (!node)
+			node = leaf;
+	}
+
+	/*
+	 * Copy used anonymous portions of the area to sh_info's page map.
+	 */
+	mutex_lock(&area->sh_info->lock);
+	for (cur = &node->leaf_link; cur != &area->used_space.leaf_list.head;
+	    cur = cur->next) {
+		unsigned int i;
+		
+		node = list_get_instance(cur, btree_node_t, leaf_link);
+		
+		for (i = 0; i < node->keys; i++) {
+			uintptr_t base = node->key[i];
+			size_t count = (size_t) node->value[i];
+			unsigned int j;
+			
+			/*
+			 * Skip read-only areas of used space that are backed
+			 * by the ELF image.
+			 */
+			if (!(area->flags & AS_AREA_WRITE))
+				if (base >= entry->p_vaddr &&
+				    base + P2SZ(count) <= start_anon)
+					continue;
+			
+			for (j = 0; j < count; j++) {
+				pte_t *pte;
+			
+				/*
+				 * Skip read-only pages that are backed by the
+				 * ELF image.
+				 */
+				if (!(area->flags & AS_AREA_WRITE))
+					if (base >= entry->p_vaddr &&
+					    base + P2SZ(j + 1) <= start_anon)
+						continue;
+				
+				page_table_lock(area->as, false);
+				pte = page_mapping_find(area->as,
+				    base + P2SZ(j), false);
+				ASSERT(pte && PTE_VALID(pte) &&
+				    PTE_PRESENT(pte));
+				btree_insert(&area->sh_info->pagemap,
+				    (base + P2SZ(j)) - area->base,
+				    (void *) PTE_GET_FRAME(pte), NULL);
+				page_table_unlock(area->as, false);
+
+				pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
+				frame_reference_add(pfn);
+			}
+				
+		}
+	}
+	mutex_unlock(&area->sh_info->lock);
+}
+
+void elf_destroy(as_area_t *area)
+{
+	size_t nonanon_pages = elf_nonanon_pages_get(area);
+
+	if (area->pages > nonanon_pages)
+		reserve_free(area->pages - nonanon_pages);
+}
 
 /** Service a page fault in the ELF backend address space area.
@@ -91,7 +238,11 @@
 	if (!as_area_check_access(area, access))
 		return AS_PF_FAULT;
-
-	ASSERT((addr >= ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) &&
-	    (addr < entry->p_vaddr + entry->p_memsz));
+	
+	if (addr < ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE))
+		return AS_PF_FAULT;
+	
+	if (addr >= entry->p_vaddr + entry->p_memsz)
+		return AS_PF_FAULT;
+	
 	i = (addr - ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE)) >> PAGE_WIDTH;
 	base = (uintptr_t)
@@ -153,5 +304,5 @@
 		 */
 		if (entry->p_flags & PF_W) {
-			frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
+			frame = (uintptr_t)frame_alloc_noreserve(ONE_FRAME, 0);
 			memcpy((void *) PA2KA(frame),
 			    (void *) (base + i * FRAME_SIZE), FRAME_SIZE);
@@ -171,5 +322,5 @@
 		 * and cleared.
 		 */
-		frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
+		frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
 		memsetb((void *) PA2KA(frame), FRAME_SIZE, 0);
 		dirty = true;
@@ -193,5 +344,5 @@
 			pad_hi = 0;
 
-		frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
+		frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 0);
 		memcpy((void *) (PA2KA(frame) + pad_lo),
 		    (void *) (base + i * FRAME_SIZE + pad_lo),
@@ -252,5 +403,5 @@
 			 * data.
 			 */
-			frame_free(frame);
+			frame_free_noreserve(frame);
 		}
 	} else {
@@ -260,94 +411,6 @@
 		 * anonymous). In any case, a frame needs to be freed.
 		 */
-		frame_free(frame);
-	}
-}
-
-/** Share ELF image backed address space area.
- *
- * If the area is writable, then all mapped pages are duplicated in the pagemap.
- * Otherwise only portions of the area that are not backed by the ELF image
- * are put into the pagemap.
- *
- * @param area		Address space area.
- */
-void elf_share(as_area_t *area)
-{
-	elf_segment_header_t *entry = area->backend_data.segment;
-	link_t *cur;
-	btree_node_t *leaf, *node;
-	uintptr_t start_anon = entry->p_vaddr + entry->p_filesz;
-
-	ASSERT(mutex_locked(&area->as->lock));
-	ASSERT(mutex_locked(&area->lock));
-
-	/*
-	 * Find the node in which to start linear search.
-	 */
-	if (area->flags & AS_AREA_WRITE) {
-		node = list_get_instance(area->used_space.leaf_head.next,
-		    btree_node_t, leaf_link);
-	} else {
-		(void) btree_search(&area->sh_info->pagemap, start_anon, &leaf);
-		node = btree_leaf_node_left_neighbour(&area->sh_info->pagemap,
-		    leaf);
-		if (!node)
-			node = leaf;
-	}
-
-	/*
-	 * Copy used anonymous portions of the area to sh_info's page map.
-	 */
-	mutex_lock(&area->sh_info->lock);
-	for (cur = &node->leaf_link; cur != &area->used_space.leaf_head;
-	    cur = cur->next) {
-		unsigned int i;
-		
-		node = list_get_instance(cur, btree_node_t, leaf_link);
-		
-		for (i = 0; i < node->keys; i++) {
-			uintptr_t base = node->key[i];
-			size_t count = (size_t) node->value[i];
-			unsigned int j;
-			
-			/*
-			 * Skip read-only areas of used space that are backed
-			 * by the ELF image.
-			 */
-			if (!(area->flags & AS_AREA_WRITE))
-				if (base >= entry->p_vaddr &&
-				    base + count * PAGE_SIZE <= start_anon)
-					continue;
-			
-			for (j = 0; j < count; j++) {
-				pte_t *pte;
-			
-				/*
-				 * Skip read-only pages that are backed by the
-				 * ELF image.
-				 */
-				if (!(area->flags & AS_AREA_WRITE))
-					if (base >= entry->p_vaddr &&
-					    base + (j + 1) * PAGE_SIZE <=
-					    start_anon)
-						continue;
-				
-				page_table_lock(area->as, false);
-				pte = page_mapping_find(area->as,
-				    base + j * PAGE_SIZE);
-				ASSERT(pte && PTE_VALID(pte) &&
-				    PTE_PRESENT(pte));
-				btree_insert(&area->sh_info->pagemap,
-				    (base + j * PAGE_SIZE) - area->base,
-				    (void *) PTE_GET_FRAME(pte), NULL);
-				page_table_unlock(area->as, false);
-
-				pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
-				frame_reference_add(pfn);
-			}
-				
-		}
-	}
-	mutex_unlock(&area->sh_info->lock);
+		frame_free_noreserve(frame);
+	}
 }
 
Index: kernel/generic/src/mm/backend_phys.c
===================================================================
--- kernel/generic/src/mm/backend_phys.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/mm/backend_phys.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -48,12 +48,43 @@
 #include <align.h>
 
-static int phys_page_fault(as_area_t *area, uintptr_t addr, pf_access_t access);
-static void phys_share(as_area_t *area);
+static bool phys_create(as_area_t *);
+static void phys_share(as_area_t *);
+static void phys_destroy(as_area_t *);
+
+static int phys_page_fault(as_area_t *, uintptr_t, pf_access_t);
 
 mem_backend_t phys_backend = {
+	.create = phys_create,
+	.resize = NULL,
+	.share = phys_share,
+	.destroy = phys_destroy,
+
 	.page_fault = phys_page_fault,
 	.frame_free = NULL,
-	.share = phys_share
 };
+
+bool phys_create(as_area_t *area)
+{
+	return true;
+}
+
+/** Share address space area backed by physical memory.
+ *
+ * Do actually nothing as sharing of address space areas
+ * that are backed up by physical memory is very easy.
+ * Note that the function must be defined so that
+ * as_area_share() will succeed.
+ */
+void phys_share(as_area_t *area)
+{
+	ASSERT(mutex_locked(&area->as->lock));
+	ASSERT(mutex_locked(&area->lock));
+}
+
+
+void phys_destroy(as_area_t *area)
+{
+	/* Nothing to do. */
+}
 
 /** Service a page fault in the address space area backed by physical memory.
@@ -88,17 +119,4 @@
 }
 
-/** Share address space area backed by physical memory.
- *
- * Do actually nothing as sharing of address space areas
- * that are backed up by physical memory is very easy.
- * Note that the function must be defined so that
- * as_area_share() will succeed.
- */
-void phys_share(as_area_t *area)
-{
-	ASSERT(mutex_locked(&area->as->lock));
-	ASSERT(mutex_locked(&area->lock));
-}
-
 /** @}
  */
Index: kernel/generic/src/mm/buddy.c
===================================================================
--- kernel/generic/src/mm/buddy.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/mm/buddy.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -82,5 +82,5 @@
 	 * Use memory after our own structure.
 	 */
-	b->order = (link_t *) (&b[1]);
+	b->order = (list_t *) (&b[1]);
 	
 	for (i = 0; i <= max_order; i++)
@@ -176,6 +176,6 @@
 	 * the request can be immediatelly satisfied.
 	 */
-	if (!list_empty(&b->order[i])) {
-		res = b->order[i].next;
+	res = list_first(&b->order[i]);
+	if (res != NULL) {
 		list_remove(res);
 		b->op->mark_busy(b, res);
Index: kernel/generic/src/mm/frame.c
===================================================================
--- kernel/generic/src/mm/frame.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/mm/frame.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,4 +45,5 @@
 #include <typedefs.h>
 #include <mm/frame.h>
+#include <mm/reserve.h>
 #include <mm/as.h>
 #include <panic.h>
@@ -59,4 +60,5 @@
 #include <macros.h>
 #include <config.h>
+#include <str.h>
 
 zones_t zones;
@@ -180,9 +182,9 @@
  *
  */
-#ifdef CONFIG_DEBUG
-NO_TRACE static size_t total_frames_free(void)
+NO_TRACE static size_t frame_total_free_get_internal(void)
 {
 	size_t total = 0;
 	size_t i;
+
 	for (i = 0; i < zones.count; i++)
 		total += zones.info[i].free_count;
@@ -190,5 +192,16 @@
 	return total;
 }
-#endif /* CONFIG_DEBUG */
+
+NO_TRACE size_t frame_total_free_get(void)
+{
+	size_t total;
+
+	irq_spinlock_lock(&zones.lock, true);
+	total = frame_total_free_get_internal();
+	irq_spinlock_unlock(&zones.lock, true);
+
+	return total;
+}
+
 
 /** Find a zone with a given frames.
@@ -472,23 +485,25 @@
  * @param frame_idx Frame index relative to zone.
  *
- */
-NO_TRACE static void zone_frame_free(zone_t *zone, size_t frame_idx)
+ * @return          Number of freed frames.
+ *
+ */
+NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
 {
 	ASSERT(zone_flags_available(zone->flags));
 	
 	frame_t *frame = &zone->frames[frame_idx];
-	
-	/* Remember frame order */
-	uint8_t order = frame->buddy_order;
+	size_t size = 0;
 	
 	ASSERT(frame->refcount);
 	
 	if (!--frame->refcount) {
-		buddy_system_free(zone->buddy_system, &frame->buddy_link);
-		
+		size = 1 << frame->buddy_order;
+		buddy_system_free(zone->buddy_system, &frame->buddy_link);		
 		/* Update zone information. */
-		zone->free_count += (1 << order);
-		zone->busy_count -= (1 << order);
-	}
+		zone->free_count += size;
+		zone->busy_count -= size;
+	}
+	
+	return size;
 }
 
@@ -516,4 +531,5 @@
 	ASSERT(link);
 	zone->free_count--;
+	reserve_force_alloc(1);
 }
 
@@ -645,5 +661,5 @@
 	for (i = 0; i < cframes; i++) {
 		zones.info[znum].busy_count++;
-		zone_frame_free(&zones.info[znum],
+		(void) zone_frame_free(&zones.info[znum],
 		    pfn - zones.info[znum].base + i);
 	}
@@ -683,5 +699,5 @@
 	/* Free unneeded frames */
 	for (i = count; i < (size_t) (1 << order); i++)
-		zone_frame_free(&zones.info[znum], i + frame_idx);
+		(void) zone_frame_free(&zones.info[znum], i + frame_idx);
 }
 
@@ -695,6 +711,4 @@
  * not to be 2^order size. Once the allocator is running it is no longer
  * possible, merged configuration data occupies more space :-/
- *
- * The function uses
  *
  */
@@ -999,4 +1013,10 @@
 	size_t hint = pzone ? (*pzone) : 0;
 	
+	/*
+	 * If not told otherwise, we must first reserve the memory.
+	 */
+	if (!(flags & FRAME_NO_RESERVE)) 
+		reserve_force_alloc(size);
+
 loop:
 	irq_spinlock_lock(&zones.lock, true);
@@ -1033,9 +1053,11 @@
 		if (flags & FRAME_ATOMIC) {
 			irq_spinlock_unlock(&zones.lock, true);
+			if (!(flags & FRAME_NO_RESERVE))
+				reserve_free(size);
 			return NULL;
 		}
 		
 #ifdef CONFIG_DEBUG
-		size_t avail = total_frames_free();
+		size_t avail = frame_total_free_get_internal();
 #endif
 		
@@ -1088,4 +1110,14 @@
 }
 
+void *frame_alloc(uint8_t order, frame_flags_t flags)
+{
+	return frame_alloc_generic(order, flags, NULL);
+}
+
+void *frame_alloc_noreserve(uint8_t order, frame_flags_t flags)
+{
+	return frame_alloc_generic(order, flags | FRAME_NO_RESERVE, NULL);
+}
+
 /** Free a frame.
  *
@@ -1095,8 +1127,11 @@
  *
  * @param frame Physical Address of of the frame to be freed.
- *
- */
-void frame_free(uintptr_t frame)
-{
+ * @param flags Flags to control memory reservation.
+ *
+ */
+void frame_free_generic(uintptr_t frame, frame_flags_t flags)
+{
+	size_t size;
+	
 	irq_spinlock_lock(&zones.lock, true);
 	
@@ -1106,8 +1141,9 @@
 	pfn_t pfn = ADDR2PFN(frame);
 	size_t znum = find_zone(pfn, 1, 0);
+
 	
 	ASSERT(znum != (size_t) -1);
 	
-	zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
+	size = zone_frame_free(&zones.info[znum], pfn - zones.info[znum].base);
 	
 	irq_spinlock_unlock(&zones.lock, true);
@@ -1118,5 +1154,5 @@
 	mutex_lock(&mem_avail_mtx);
 	if (mem_avail_req > 0)
-		mem_avail_req--;
+		mem_avail_req -= min(mem_avail_req, size);
 	
 	if (mem_avail_req == 0) {
@@ -1125,4 +1161,17 @@
 	}
 	mutex_unlock(&mem_avail_mtx);
+	
+	if (!(flags & FRAME_NO_RESERVE))
+		reserve_free(size);
+}
+
+void frame_free(uintptr_t frame)
+{
+	frame_free_generic(frame, 0);
+}
+
+void frame_free_noreserve(uintptr_t frame)
+{
+	frame_free_generic(frame, FRAME_NO_RESERVE);
 }
 
@@ -1355,8 +1404,12 @@
 	bool available = zone_flags_available(flags);
 	
+	uint64_t size;
+	const char *size_suffix;
+	bin_order_suffix(FRAMES2SIZE(count), &size, &size_suffix, false);
+	
 	printf("Zone number:       %zu\n", znum);
 	printf("Zone base address: %p\n", (void *) base);
-	printf("Zone size:         %zu frames (%zu KiB)\n", count,
-	    SIZE2KB(FRAMES2SIZE(count)));
+	printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
+	    size, size_suffix);
 	printf("Zone flags:        %c%c%c\n",
 	    available ? 'A' : ' ',
@@ -1365,8 +1418,12 @@
 	
 	if (available) {
-		printf("Allocated space:   %zu frames (%zu KiB)\n",
-		    busy_count, SIZE2KB(FRAMES2SIZE(busy_count)));
-		printf("Available space:   %zu frames (%zu KiB)\n",
-		    free_count, SIZE2KB(FRAMES2SIZE(free_count)));
+		bin_order_suffix(FRAMES2SIZE(busy_count), &size, &size_suffix,
+		    false);
+		printf("Allocated space:   %zu frames (%" PRIu64 " %s)\n",
+		    busy_count, size, size_suffix);
+		bin_order_suffix(FRAMES2SIZE(free_count), &size, &size_suffix,
+		    false);
+		printf("Available space:   %zu frames (%" PRIu64 " %s)\n",
+		    free_count, size, size_suffix);
 	}
 }
Index: kernel/generic/src/mm/page.c
===================================================================
--- kernel/generic/src/mm/page.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/mm/page.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -60,4 +60,6 @@
 
 #include <mm/page.h>
+#include <genarch/mm/page_ht.h>
+#include <genarch/mm/page_pt.h>
 #include <arch/mm/page.h>
 #include <arch/mm/asid.h>
@@ -70,4 +72,6 @@
 #include <debug.h>
 #include <arch.h>
+#include <syscall/copy.h>
+#include <errno.h>
 
 /** Virtual operations for page subsystem. */
@@ -108,5 +112,5 @@
  * using flags. Allocate and setup any missing page tables.
  *
- * @param as    Address space to wich page belongs.
+ * @param as    Address space to which page belongs.
  * @param page  Virtual address of the page to be mapped.
  * @param frame Physical address of memory frame to which the mapping is
@@ -135,5 +139,5 @@
  * this call visible.
  *
- * @param as   Address space to wich page belongs.
+ * @param as   Address space to which page belongs.
  * @param page Virtual address of the page to be demapped.
  *
@@ -152,10 +156,9 @@
 }
 
-/** Find mapping for virtual page
- *
- * Find mapping for virtual page.
- *
- * @param as   Address space to wich page belongs.
- * @param page Virtual page.
+/** Find mapping for virtual page.
+ *
+ * @param as     Address space to which page belongs.
+ * @param page   Virtual page.
+ * @param nolock True if the page tables need not be locked.
  *
  * @return NULL if there is no such mapping; requested mapping
@@ -163,12 +166,43 @@
  *
  */
-NO_TRACE pte_t *page_mapping_find(as_t *as, uintptr_t page)
-{
-	ASSERT(page_table_locked(as));
+NO_TRACE pte_t *page_mapping_find(as_t *as, uintptr_t page, bool nolock)
+{
+	ASSERT(nolock || page_table_locked(as));
 	
 	ASSERT(page_mapping_operations);
 	ASSERT(page_mapping_operations->mapping_find);
 	
-	return page_mapping_operations->mapping_find(as, page);
+	return page_mapping_operations->mapping_find(as, page, nolock);
+}
+
+/** Syscall wrapper for getting mapping of a virtual page.
+ * 
+ * @retval EOK Everything went find, @p uspace_frame and @p uspace_node
+ *             contains correct values.
+ * @retval ENOENT Virtual address has no mapping.
+ */
+sysarg_t sys_page_find_mapping(uintptr_t virt_address,
+    uintptr_t *uspace_frame)
+{
+	mutex_lock(&AS->lock);
+	
+	pte_t *pte = page_mapping_find(AS, virt_address, false);
+	if (!PTE_VALID(pte) || !PTE_PRESENT(pte)) {
+		mutex_unlock(&AS->lock);
+		
+		return (sysarg_t) ENOENT;
+	}
+	
+	uintptr_t phys_address = PTE_GET_FRAME(pte);
+	
+	mutex_unlock(&AS->lock);
+	
+	int rc = copy_to_uspace(uspace_frame,
+	    &phys_address, sizeof(phys_address));
+	if (rc != EOK) {
+		return (sysarg_t) rc;
+	}
+	
+	return EOK;
 }
 
Index: kernel/generic/src/mm/reserve.c
===================================================================
--- kernel/generic/src/mm/reserve.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ kernel/generic/src/mm/reserve.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2011 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup genericmm
+ * @{
+ */
+
+/**
+ * @file
+ * @brief Memory reservations.
+ */
+
+#include <mm/reserve.h>
+#include <mm/frame.h>
+#include <mm/slab.h>
+#include <synch/spinlock.h>
+#include <typedefs.h>
+#include <arch/types.h>
+
+IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(reserve_lock, "reserve_lock");
+static ssize_t reserve = 0;
+
+/** Initialize memory reservations tracking.
+ *
+ * This function must be called after frame zones are created and merged
+ * and before any address space area is created.
+ */
+void reserve_init(void)
+{
+	reserve = frame_total_free_get();
+}
+
+/** Try to reserve memory.
+ *
+ * This function may not be called from contexts that do not allow memory
+ * reclaiming, such as some invocations of frame_alloc_generic().
+ *
+ * @param size		Number of frames to reserve.
+ * @return		True on success or false otherwise.
+ */
+bool reserve_try_alloc(size_t size)
+{
+	bool reserved = false;
+
+	irq_spinlock_lock(&reserve_lock, true);
+	if (reserve >= 0 && (size_t) reserve >= size) {
+		reserve -= size;
+		reserved = true;
+	} else {
+		/*
+		 * Some reservable frames may be cached by the slab allocator.
+		 * Try to reclaim some reservable memory. Try to be gentle for
+		 * the first time. If it does not help, try to reclaim
+		 * everything.
+		 */
+		irq_spinlock_unlock(&reserve_lock, true);
+		slab_reclaim(0);
+		irq_spinlock_lock(&reserve_lock, true);
+		if (reserve >= 0 && (size_t) reserve >= size) {
+			reserve -= size;
+			reserved = true;
+		} else {
+			irq_spinlock_unlock(&reserve_lock, true);
+			slab_reclaim(SLAB_RECLAIM_ALL);
+			irq_spinlock_lock(&reserve_lock, true);
+			if (reserve >= 0 && (size_t) reserve >= size) {
+				reserve -= size;
+				reserved = true;
+			}
+		}
+	}
+	irq_spinlock_unlock(&reserve_lock, true);
+
+	return reserved;
+}
+
+/** Reserve memory.
+ *
+ * This function simply marks the respective amount of memory frames reserved.
+ * It does not implement any sort of blocking for the case there is not enough
+ * reservable memory. It will simply take the reserve into negative numbers and
+ * leave the blocking up to the allocation phase.
+ *
+ * @param size		Number of frames to reserve.
+ */
+void reserve_force_alloc(size_t size)
+{
+	irq_spinlock_lock(&reserve_lock, true);
+	reserve -= size;
+	irq_spinlock_unlock(&reserve_lock, true);
+}
+
+/** Unreserve memory.
+ *
+ * @param size		Number of frames to unreserve.
+ */
+void reserve_free(size_t size)
+{
+	irq_spinlock_lock(&reserve_lock, true);
+	reserve += size;
+	irq_spinlock_unlock(&reserve_lock, true);
+}
+
+/** @}
+ */
Index: kernel/generic/src/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/mm/slab.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -317,6 +317,6 @@
 		spinlock_lock(&cache->slablock);
 	} else {
-		slab = list_get_instance(cache->partial_slabs.next, slab_t,
-		    link);
+		slab = list_get_instance(list_first(&cache->partial_slabs),
+		    slab_t, link);
 		list_remove(&slab->link);
 	}
@@ -360,7 +360,7 @@
 	if (!list_empty(&cache->magazines)) {
 		if (first)
-			cur = cache->magazines.next;
+			cur = list_first(&cache->magazines);
 		else
-			cur = cache->magazines.prev;
+			cur = list_last(&cache->magazines);
 		
 		mag = list_get_instance(cur, slab_magazine_t, link);
@@ -812,7 +812,5 @@
 	
 	size_t frames = 0;
-	link_t *cur;
-	for (cur = slab_cache_list.next; cur != &slab_cache_list;
-	    cur = cur->next) {
+	list_foreach(slab_cache_list, cur) {
 		slab_cache_t *cache = list_get_instance(cur, slab_cache_t, link);
 		frames += _slab_reclaim(cache, flags);
@@ -861,9 +859,9 @@
 		link_t *cur;
 		size_t i;
-		for (i = 0, cur = slab_cache_list.next;
-		    (i < skip) && (cur != &slab_cache_list);
+		for (i = 0, cur = slab_cache_list.head.next;
+		    (i < skip) && (cur != &slab_cache_list.head);
 		    i++, cur = cur->next);
 		
-		if (cur == &slab_cache_list) {
+		if (cur == &slab_cache_list.head) {
 			irq_spinlock_unlock(&slab_cache_lock, true);
 			break;
@@ -940,7 +938,5 @@
 	irq_spinlock_lock(&slab_cache_lock, false);
 	
-	link_t *cur;
-	for (cur = slab_cache_list.next; cur != &slab_cache_list;
-	    cur = cur->next) {
+	list_foreach(slab_cache_list, cur) {
 		slab_cache_t *slab = list_get_instance(cur, slab_cache_t, link);
 		if ((slab->flags & SLAB_CACHE_MAGDEFERRED) !=
Index: kernel/generic/src/printf/vprintf.c
===================================================================
--- kernel/generic/src/printf/vprintf.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/printf/vprintf.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,6 +41,4 @@
 #include <typedefs.h>
 #include <str.h>
-
-IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(printf_lock, "*printf_lock");
 
 static int vprintf_str_write(const char *str, size_t size, void *data)
@@ -93,9 +91,5 @@
 	};
 	
-	irq_spinlock_lock(&printf_lock, true);
-	int ret = printf_core(fmt, &ps, ap);
-	irq_spinlock_unlock(&printf_lock, true);
-	
-	return ret;
+	return printf_core(fmt, &ps, ap);
 }
 
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/proc/program.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,5 +40,4 @@
 #include <proc/thread.h>
 #include <proc/task.h>
-#include <proc/uarg.h>
 #include <mm/as.h>
 #include <mm/slab.h>
@@ -48,13 +47,9 @@
 #include <ipc/ipcrsc.h>
 #include <security/cap.h>
-#include <lib/elf.h>
+#include <lib/elf_load.h>
 #include <errno.h>
 #include <print.h>
 #include <syscall/copy.h>
 #include <proc/program.h>
-
-#ifndef LOADED_PROG_STACK_PAGES_NO
-#define LOADED_PROG_STACK_PAGES_NO 1
-#endif
 
 /**
@@ -90,10 +85,10 @@
 	
 	/*
-	 * Create the data address space area.
+	 * Create the stack address space area.
 	 */
 	as_area_t *area = as_area_create(as,
 	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE,
-	    LOADED_PROG_STACK_PAGES_NO * PAGE_SIZE, USTACK_ADDRESS,
-	    AS_AREA_ATTR_NONE, &anon_backend, NULL);
+	    STACK_SIZE, USTACK_ADDRESS, AS_AREA_ATTR_NONE,
+	    &anon_backend, NULL);
 	if (!area)
 		return ENOMEM;
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/proc/scheduler.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -237,6 +237,6 @@
 		 * Take the first thread from the queue.
 		 */
-		thread_t *thread =
-		    list_get_instance(CPU->rq[i].rq_head.next, thread_t, rq_link);
+		thread_t *thread = list_get_instance(
+		    list_first(&CPU->rq[i].rq), thread_t, rq_link);
 		list_remove(&thread->rq_link);
 		
@@ -273,7 +273,7 @@
 static void relink_rq(int start)
 {
-	link_t head;
-	
-	list_initialize(&head);
+	list_t list;
+	
+	list_initialize(&list);
 	irq_spinlock_lock(&CPU->lock, false);
 	
@@ -284,5 +284,5 @@
 			
 			irq_spinlock_lock(&CPU->rq[i + 1].lock, false);
-			list_concat(&head, &CPU->rq[i + 1].rq_head);
+			list_concat(&list, &CPU->rq[i + 1].rq);
 			size_t n = CPU->rq[i + 1].n;
 			CPU->rq[i + 1].n = 0;
@@ -292,5 +292,5 @@
 			
 			irq_spinlock_lock(&CPU->rq[i].lock, false);
-			list_concat(&CPU->rq[i].rq_head, &head);
+			list_concat(&CPU->rq[i].rq, &list);
 			CPU->rq[i].n += n;
 			irq_spinlock_unlock(&CPU->rq[i].lock, false);
@@ -354,5 +354,5 @@
 	
 	/*
-	 * Through the 'THE' structure, we keep track of THREAD, TASK, CPU, VM
+	 * Through the 'THE' structure, we keep track of THREAD, TASK, CPU, AS
 	 * and preemption counter. At this point THE could be coming either
 	 * from THREAD's or CPU's stack.
@@ -376,5 +376,5 @@
 	context_save(&CPU->saved_context);
 	context_set(&CPU->saved_context, FADDR(scheduler_separated_stack),
-	    (uintptr_t) CPU->stack, CPU_STACK_SIZE);
+	    (uintptr_t) CPU->stack, STACK_SIZE);
 	context_restore(&CPU->saved_context);
 	
@@ -586,5 +586,4 @@
 	 * Searching least priority queues on all CPU's first and most priority
 	 * queues on all CPU's last.
-	 *
 	 */
 	size_t acpu;
@@ -617,26 +616,27 @@
 			
 			/* Search rq from the back */
-			link_t *link = cpu->rq[rq].rq_head.prev;
-			
-			while (link != &(cpu->rq[rq].rq_head)) {
-				thread = (thread_t *) list_get_instance(link, thread_t, rq_link);
+			link_t *link = cpu->rq[rq].rq.head.prev;
+			
+			while (link != &(cpu->rq[rq].rq.head)) {
+				thread = (thread_t *) list_get_instance(link,
+				    thread_t, rq_link);
 				
 				/*
-				 * We don't want to steal CPU-wired threads
-				 * neither threads already stolen. The latter
-				 * prevents threads from migrating between CPU's
-				 * without ever being run. We don't want to
-				 * steal threads whose FPU context is still in
-				 * CPU.
-				 *
+				 * Do not steal CPU-wired threads, threads
+				 * already stolen, threads for which migration
+				 * was temporarily disabled or threads whose
+				 * FPU context is still in the CPU.
 				 */
 				irq_spinlock_lock(&thread->lock, false);
 				
-				if ((!(thread->flags & (THREAD_FLAG_WIRED | THREAD_FLAG_STOLEN)))
-				    && (!(thread->fpu_context_engaged))) {
+				if (!(thread->flags & THREAD_FLAG_WIRED) &&
+				    !(thread->flags & THREAD_FLAG_STOLEN) &&
+				    !thread->nomigrate &&
+				    !thread->fpu_context_engaged) {
 					/*
 					 * Remove thread from ready queue.
 					 */
-					irq_spinlock_unlock(&thread->lock, false);
+					irq_spinlock_unlock(&thread->lock,
+					    false);
 					
 					atomic_dec(&cpu->nrdy);
@@ -660,5 +660,6 @@
 				 */
 				
-				irq_spinlock_pass(&(cpu->rq[rq].lock), &thread->lock);
+				irq_spinlock_pass(&(cpu->rq[rq].lock),
+				    &thread->lock);
 				
 #ifdef KCPULB_VERBOSE
@@ -739,9 +740,7 @@
 			
 			printf("\trq[%u]: ", i);
-			link_t *cur;
-			for (cur = cpus[cpu].rq[i].rq_head.next;
-			    cur != &(cpus[cpu].rq[i].rq_head);
-			    cur = cur->next) {
-				thread_t *thread = list_get_instance(cur, thread_t, rq_link);
+			list_foreach(cpus[cpu].rq[i].rq, cur) {
+				thread_t *thread = list_get_instance(cur,
+				    thread_t, rq_link);
 				printf("%" PRIu64 "(%s) ", thread->tid,
 				    thread_states[thread->state]);
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/proc/task.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -50,4 +50,5 @@
 #include <ipc/ipc.h>
 #include <ipc/ipcrsc.h>
+#include <ipc/event.h>
 #include <print.h>
 #include <errno.h>
@@ -57,5 +58,4 @@
 #include <syscall/copy.h>
 #include <macros.h>
-#include <ipc/event.h>
 
 /** Spinlock protecting the tasks_tree AVL tree. */
@@ -155,6 +155,6 @@
 	mutex_initialize(&task->futexes_lock, MUTEX_PASSIVE);
 	
-	list_initialize(&task->th_head);
-	list_initialize(&task->sync_box_head);
+	list_initialize(&task->threads);
+	list_initialize(&task->sync_boxes);
 	
 	ipc_answerbox_init(&task->answerbox, task);
@@ -190,5 +190,5 @@
 	str_cpy(task->name, TASK_NAME_BUFLEN, name);
 	
-	task->context = CONTEXT;
+	task->container = CONTAINER;
 	task->capabilities = 0;
 	task->ucycles = 0;
@@ -201,4 +201,6 @@
 	task->ipc_info.irq_notif_received = 0;
 	task->ipc_info.forwarded = 0;
+
+	event_task_init(task);
 	
 #ifdef CONFIG_UDEBUG
@@ -211,5 +213,5 @@
 	
 	if ((ipc_phone_0) &&
-	    (context_check(ipc_phone_0->task->context, task->context)))
+	    (container_check(ipc_phone_0->task->container, task->container)))
 		ipc_phone_connect(&task->phones[0], ipc_phone_0);
 	
@@ -435,6 +437,5 @@
 	
 	/* Current values of threads */
-	link_t *cur;
-	for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
+	list_foreach(task->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		
@@ -468,6 +469,5 @@
 	 */
 	
-	link_t *cur;
-	for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
+	list_foreach(task->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		bool sleeping = false;
@@ -534,9 +534,7 @@
 	*/
 	if (notify) {
-		if (event_is_subscribed(EVENT_FAULT)) {
-			/* Notify the subscriber that a fault occurred. */
-			event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
-			    UPPER32(TASK->taskid), (sysarg_t) THREAD);
-		
+		/* Notify the subscriber that a fault occurred. */
+		if (event_notify_3(EVENT_FAULT, false, LOWER32(TASK->taskid),
+		    UPPER32(TASK->taskid), (sysarg_t) THREAD) == EOK) {
 #ifdef CONFIG_UDEBUG
 			/* Wait for a debugging session. */
@@ -586,5 +584,5 @@
 		printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %10p %10p"
 		    " %9" PRIu64 "%c %9" PRIu64 "%c\n", task->taskid,
-		    task->name, task->context, task, task->as,
+		    task->name, task->container, task, task->as,
 		    ucycles, usuffix, kcycles, ksuffix);
 #endif
@@ -597,5 +595,5 @@
 	else
 		printf("%-8" PRIu64 " %-14s %-5" PRIu32 " %18p %18p\n",
-		    task->taskid, task->name, task->context, task, task->as);
+		    task->taskid, task->name, task->container, task, task->as);
 #endif
 	
@@ -627,5 +625,5 @@
 		printf("[id    ] [threads] [calls] [callee\n");
 	else
-		printf("[id    ] [name        ] [ctx] [address ] [as      ]"
+		printf("[id    ] [name        ] [ctn] [address ] [as      ]"
 		    " [ucycles ] [kcycles ]\n");
 #endif
@@ -636,5 +634,5 @@
 		    " [callee\n");
 	else
-		printf("[id    ] [name        ] [ctx] [address         ]"
+		printf("[id    ] [name        ] [ctn] [address         ]"
 		    " [as              ]\n");
 #endif
Index: rnel/generic/src/proc/tasklet.c
===================================================================
--- kernel/generic/src/proc/tasklet.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * Copyright (c) 2007 Jan Hudecek
- * 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.
- */
-
-/** @addtogroup genericproc
- * @{
- */
-/** @file tasklet.c
- *  @brief Tasklet implementation
- */
-
-#include <proc/tasklet.h>
-#include <synch/spinlock.h>
-#include <mm/slab.h>
-#include <config.h>
-
-/** Spinlock protecting list of tasklets */
-SPINLOCK_INITIALIZE(tasklet_lock);
-
-/** Array of tasklet lists for every CPU */
-tasklet_descriptor_t **tasklet_list;
-
-void tasklet_init(void)
-{
-	unsigned int i;
-	
-	tasklet_list = malloc(sizeof(tasklet_descriptor_t *) * config.cpu_count, 0);
-	if (!tasklet_list)
-		panic("Error initializing tasklets.");
-	
-	for (i = 0; i < config.cpu_count; i++)
-		tasklet_list[i] = NULL;
-	
-	spinlock_initialize(&tasklet_lock, "tasklet_lock");
-}
-
-
-/** @}
- */
Index: kernel/generic/src/proc/the.c
===================================================================
--- kernel/generic/src/proc/the.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/proc/the.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -58,4 +58,5 @@
 	the->task = NULL;
 	the->as = NULL;
+	the->magic = MAGIC;
 }
 
@@ -70,4 +71,5 @@
 NO_TRACE void the_copy(the_t *src, the_t *dst)
 {
+	ASSERT(src->magic == MAGIC);
 	*dst = *src;
 }
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/proc/thread.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #include <proc/thread.h>
 #include <proc/task.h>
-#include <proc/uarg.h>
 #include <mm/frame.h>
 #include <mm/page.h>
@@ -45,5 +44,4 @@
 #include <arch/cycle.h>
 #include <arch.h>
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 #include <synch/waitq.h>
@@ -55,4 +53,5 @@
 #include <time/clock.h>
 #include <time/timeout.h>
+#include <time/delay.h>
 #include <config.h>
 #include <arch/interrupt.h>
@@ -67,10 +66,4 @@
 #include <syscall/copy.h>
 #include <errno.h>
-
-
-#ifndef LOADED_PROG_STACK_PAGES_NO
-#define LOADED_PROG_STACK_PAGES_NO 1
-#endif
-
 
 /** Thread states */
@@ -265,5 +258,5 @@
 	 */
 	
-	list_append(&thread->rq_link, &cpu->rq[i].rq_head);
+	list_append(&thread->rq_link, &cpu->rq[i].rq);
 	cpu->rq[i].n++;
 	irq_spinlock_unlock(&(cpu->rq[i].lock), true);
@@ -300,5 +293,5 @@
 	
 	/* Not needed, but good for debugging */
-	memsetb(thread->kstack, THREAD_STACK_SIZE * 1 << STACK_FRAMES, 0);
+	memsetb(thread->kstack, STACK_SIZE, 0);
 	
 	irq_spinlock_lock(&tidlock, true);
@@ -308,5 +301,5 @@
 	context_save(&thread->saved_context);
 	context_set(&thread->saved_context, FADDR(cushion),
-	    (uintptr_t) thread->kstack, THREAD_STACK_SIZE);
+	    (uintptr_t) thread->kstack, STACK_SIZE);
 	
 	the_initialize((the_t *) thread->kstack);
@@ -327,4 +320,5 @@
 	thread->cpu = NULL;
 	thread->flags = flags;
+	thread->nomigrate = 0;
 	thread->state = Entering;
 	
@@ -427,5 +421,5 @@
 		atomic_inc(&task->lifecount);
 	
-	list_append(&thread->th_link, &task->th_head);
+	list_append(&thread->th_link, &task->threads);
 	
 	irq_spinlock_pass(&task->lock, &threads_lock);
@@ -489,4 +483,21 @@
 }
 
+/** Prevent the current thread from being migrated to another processor. */
+void thread_migration_disable(void)
+{
+	ASSERT(THREAD);
+
+	THREAD->nomigrate++;
+}
+
+/** Allow the current thread to be migrated to another processor. */
+void thread_migration_enable(void)
+{
+	ASSERT(THREAD);
+	ASSERT(THREAD->nomigrate > 0);
+
+	THREAD->nomigrate--;
+}
+
 /** Thread sleep
  *
@@ -605,5 +616,5 @@
 		printf("%-8" PRIu64 " %-14s %10p %-8s %10p %-5" PRIu32 "\n",
 		    thread->tid, name, thread, thread_states[thread->state],
-		    thread->task, thread->task->context);
+		    thread->task, thread->task->container);
 #endif
 	
@@ -617,5 +628,5 @@
 		printf("%-8" PRIu64 " %-14s %18p %-8s %18p %-5" PRIu32 "\n",
 		    thread->tid, name, thread, thread_states[thread->state],
-		    thread->task, thread->task->context);
+		    thread->task, thread->task->container);
 #endif
 	
@@ -658,5 +669,5 @@
 	else
 		printf("[id    ] [name        ] [address ] [state ] [task    ]"
-		    " [ctx]\n");
+		    " [ctn]\n");
 #endif
 	
@@ -667,5 +678,5 @@
 	} else
 		printf("[id    ] [name        ] [address         ] [state ]"
-		    " [task            ] [ctx]\n");
+		    " [task            ] [ctn]\n");
 #endif
 	
@@ -918,4 +929,10 @@
 }
 
+sysarg_t sys_thread_udelay(uint32_t usec)
+{
+	delay(usec);
+	return 0;
+}
+
 /** @}
  */
Index: kernel/generic/src/security/cap.c
===================================================================
--- kernel/generic/src/security/cap.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/security/cap.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -92,5 +92,5 @@
 	task_t *task = task_find_by_id(taskid);
 	
-	if ((!task) || (!context_check(CONTEXT, task->context))) {
+	if ((!task) || (!container_check(CONTAINER, task->container))) {
 		irq_spinlock_unlock(&tasks_lock, true);
 		return (sysarg_t) ENOENT;
@@ -121,5 +121,5 @@
 	
 	task_t *task = task_find_by_id(taskid);
-	if ((!task) || (!context_check(CONTEXT, task->context))) {
+	if ((!task) || (!container_check(CONTAINER, task->container))) {
 		irq_spinlock_unlock(&tasks_lock, true);
 		return (sysarg_t) ENOENT;
Index: kernel/generic/src/synch/condvar.c
===================================================================
--- kernel/generic/src/synch/condvar.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/synch/condvar.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #include <synch/mutex.h>
 #include <synch/waitq.h>
-#include <synch/synch.h>
 #include <arch.h>
 
Index: kernel/generic/src/synch/futex.c
===================================================================
--- kernel/generic/src/synch/futex.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/synch/futex.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #include <synch/mutex.h>
 #include <synch/spinlock.h>
-#include <synch/synch.h>
 #include <mm/frame.h>
 #include <mm/page.h>
@@ -119,5 +118,5 @@
 	 */
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
+	t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE), false);
 	if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
 		page_table_unlock(AS, true);
@@ -155,5 +154,5 @@
 	 */
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE));
+	t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE), false);
 	if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) {
 		page_table_unlock(AS, true);
@@ -272,11 +271,8 @@
 void futex_cleanup(void)
 {
-	link_t *cur;
-	
 	mutex_lock(&futex_ht_lock);
 	mutex_lock(&TASK->futexes_lock);
 
-	for (cur = TASK->futexes.leaf_head.next;
-	    cur != &TASK->futexes.leaf_head; cur = cur->next) {
+	list_foreach(TASK->futexes.leaf_list, cur) {
 		btree_node_t *node;
 		unsigned int i;
Index: kernel/generic/src/synch/mutex.c
===================================================================
--- kernel/generic/src/synch/mutex.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/synch/mutex.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,4 @@
 #include <synch/mutex.h>
 #include <synch/semaphore.h>
-#include <synch/synch.h>
 #include <debug.h>
 #include <arch.h>
Index: kernel/generic/src/synch/semaphore.c
===================================================================
--- kernel/generic/src/synch/semaphore.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/synch/semaphore.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,4 @@
 #include <synch/waitq.h>
 #include <synch/spinlock.h>
-#include <synch/synch.h>
 #include <arch/asm.h>
 #include <arch.h>
Index: kernel/generic/src/synch/spinlock.c
===================================================================
--- kernel/generic/src/synch/spinlock.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/synch/spinlock.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -96,5 +96,4 @@
 		 * run in a simulator) that caused problems with both
 		 * printf_lock and the framebuffer lock.
-		 *
 		 */
 		if (lock->name[0] == '*')
Index: kernel/generic/src/synch/waitq.c
===================================================================
--- kernel/generic/src/synch/waitq.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/synch/waitq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,5 +45,4 @@
 
 #include <synch/waitq.h>
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 #include <proc/thread.h>
@@ -69,5 +68,5 @@
 {
 	irq_spinlock_initialize(&wq->lock, "wq.lock");
-	list_initialize(&wq->head);
+	list_initialize(&wq->sleepers);
 	wq->missed_wakeups = 0;
 }
@@ -196,6 +195,7 @@
 	irq_spinlock_lock(&wq->lock, true);
 	
-	if (!list_empty(&wq->head)) {
-		thread_t *thread = list_get_instance(wq->head.next, thread_t, wq_link);
+	if (!list_empty(&wq->sleepers)) {
+		thread_t *thread = list_get_instance(list_first(&wq->sleepers),
+		    thread_t, wq_link);
 		
 		irq_spinlock_lock(&thread->lock, false);
@@ -407,5 +407,5 @@
 	}
 	
-	list_append(&THREAD->wq_link, &wq->head);
+	list_append(&THREAD->wq_link, &wq->sleepers);
 	
 	/*
@@ -464,5 +464,5 @@
 	
 loop:
-	if (list_empty(&wq->head)) {
+	if (list_empty(&wq->sleepers)) {
 		wq->missed_wakeups++;
 		if ((count) && (mode == WAKEUP_ALL))
@@ -473,5 +473,6 @@
 	
 	count++;
-	thread_t *thread = list_get_instance(wq->head.next, thread_t, wq_link);
+	thread_t *thread = list_get_instance(list_first(&wq->sleepers),
+	    thread_t, wq_link);
 	
 	/*
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/syscall/syscall.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,4 +41,5 @@
 #include <proc/program.h>
 #include <mm/as.h>
+#include <mm/page.h>
 #include <print.h>
 #include <arch.h>
@@ -118,4 +119,5 @@
 
 syshandler_t syscall_table[SYSCALL_END] = {
+	/* System management syscalls. */
 	(syshandler_t) sys_klog,
 	(syshandler_t) sys_tls_set,
@@ -126,4 +128,5 @@
 	(syshandler_t) sys_thread_get_id,
 	(syshandler_t) sys_thread_usleep,
+	(syshandler_t) sys_thread_udelay,
 	
 	(syshandler_t) sys_task_get_id,
@@ -145,4 +148,7 @@
 	(syshandler_t) sys_as_get_unmapped_area,
 	
+	/* Page mapping related syscalls. */
+	(syshandler_t) sys_page_find_mapping,
+	
 	/* IPC related syscalls. */
 	(syshandler_t) sys_ipc_call_sync_fast,
@@ -161,4 +167,5 @@
 	/* Event notification syscalls. */
 	(syshandler_t) sys_event_subscribe,
+	(syshandler_t) sys_event_unmask,
 	
 	/* Capabilities related syscalls. */
@@ -173,5 +180,5 @@
 	(syshandler_t) sys_unregister_irq,
 	
-	/* Sysinfo syscalls */
+	/* Sysinfo syscalls. */
 	(syshandler_t) sys_sysinfo_get_tag,
 	(syshandler_t) sys_sysinfo_get_value,
@@ -179,7 +186,6 @@
 	(syshandler_t) sys_sysinfo_get_data,
 	
-	/* Debug calls */
-	(syshandler_t) sys_debug_enable_console,
-	(syshandler_t) sys_debug_disable_console
+	/* Kernel console syscalls. */
+	(syshandler_t) sys_debug_activate_console
 };
 
Index: kernel/generic/src/sysinfo/stats.c
===================================================================
--- kernel/generic/src/sysinfo/stats.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/sysinfo/stats.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,5 @@
 
 #include <typedefs.h>
-#include <sysinfo/abi.h>
+#include <abi/sysinfo.h>
 #include <sysinfo/stats.h>
 #include <sysinfo/sysinfo.h>
@@ -173,7 +173,5 @@
 	
 	/* Walk the B+ tree and count pages */
-	link_t *cur;
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
@@ -218,7 +216,5 @@
 	
 	/* Walk the B+ tree and count pages */
-	link_t *cur;
-	for (cur = as->as_area_btree.leaf_head.next;
-	    cur != &as->as_area_btree.leaf_head; cur = cur->next) {
+	list_foreach(as->as_area_btree.leaf_list, cur) {
 		btree_node_t *node =
 		    list_get_instance(cur, btree_node_t, leaf_link);
Index: kernel/generic/src/time/clock.c
===================================================================
--- kernel/generic/src/time/clock.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/time/clock.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -94,4 +94,5 @@
 	clock_parea.frames = 1;
 	clock_parea.unpriv = true;
+	clock_parea.mapped = false;
 	ddi_parea_register(&clock_parea);
 	
@@ -163,6 +164,7 @@
 		
 		link_t *cur;
-		while ((cur = CPU->timeout_active_head.next) != &CPU->timeout_active_head) {
-			timeout_t *timeout = list_get_instance(cur, timeout_t, link);
+		while ((cur = list_first(&CPU->timeout_active_list)) != NULL) {
+			timeout_t *timeout = list_get_instance(cur, timeout_t,
+			    link);
 			
 			irq_spinlock_lock(&timeout->lock, false);
Index: kernel/generic/src/time/delay.c
===================================================================
--- kernel/generic/src/time/delay.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/time/delay.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
  
 #include <time/delay.h>
+#include <proc/thread.h>
 #include <typedefs.h>
 #include <cpu.h>
@@ -42,9 +43,7 @@
 #include <arch.h>
 
-/** Active delay
+/** Delay the execution for the given number of microseconds (or slightly more).
  *
- * Delay the execution for the given number
- * of microseconds (or slightly more). The delay
- * is implemented as CPU calibrated active loop.
+ * The delay is implemented as active delay loop.
  *
  * @param usec Number of microseconds to sleep.
@@ -52,15 +51,14 @@
 void delay(uint32_t usec)
 {
-	ipl_t ipl;
-	
 	/* 
-	 * The delay loop is calibrated for each and every
-	 * CPU in the system. Therefore it is necessary to
-	 * call interrupts_disable() before calling the
-	 * asm_delay_loop().
+	 * The delay loop is calibrated for each and every CPU in the system.
+	 * If running in a thread context, it is therefore necessary to disable
+	 * thread migration. We want to do this in a lightweight manner.
 	 */
-	ipl = interrupts_disable();
+	if (THREAD)
+		thread_migration_disable();
 	asm_delay_loop(usec * CPU->delay_loop_const);
-	interrupts_restore(ipl);
+	if (THREAD)
+		thread_migration_enable();
 }
 
Index: kernel/generic/src/time/timeout.c
===================================================================
--- kernel/generic/src/time/timeout.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/time/timeout.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -54,5 +54,5 @@
 {
 	irq_spinlock_initialize(&CPU->timeoutlock, "cpu.timeoutlock");
-	list_initialize(&CPU->timeout_active_head);
+	list_initialize(&CPU->timeout_active_list);
 }
 
@@ -119,6 +119,6 @@
 	timeout_t *target = NULL;
 	link_t *cur;
-	for (cur = CPU->timeout_active_head.next;
-	    cur != &CPU->timeout_active_head; cur = cur->next) {
+	for (cur = CPU->timeout_active_list.head.next;
+	    cur != &CPU->timeout_active_list.head; cur = cur->next) {
 		target = list_get_instance(cur, timeout_t, link);
 		irq_spinlock_lock(&target->lock, false);
@@ -135,5 +135,5 @@
 	/* Avoid using cur->prev directly */
 	link_t *prev = cur->prev;
-	list_prepend(&timeout->link, prev);
+	list_insert_after(&timeout->link, prev);
 	
 	/*
@@ -146,5 +146,5 @@
 	 * Decrease ticks of timeout's immediate succesor by timeout->ticks.
 	 */
-	if (cur != &CPU->timeout_active_head) {
+	if (cur != &CPU->timeout_active_list.head) {
 		irq_spinlock_lock(&target->lock, false);
 		target->ticks -= timeout->ticks;
@@ -184,9 +184,9 @@
 	/*
 	 * Now we know for sure that timeout hasn't been activated yet
-	 * and is lurking in timeout->cpu->timeout_active_head queue.
+	 * and is lurking in timeout->cpu->timeout_active_list.
 	 */
 	
 	link_t *cur = timeout->link.next;
-	if (cur != &timeout->cpu->timeout_active_head) {
+	if (cur != &timeout->cpu->timeout_active_list.head) {
 		timeout_t *tmp = list_get_instance(cur, timeout_t, link);
 		irq_spinlock_lock(&tmp->lock, false);
Index: kernel/generic/src/udebug/udebug.c
===================================================================
--- kernel/generic/src/udebug/udebug.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/udebug/udebug.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -406,6 +406,5 @@
 	
 	/* Finish debugging of all userspace threads */
-	link_t *cur;
-	for (cur = task->th_head.next; cur != &task->th_head; cur = cur->next) {
+	list_foreach(task->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		
Index: kernel/generic/src/udebug/udebug_ops.c
===================================================================
--- kernel/generic/src/udebug/udebug_ops.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/generic/src/udebug/udebug_ops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -196,6 +196,5 @@
 	/* Set udebug.active on all of the task's userspace threads. */
 	
-	link_t *cur;
-	for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
+	list_foreach(TASK->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		
@@ -390,6 +389,5 @@
 	
 	/* FIXME: make sure the thread isn't past debug shutdown... */
-	link_t *cur;
-	for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
+	list_foreach(TASK->threads, cur) {
 		thread_t *thread = list_get_instance(cur, thread_t, th_link);
 		
Index: rnel/test/fpu/fpu1.def
===================================================================
--- kernel/test/fpu/fpu1.def	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"fpu1",
-	"Intel FPU test",
-	&test_fpu1,
-	true
-},
Index: rnel/test/fpu/fpu1_ia64.c
===================================================================
--- kernel/test/fpu/fpu1_ia64.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,172 +1,0 @@
-/*
- * Copyright (c) 2005 Jakub Vana
- * Copyright (c) 2005 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <print.h>
-#include <debug.h>
-
-#include <test.h>
-#include <atomic.h>
-#include <proc/thread.h>
-
-#include <arch.h>
-#include <arch/arch.h>
-
-
-#define THREADS   150
-#define ATTEMPTS  100
-
-#define E_10e8   271828182
-#define PI_10e8  3141592
-
-static inline long double sqrt(long double a)
-{
-	long double x =	1;
-	long double lx = 0;
-	
-	if (a < 0.00000000000000001)
-		return 0;
-		
-	while (x != lx) {
-		lx = x;
-		x = (x + (a / x)) / 2;
-	}
-	
-	return x;
-}
-
-static atomic_t threads_ok;
-static atomic_t threads_fault;
-static waitq_t can_start;
-
-static void e(void *data)
-{
-	int i;
-	double e, d, le, f;
-	
-	thread_detach(THREAD);
-	
-	waitq_sleep(&can_start);
-	
-	for (i = 0; i<ATTEMPTS; i++) {
-		le = -1;
-		e = 0;
-		f = 1;
-		
-		for (d = 1; e != le; d *= f, f += 1) {
-			le = e;
-			e = e + 1 / d;
-		}
-		
-		if ((int) (100000000 * e) != E_10e8) {
-			TPRINTF("tid%" PRIu64 ": e*10e8=%zd should be %" PRIun "\n", THREAD->tid, (sysarg_t) (100000000 * e), (sysarg_t) E_10e8);
-			atomic_inc(&threads_fault);
-			break;
-		}
-	}
-	atomic_inc(&threads_ok);
-}
-
-static void pi(void *data)
-{
-	int i;
-	double lpi, pi;
-	double n, ab, ad;
-	
-	thread_detach(THREAD);
-	
-	waitq_sleep(&can_start);
-	
-	for (i = 0; i < ATTEMPTS; i++) {
-		lpi = -1;
-		pi = 0;
-		
-		for (n = 2, ab = sqrt(2); lpi != pi; n *= 2, ab = ad) {
-			double sc, cd;
-			
-			sc = sqrt(1 - (ab * ab / 4));
-			cd = 1 - sc;
-			ad = sqrt(ab * ab / 4 + cd * cd);
-			lpi = pi;
-			pi = 2 * n * ad;
-		}
-		
-		if ((int) (1000000 * pi) != PI_10e8) {
-			TPRINTF("tid%" PRIu64 ": pi*10e8=%zd should be %" PRIun "\n", THREAD->tid, (sysarg_t) (1000000 * pi), (sysarg_t) (PI_10e8 / 100));
-			atomic_inc(&threads_fault);
-			break;
-		}
-	}
-	atomic_inc(&threads_ok);
-}
-
-const char *test_fpu1(void)
-{
-	unsigned int i;
-	atomic_count_t total = 0;
-	
-	waitq_initialize(&can_start);
-	atomic_set(&threads_ok, 0);
-	atomic_set(&threads_fault, 0);
-	
-	TPRINTF("Creating %u threads... ", 2 * THREADS);
-	
-	for (i = 0; i < THREADS; i++) {
-		thread_t *t;
-		
-		if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) {
-			TPRINTF("could not create thread %u\n", 2 * i);
-			break;
-		}
-		thread_ready(t);
-		total++;
-		
-		if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) {
-			TPRINTF("could not create thread %u\n", 2 * i + 1);
-			break;
-		}
-		thread_ready(t);
-		total++;
-	}
-	
-	TPRINTF("ok\n");
-	
-	thread_sleep(1);
-	waitq_wakeup(&can_start, WAKEUP_ALL);
-	
-	while (atomic_get(&threads_ok) != total) {
-		TPRINTF("Threads left: %" PRIua "\n",
-		    total - atomic_get(&threads_ok));
-		thread_sleep(1);
-	}
-	
-	if (atomic_get(&threads_fault) == 0)
-		return NULL;
-	
-	return "Test failed";
-}
Index: rnel/test/fpu/fpu1_skip.c
===================================================================
--- kernel/test/fpu/fpu1_skip.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,34 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-#include <test.h>
-
-const char *test_fpu1(void)
-{
-	return NULL;
-}
Index: rnel/test/fpu/fpu1_x86.c
===================================================================
--- kernel/test/fpu/fpu1_x86.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,170 +1,0 @@
-/*
- * Copyright (c) 2005 Jakub Vana
- * Copyright (c) 2005 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <print.h>
-#include <debug.h>
-
-#include <test.h>
-#include <atomic.h>
-#include <proc/thread.h>
-
-#include <arch.h>
-#include <arch/arch.h>
-
-
-#define THREADS   150
-#define ATTEMPTS  100
-
-#define E_10e8   271828182
-#define PI_10e8  314159265
-
-static inline double sqrt(double x)
-{
-	double v;
-	
-	asm (
-		"fsqrt\n"
-		: "=t" (v)
-		: "0" (x)
-	);
-	
-	return v;
-}
-
-static atomic_t threads_ok;
-static atomic_t threads_fault;
-static waitq_t can_start;
-
-static void e(void *data)
-{
-	int i;
-	double e, d, le, f;
-	
-	thread_detach(THREAD);
-	
-	waitq_sleep(&can_start);
-	
-	for (i = 0; i<ATTEMPTS; i++) {
-		le = -1;
-		e = 0;
-		f = 1;
-		
-		for (d = 1; e != le; d *= f, f += 1) {
-			le = e;
-			e = e + 1 / d;
-		}
-		
-		if ((int) (100000000 * e) != E_10e8) {
-			TPRINTF("tid%" PRIu64 ": e*10e8=%" PRIun " should be %" PRIun "\n",
-			    THREAD->tid, (sysarg_t) (100000000 * e), (sysarg_t) E_10e8);
-			atomic_inc(&threads_fault);
-			break;
-		}
-	}
-	atomic_inc(&threads_ok);
-}
-
-static void pi(void *data)
-{
-	int i;
-	double lpi, pi;
-	double n, ab, ad;
-	
-	thread_detach(THREAD);
-	
-	waitq_sleep(&can_start);
-	
-	for (i = 0; i < ATTEMPTS; i++) {
-		lpi = -1;
-		pi = 0;
-		
-		for (n = 2, ab = sqrt(2); lpi != pi; n *= 2, ab = ad) {
-			double sc, cd;
-			
-			sc = sqrt(1 - (ab * ab / 4));
-			cd = 1 - sc;
-			ad = sqrt(ab * ab / 4 + cd * cd);
-			lpi = pi;
-			pi = 2 * n * ad;
-		}
-		
-		if ((int) (100000000 * pi) != PI_10e8) {
-			TPRINTF("tid%" PRIu64 ": pi*10e8=%" PRIun " should be %" PRIun "\n",
-			    THREAD->tid, (sysarg_t) (100000000 * pi), (sysarg_t) PI_10e8);
-			atomic_inc(&threads_fault);
-			break;
-		}
-	}
-	atomic_inc(&threads_ok);
-}
-
-const char *test_fpu1(void)
-{
-	unsigned int i;
-	atomic_count_t total = 0;
-	
-	waitq_initialize(&can_start);
-	atomic_set(&threads_ok, 0);
-	atomic_set(&threads_fault, 0);
-	
-	TPRINTF("Creating %u threads... ", 2 * THREADS);
-	
-	for (i = 0; i < THREADS; i++) {
-		thread_t *t;
-		
-		if (!(t = thread_create(e, NULL, TASK, 0, "e", false))) {
-			TPRINTF("could not create thread %u\n", 2 * i);
-			break;
-		}
-		thread_ready(t);
-		total++;
-		
-		if (!(t = thread_create(pi, NULL, TASK, 0, "pi", false))) {
-			TPRINTF("could not create thread %u\n", 2 * i + 1);
-			break;
-		}
-		thread_ready(t);
-		total++;
-	}
-	
-	TPRINTF("ok\n");
-	
-	thread_sleep(1);
-	waitq_wakeup(&can_start, WAKEUP_ALL);
-	
-	while (atomic_get(&threads_ok) != total) {
-		TPRINTF("Threads left: %" PRIua "\n", total - atomic_get(&threads_ok));
-		thread_sleep(1);
-	}
-	
-	if (atomic_get(&threads_fault) == 0)
-		return NULL;
-	
-	return "Test failed";
-}
Index: rnel/test/fpu/mips2.c
===================================================================
--- kernel/test/fpu/mips2.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,154 +1,0 @@
-/*
- * Copyright (c) 2005 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <print.h>
-#include <debug.h>
-
-#include <test.h>
-#include <atomic.h>
-#include <proc/thread.h>
-#include <time/delay.h>
-
-#include <arch.h>
-
-#define THREADS   50
-#define DELAY     10000L
-#define ATTEMPTS  5
-
-static atomic_t threads_ok;
-static atomic_t threads_fault;
-static waitq_t can_start;
-
-static void testit1(void *data)
-{
-	int i;
-	int arg __attribute__((aligned(16))) = (int) ((sysarg_t) data);
-	int after_arg __attribute__((aligned(16)));
-	
-	thread_detach(THREAD);
-	
-	waitq_sleep(&can_start);
-	
-	for (i = 0; i < ATTEMPTS; i++) {
-		asm volatile (
-			"mtc1 %0,$1"
-			: "=r" (arg)
-		);
-		
-		delay(DELAY);
-		
-		asm volatile (
-			"mfc1 %0, $1"
-			: "=r" (after_arg)
-		);
-		
-		if (arg != after_arg) {
-			TPRINTF("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg);
-			atomic_inc(&threads_fault);
-			break;
-		}
-	}
-	atomic_inc(&threads_ok);
-}
-
-static void testit2(void *data)
-{
-	int i;
-	int arg __attribute__((aligned(16))) = (int) ((sysarg_t) data);
-	int after_arg __attribute__((aligned(16)));
-	
-	thread_detach(THREAD);
-	
-	waitq_sleep(&can_start);
-	
-	for (i = 0; i < ATTEMPTS; i++) {
-		asm volatile (
-			"mtc1 %0,$1"
-			: "=r" (arg)
-		);
-		
-		scheduler();
-		asm volatile (
-			"mfc1 %0,$1"
-			: "=r" (after_arg)
-		);
-		
-		if (arg != after_arg) {
-			TPRINTF("General reg tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg);
-			atomic_inc(&threads_fault);
-			break;
-		}
-	}
-	atomic_inc(&threads_ok);
-}
-
-
-const char *test_mips2(void)
-{
-	unsigned int i;
-	atomic_count_t total = 0;
-	
-	waitq_initialize(&can_start);
-	atomic_set(&threads_ok, 0);
-	atomic_set(&threads_fault, 0);
-	
-	TPRINTF("Creating %u threads... ", 2 * THREADS);
-	
-	for (i = 0; i < THREADS; i++) {
-		thread_t *t;
-		
-		if (!(t = thread_create(testit1, (void *) ((sysarg_t) 2 * i), TASK, 0, "testit1", false))) {
-			TPRINTF("could not create thread %u\n", 2 * i);
-			break;
-		}
-		thread_ready(t);
-		total++;
-		
-		if (!(t = thread_create(testit2, (void *) ((sysarg_t) 2 * i + 1), TASK, 0, "testit2", false))) {
-			TPRINTF("could not create thread %u\n", 2 * i + 1);
-			break;
-		}
-		thread_ready(t);
-		total++;
-	}
-	
-	TPRINTF("ok\n");
-	
-	thread_sleep(1);
-	waitq_wakeup(&can_start, WAKEUP_ALL);
-	
-	while (atomic_get(&threads_ok) != total) {
-		TPRINTF("Threads left: %d\n", total - atomic_get(&threads_ok));
-		thread_sleep(1);
-	}
-	
-	if (atomic_get(&threads_fault) == 0)
-		return NULL;
-	
-	return "Test failed";
-}
Index: rnel/test/fpu/mips2.def
===================================================================
--- kernel/test/fpu/mips2.def	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"mips2",
-	"MIPS FPU test",
-	&test_mips2,
-	true
-},
Index: rnel/test/fpu/mips2_skip.c
===================================================================
--- kernel/test/fpu/mips2_skip.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,34 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-#include <test.h>
-
-const char *test_mips2(void)
-{
-	return NULL;
-}
Index: rnel/test/fpu/sse1.c
===================================================================
--- kernel/test/fpu/sse1.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,152 +1,0 @@
-/*
- * Copyright (c) 2005 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <print.h>
-#include <debug.h>
-
-#include <test.h>
-#include <atomic.h>
-#include <proc/thread.h>
-#include <time/delay.h>
-
-#include <arch.h>
-
-#define THREADS   25
-#define DELAY     10000L
-#define ATTEMPTS  5
-
-static atomic_t threads_ok;
-static atomic_t threads_fault;
-static waitq_t can_start;
-
-static void testit1(void *data)
-{
-	int i;
-	int arg __attribute__((aligned(16))) = (int) ((sysarg_t) data);
-	int after_arg __attribute__((aligned(16)));
-	
-	thread_detach(THREAD);
-	
-	waitq_sleep(&can_start);
-	
-	for (i = 0; i < ATTEMPTS; i++) {
-		asm volatile (
-			"movlpd %[arg], %%xmm2\n"
-			: [arg] "=m" (arg)
-		);
-		
-		delay(DELAY);
-		asm volatile (
-			"movlpd %%xmm2, %[after_arg]\n"
-			: [after_arg] "=m" (after_arg)
-		);
-		
-		if (arg != after_arg) {
-			TPRINTF("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg);
-			atomic_inc(&threads_fault);
-			break;
-		}
-	}
-	atomic_inc(&threads_ok);
-}
-
-static void testit2(void *data)
-{
-	int i;
-	int arg __attribute__((aligned(16))) = (int) ((sysarg_t) data);
-	int after_arg __attribute__((aligned(16)));
-	
-	thread_detach(THREAD);
-	
-	waitq_sleep(&can_start);
-	
-	for (i = 0; i < ATTEMPTS; i++) {
-		asm volatile (
-			"movlpd %[arg], %%xmm2\n"
-			: [arg] "=m" (arg)
-		);
-		
-		scheduler();
-		asm volatile (
-			"movlpd %%xmm2, %[after_arg]\n"
-			: [after_arg] "=m" (after_arg)
-		);
-		
-		if (arg != after_arg) {
-			TPRINTF("tid%" PRIu64 ": arg(%d) != %d\n", THREAD->tid, arg, after_arg);
-			atomic_inc(&threads_fault);
-			break;
-		}
-	}
-	atomic_inc(&threads_ok);
-}
-
-const char *test_sse1(void)
-{
-	unsigned int i;
-	atomic_count_t total = 0;
-	
-	waitq_initialize(&can_start);
-	atomic_set(&threads_ok, 0);
-	atomic_set(&threads_fault, 0);
-	
-	TPRINTF("Creating %u threads... ", 2 * THREADS);
-	
-	for (i = 0; i < THREADS; i++) {
-		thread_t *t;
-		
-		if (!(t = thread_create(testit1, (void *) ((sysarg_t) 2 * i), TASK, 0, "testit1", false))) {
-			TPRINTF("could not create thread %u\n", 2 * i);
-			break;
-		}
-		thread_ready(t);
-		total++;
-		
-		if (!(t = thread_create(testit2, (void *) ((sysarg_t) 2 * i + 1), TASK, 0, "testit2", false))) {
-			TPRINTF("could not create thread %u\n", 2 * i + 1);
-			break;
-		}
-		thread_ready(t);
-		total++;
-	}
-	
-	TPRINTF("ok\n");
-	
-	thread_sleep(1);
-	waitq_wakeup(&can_start, WAKEUP_ALL);
-	
-	while (atomic_get(&threads_ok) != total) {
-		TPRINTF("Threads left: %" PRIua "\n", total - atomic_get(&threads_ok));
-		thread_sleep(1);
-	}
-	
-	if (atomic_get(&threads_fault) == 0)
-		return NULL;
-	
-	return "Test failed";
-}
Index: rnel/test/fpu/sse1.def
===================================================================
--- kernel/test/fpu/sse1.def	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"sse1",
-	"Intel SEE test",
-	&test_sse1,
-	true
-},
Index: rnel/test/fpu/sse1_skip.c
===================================================================
--- kernel/test/fpu/sse1_skip.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,34 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-#include <test.h>
-
-const char *test_sse1(void)
-{
-	return NULL;
-}
Index: kernel/test/mm/mapping1.c
===================================================================
--- kernel/test/mm/mapping1.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/test/mm/mapping1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,4 +35,5 @@
 #include <typedefs.h>
 #include <debug.h>
+#include <arch.h>
 
 #define PAGE0  0x10000000
@@ -58,4 +59,6 @@
 	*((uint32_t *) frame1) = VALUE1;
 	
+	page_table_lock(AS, true);
+
 	TPRINTF("Mapping virtual address %p to physical address %p.\n",
 	    (void *) PAGE0, (void *) KA2PA(frame0));
@@ -65,4 +68,6 @@
 	    (void *) PAGE1, (void *) KA2PA(frame1));
 	page_mapping_insert(AS_KERNEL, PAGE1, KA2PA(frame1), PAGE_PRESENT | PAGE_WRITE);
+
+	page_table_unlock(AS, true);
 	
 	v0 = *((uint32_t *) PAGE0);
Index: kernel/test/synch/semaphore2.c
===================================================================
--- kernel/test/synch/semaphore2.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/test/synch/semaphore2.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,4 @@
 #include <synch/waitq.h>
 #include <synch/semaphore.h>
-#include <synch/synch.h>
 #include <synch/spinlock.h>
 
Index: kernel/test/test.c
===================================================================
--- kernel/test/test.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/test/test.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,7 +43,4 @@
 #include <debug/mips1.def>
 #include <fault/fault1.def>
-#include <fpu/fpu1.def>
-#include <fpu/sse1.def>
-#include <fpu/mips2.def>
 #include <mm/falloc1.def>
 #include <mm/falloc2.def>
Index: kernel/test/test.h
===================================================================
--- kernel/test/test.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ kernel/test/test.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -61,7 +61,4 @@
 extern const char *test_mips1(void);
 extern const char *test_fault1(void);
-extern const char *test_fpu1(void);
-extern const char *test_sse1(void);
-extern const char *test_mips2(void);
 extern const char *test_falloc1(void);
 extern const char *test_falloc2(void);
Index: release/Makefile
===================================================================
--- release/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ release/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,5 +34,5 @@
 PROFILES = amd64 arm32/GXemul arm32/integratorcp arm32/gta02 ia32 \
     ia64/i460GX ia64/ski mips32/GXemul mips32/msim sparc64/niagara \
-    sparc64/serengeti sparc64/ultra
+    sparc64/ultra
 
 BZR = bzr
Index: tools/autotool.py
===================================================================
--- tools/autotool.py	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ tools/autotool.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -243,5 +243,7 @@
 	outf.close()
 	
-	args = [common['CC'], "-S", "-o", PROBE_OUTPUT, PROBE_SOURCE]
+	args = [common['CC']]
+	args.extend(common['CC_ARGS'])
+	args.extend(["-S", "-o", PROBE_OUTPUT, PROBE_SOURCE])
 	
 	try:
@@ -361,4 +363,7 @@
 		typedefs.append({'oldtype': "signed %s" % probe['signed_sizes'][b], 'newtype': "int%u_t" % (b * 8)})
 		
+		macros.append({'oldmacro': "unsigned %s" % probe['unsigned_sizes'][b], 'newmacro': "UINT%u_T" % (b * 8)})
+		macros.append({'oldmacro': "signed %s" % probe['signed_sizes'][b], 'newmacro': "INT%u_T" % (b * 8)})
+		
 		macros.append({'oldmacro': "\"%so\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIo%u" % (b * 8)})
 		macros.append({'oldmacro': "\"%su\"" % probe['unsigned_strcs'][b], 'newmacro': "PRIu%u" % (b * 8)})
@@ -501,5 +506,5 @@
 		cross_prefix = os.environ['CROSS_PREFIX']
 	else:
-		cross_prefix = "/usr/local"
+		cross_prefix = "/usr/local/cross"
 	
 	# Prefix binutils tools on Solaris
@@ -523,4 +528,5 @@
 		
 		# Compiler
+		common['CC_ARGS'] = []
 		if (config['COMPILER'] == "gcc_cross"):
 			if (config['PLATFORM'] == "abs32le"):
@@ -536,4 +542,5 @@
 				if (config['CROSS_TARGET'] == "mips32"):
 					gnu_target = "mipsel-linux-gnu"
+					common['CC_ARGS'].append("-mabi=32")
 			
 			if (config['PLATFORM'] == "amd64"):
@@ -555,4 +562,5 @@
 			if (config['PLATFORM'] == "mips32"):
 				check_config(config, "MACHINE")
+				common['CC_ARGS'].append("-mabi=32")
 				
 				if ((config['MACHINE'] == "lgxemul") or (config['MACHINE'] == "msim")):
@@ -563,4 +571,12 @@
 					target = "mips32eb"
 					gnu_target = "mips-linux-gnu"
+			
+			if (config['PLATFORM'] == "mips64"):
+				check_config(config, "MACHINE")
+				common['CC_ARGS'].append("-mabi=64")
+				
+				if (config['MACHINE'] == "msim"):
+					target = config['PLATFORM']
+					gnu_target = "mips64el-linux-gnu"
 			
 			if (config['PLATFORM'] == "ppc32"):
Index: tools/filldir.py
===================================================================
--- tools/filldir.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ tools/filldir.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2011 Martin Sucha
+# 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.
+#
+
+"""
+Fill a directory with N empty directories
+"""
+
+import sys
+import os
+import os.path
+
+if len(sys.argv) < 3:
+	print 'Usage: filldir <parent-dir> <count>'
+	exit(2)
+
+parent = sys.argv[1]
+num = int(sys.argv[2])
+
+i = 0
+while i < num:
+	name = hex(i)[2:].zfill(5)
+	path = os.path.join(parent, name)
+	os.mkdir(path)
+	i += 1
Index: tools/gentestfile.py
===================================================================
--- tools/gentestfile.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ tools/gentestfile.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2011 Martin Sucha
+# 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.
+#
+
+"""
+Generate a file to be used by app/testread
+"""
+
+import struct
+import sys
+
+if len(sys.argv) < 2:
+	print "Usage: gentestfile.py <count of 64-bit numbers to output>"
+	exit()
+
+m = long(sys.argv[1])
+i = 0
+pow_2_64 = 2 ** 64
+st = struct.Struct('<Q')
+while i < m:
+	sys.stdout.write(st.pack(i))
+	i = (i + 1) % pow_2_64
+
Index: tools/imgutil.py
===================================================================
--- tools/imgutil.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ tools/imgutil.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2008 Martin Decky
+# Copyright (c) 2011 Martin Sucha
+# 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.
+#
+
+"""
+Utilities for filesystem image creators
+"""
+
+import os
+import stat
+
+exclude_names = set(['.svn', '.bzr'])
+
+def align_up(size, alignment):
+	"Return size aligned up to alignment"
+	
+	if (size % alignment == 0):
+		return size
+	
+	return ((size // alignment) + 1) * alignment
+
+def count_up(size, alignment):
+	"Return units necessary to fit the size"
+	
+	if (size % alignment == 0):
+		return (size // alignment)
+	
+	return ((size // alignment) + 1)
+
+def num_of_trailing_bin_zeros(num):
+	"Return number of trailing zeros in binary representation"
+	
+	i = 0
+	if (num == 0): raise ValueError()
+	while num & 1 == 0:
+		i += 1
+		num = num >> 1
+	return i
+
+def get_bit(number, n):
+	"Return True if n-th least-significant bit is set in the given number"
+	
+	return bool((number >> n) & 1)
+
+def set_bit(number, n):
+	"Return the number with n-th least-significant bit set"
+	
+	return number | (1 << n)
+
+class ItemToPack:
+	"Stores information about one directory item to be added to the image"
+	
+	def __init__(self, parent, name):
+		self.parent = parent
+		self.name = name
+		self.path = os.path.join(parent, name)
+		self.stat = os.stat(self.path)
+		self.is_dir = stat.S_ISDIR(self.stat.st_mode)
+		self.is_file = stat.S_ISREG(self.stat.st_mode)
+		self.size = self.stat.st_size
+
+def listdir_items(path):
+	"Return a list of items to be packed inside a fs image"
+	
+	for name in os.listdir(path):
+		if name in exclude_names:
+			continue
+		item = ItemToPack(path, name)
+		if not (item.is_dir or item.is_file):
+			continue
+		yield item
+
+def chunks(item, chunk_size):
+	"Iterate contents of a file in chunks of a given size"
+	
+	inf = open(item.path, 'rb')
+	rd = 0
+	while (rd < item.size):
+		data = bytes(inf.read(chunk_size))
+		yield data
+		rd += len(data)
+	inf.close()
Index: tools/mkarray.py
===================================================================
--- tools/mkarray.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ tools/mkarray.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2011 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.
+#
+"""
+C structure creator
+"""
+
+import sys
+import os
+import struct
+
+def usage(prname):
+	"Print usage syntax"
+	print("%s <DESTINATION> <LABEL> [SOURCE ...]" % prname)
+
+def main():
+	if (len(sys.argv) < 3):
+		usage(sys.argv[0])
+		return
+	
+	dest = sys.argv[1]
+	label = sys.argv[2]
+	
+	header_ctx = []
+	data_ctx = []
+	for src in sys.argv[3:]:
+		basename = os.path.basename(src)
+		symbol = basename.replace(".", "_")
+		
+		print("%s -> %s" % (src, symbol))
+		
+		src_in = open(src, "rb")
+		src_data = src_in.read()
+		src_in.close()
+		
+		header_rec = "extern uint8_t %s[];" % symbol
+		header_ctx.append(header_rec)
+		
+		data_rec = "uint8_t %s[] = {\n\t" % symbol
+		
+		fmt = 'B'
+		item_size = struct.calcsize(fmt)
+		offset = 0
+		cnt = 0
+		
+		while (len(src_data[offset:]) >= item_size):
+			byte = struct.unpack_from(fmt, src_data, offset)
+			
+			if (offset > 0):
+				if ((cnt % 15) == 0):
+					data_rec += ",\n\t"
+				else:
+					data_rec += ", "
+			
+			data_rec += "0x%x" % byte
+			offset += item_size
+			cnt += 1
+		
+		data_rec += "\n};\n"
+		data_ctx.append(data_rec)
+		
+		header_rec = "extern size_t %s_size;" % symbol
+		header_ctx.append(header_rec)
+		
+		data_rec = "size_t %s_size = %u;\n" % (symbol, offset)
+		data_ctx.append(data_rec)
+	
+	header = open("%s.h" % dest, "w")
+	
+	header.write('/***************************************\n')
+	header.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	header.write(' ***************************************/\n\n')
+	header.write("#ifndef %s_H_\n" % label)
+	header.write("#define %s_H_\n\n" % label)
+	header.write("#include <sys/types.h>\n\n")
+	header.write("\n".join(header_ctx))
+	header.write("\n\n")
+	header.write("#endif\n")
+	
+	header.close()
+	
+	data = open("%s.c" % dest, "w")
+	
+	data.write('/***************************************\n')
+	data.write(' * AUTO-GENERATED FILE, DO NOT EDIT!!! *\n')
+	data.write(' ***************************************/\n\n')
+	data.write("#include \"%s.h\"\n\n" % dest)
+	data.write("\n".join(data_ctx))
+	
+	data.close()
+
+if __name__ == '__main__':
+	main()
Index: tools/mkext2.py
===================================================================
--- tools/mkext2.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ tools/mkext2.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,676 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2011 Martin Sucha
+# 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.
+#
+
+"""
+EXT2 creator
+"""
+
+import sys
+import os
+import xstruct
+import array
+import time
+import uuid
+from imgutil import *
+
+GDE_SIZE = 32
+
+STRUCT_DIR_ENTRY_HEAD = """little:
+	uint32_t inode       /* inode number */
+	uint16_t skip        /* byte offset to the next record */
+	uint8_t  name_length /* file attributes */
+	uint8_t  inode_type  /* type of the referenced inode */
+"""
+
+STRUCT_SUPERBLOCK = """little:
+	uint32_t total_inode_count    /* Total number of inodes */
+	uint32_t total_block_count    /* Total number of blocks */
+	uint32_t reserved_block_count /* Total number of reserved blocks */
+	uint32_t free_block_count     /* Total number of free blocks */
+	uint32_t free_inode_count     /* Total number of free inodes */
+	uint32_t first_block          /* Block containing the superblock */
+	uint32_t block_size_log2      /* log_2(block_size) */
+	int32_t  fragment_size_log2   /* log_2(fragment size) */
+	uint32_t blocks_per_group     /* Number of blocks in one block group */
+	uint32_t fragments_per_group  /* Number of fragments per block group */
+	uint32_t inodes_per_group     /* Number of inodes per block group */
+	uint32_t mount_time           /* Time when the filesystem was last mounted */
+	uint32_t write_time           /* Time when the filesystem was last written */
+	uint16_t mount_count          /* Mount count since last full filesystem check */
+	uint16_t max_mount_count      /* Number of mounts after which the fs must be checked */
+	uint16_t magic                /* Magic value */
+	uint16_t state                /* State (mounted/unmounted) */
+	uint16_t error_behavior       /* What to do when errors are encountered */
+	uint16_t rev_minor            /* Minor revision level */
+	uint32_t last_check_time      /* Unix time of last fs check */
+	uint32_t max_check_interval   /* Max unix time interval between checks */
+	uint32_t os                   /* OS that created the filesystem */
+	uint32_t rev_major            /* Major revision level */
+	padding[4] /* default reserved uid and gid */
+	
+	/* Following is for ext2 revision 1 only */
+	uint32_t first_inode
+	uint16_t inode_size
+	uint16_t block_group_number /* Block group where this SB is stored */
+	uint32_t features_compatible
+	uint32_t features_incompatible
+	uint32_t features_read_only
+	char     uuid[16]
+	char     volume_name[16]
+"""
+
+STRUCT_BLOCK_GROUP_DESCRIPTOR = """little:
+	uint32_t block_bitmap_block      /* Block ID for block bitmap */
+	uint32_t inode_bitmap_block      /* Block ID for inode bitmap */
+	uint32_t inode_table_first_block /* Block ID of first block of inode table */
+	uint16_t free_block_count        /* Count of free blocks */
+	uint16_t free_inode_count        /* Count of free inodes */
+	uint16_t directory_inode_count   /* Number of inodes allocated to directories */
+"""
+
+STRUCT_INODE = """little:
+	uint16_t mode
+	uint16_t user_id
+	uint32_t size
+	uint32_t access_time
+	uint32_t creation_time
+	uint32_t modification_time
+	uint32_t deletion_time
+	uint16_t group_id
+	uint16_t usage_count /* Hard link count, when 0 the inode is to be freed */
+	uint32_t reserved_512_blocks /* Size of this inode in 512-byte blocks */
+	uint32_t flags
+	padding[4]
+	uint32_t direct_blocks[12] /* Direct block ids stored in this inode */
+	uint32_t indirect_blocks[3]
+	uint32_t version
+	uint32_t file_acl
+	uint32_t size_high /* For regular files in version >= 1, dir_acl if dir */
+	padding[6]
+	uint16_t mode_high /* Hurd only */
+	uint16_t user_id_high /* Linux/Hurd only */
+	uint16_t group_id_high /* Linux/Hurd only */
+"""
+
+# The following is here to handle byte-order conversion in indirect block lookups
+STRUCT_BLOCK_REFERENCE = """little:
+	uint32_t block_id /* Referenced block ID */
+"""
+
+class Filesystem:	
+	def __init__(self, filename, block_groups, blocks_per_group, inodes_per_group, block_size, inode_size, reserved_inode_count):
+		"Initialize the filesystem writer"
+		
+		outf = open(filename, "w+b")
+		# Set the correct size of the image, so that we can read arbitrary position
+		outf.truncate(block_size * blocks_per_group * block_groups)
+		self.outf = outf
+		self.uuid = uuid.uuid4()
+		self.block_size = block_size
+		self.inode_size = inode_size
+		self.block_groups = block_groups
+		self.blocks_per_group = blocks_per_group
+		self.inodes_per_group = inodes_per_group
+		self.reserved_inode_count = reserved_inode_count
+		self.gdt_blocks = count_up(block_groups * GDE_SIZE, block_size)
+		self.inode_table_blocks_per_group = (inodes_per_group * inode_size) // block_size
+		self.inode_bitmap_blocks_per_group = count_up(inodes_per_group // 8, block_size)
+		self.block_bitmap_blocks_per_group = count_up(blocks_per_group // 8, block_size)
+		self.total_block_count = self.blocks_per_group * self.block_groups
+		self.total_inode_count = self.inodes_per_group * self.block_groups
+		self.inode_table_blocks = count_up(self.total_inode_count * inode_size, block_size)
+		self.inodes = {}
+		self.superblock_at_block = 2047 // block_size
+		self.block_ids_per_block = self.block_size // 4
+		self.indirect_limits = [12, None, None, None]
+		self.indirect_blocks_per_level = [1, None, None, None]
+		for i in range(1,4):
+			self.indirect_blocks_per_level[i] = self.indirect_blocks_per_level[i-1] * self.block_ids_per_block
+			self.indirect_limits[i] = self.indirect_limits[i-1] + self.indirect_blocks_per_level[i]
+		self.block_allocator = Allocator(0, self.total_block_count)
+		self.inode_allocator = Allocator(1, self.total_inode_count)
+		self.init_gdt()
+		# Set the callbacks after GDT has been initialized
+		self.block_allocator.mark_cb = self.mark_block_cb
+		self.inode_allocator.mark_cb = self.mark_inode_cb
+		self.block_allocator.mark_used_all(range(self.superblock_at_block))
+		self.inode_allocator.mark_used_all(range(1, self.reserved_inode_count + 1))
+		self.root_inode = Inode(self, 2, Inode.TYPE_DIR)
+		self.gdt[0].directory_inode_count += 1
+		self.lost_plus_found = Inode(self, self.inode_allocator.alloc(directory=True), Inode.TYPE_DIR)
+		lpf_dir = DirWriter(self.lost_plus_found)
+		lpf_dir.add(self.lost_plus_found.as_dirent('.'))
+		lpf_dir.add(self.root_inode.as_dirent('..'))
+		lpf_dir.finish()
+	
+	def init_gdt(self):
+		"Initialize block group descriptor table"
+		
+		self.superblock_positions = []
+		self.gdt = []
+		consumed_blocks_per_group = (1 + self.gdt_blocks +
+			    self.inode_bitmap_blocks_per_group +
+			    self.block_bitmap_blocks_per_group +
+			    self.inode_table_blocks_per_group)
+		initial_free_blocks = self.blocks_per_group - consumed_blocks_per_group
+		for bg in range(self.block_groups):
+			base = bg * self.blocks_per_group
+			if (bg == 0):
+				base = self.superblock_at_block
+				self.superblock_positions.append(1024)
+			else:
+				self.superblock_positions.append(base * self.block_size)
+			self.block_allocator.mark_used_all(range(base, base+consumed_blocks_per_group))
+			pos = base + 1 + self.gdt_blocks
+			gde = xstruct.create(STRUCT_BLOCK_GROUP_DESCRIPTOR)
+			gde.block_bitmap_block = pos
+			pos += self.block_bitmap_blocks_per_group
+			gde.inode_bitmap_block = pos
+			pos += self.inode_bitmap_blocks_per_group
+			gde.inode_table_first_block = pos
+			gde.free_block_count = initial_free_blocks
+			gde.free_inode_count = self.inodes_per_group
+			gde.directory_inode_count = 0
+			self.gdt.append(gde)
+	
+	def mark_block_cb(self, block):
+		"Called after a block has been allocated"
+		
+		self.gdt[block // self.blocks_per_group].free_block_count -= 1
+	
+	def mark_inode_cb(self, index, directory=False):
+		"Called after an inode has been allocated"
+		
+		index -= 1
+		gde = self.gdt[index // self.inodes_per_group]
+		gde.free_inode_count -= 1
+		if directory:
+			gde.directory_inode_count += 1		
+	
+	def seek_to_block(self, block, offset=0):
+		"Seek to offset bytes after the start of the given block"
+		
+		if offset < 0 or offset > self.block_size:
+			raise Exception("Invalid in-block offset")
+		self.outf.seek(block * self.block_size + offset)
+	
+	def seek_to_inode(self, index):
+		"Seek to the start of the inode structure for the inode number index"
+		
+		index -= 1
+		if index < 0:
+			raise Exception("Invalid inode number")
+		gde = self.gdt[index // self.inodes_per_group]
+		base_block = gde.inode_table_first_block
+		offset = (index % self.inodes_per_group) * self.inode_size
+		block = base_block + (offset // self.block_size)
+		self.seek_to_block(block, offset % self.block_size)	
+	
+	def subtree_add(self, inode, parent_inode, dirpath, is_root=False):
+		"Recursively add files to the filesystem"
+		
+		dir_writer = DirWriter(inode)	
+		dir_writer.add(inode.as_dirent('.'))
+		dir_writer.add(parent_inode.as_dirent('..'))
+		
+		if is_root:
+			dir_writer.add(self.lost_plus_found.as_dirent('lost+found'))
+
+		for item in listdir_items(dirpath):
+			newidx = self.inode_allocator.alloc(directory = item.is_dir)
+			if item.is_file:
+				child_inode = Inode(self, newidx, Inode.TYPE_FILE)
+				for data in chunks(item, self.block_size):
+					child_inode.write(data)
+			elif item.is_dir:
+				child_inode = Inode(self, newidx, Inode.TYPE_DIR)
+				self.subtree_add(child_inode, inode, item.path)
+		
+			dir_writer.add(child_inode.as_dirent(item.name))
+			self.write_inode(child_inode)
+
+		dir_writer.finish()
+	
+	def write_inode(self, inode):
+		"Write inode information into the inode table"
+		
+		self.seek_to_inode(inode.index)
+		self.outf.write(inode.pack())
+
+	def write_gdt(self):
+		"Write group descriptor table at the current file position"
+		
+		for gde in self.gdt:
+			data = bytes(gde.pack())
+			self.outf.write(data)
+			self.outf.seek(GDE_SIZE-len(data), os.SEEK_CUR)
+	
+	def write_superblock(self, block_group):
+		"Write superblock at the current position"
+		
+		sb = xstruct.create(STRUCT_SUPERBLOCK)
+		sb.total_inode_count = self.total_inode_count
+		sb.total_block_count = self.total_block_count
+		sb.reserved_block_count = 0
+		sb.free_block_count = self.block_allocator.free
+		sb.free_inode_count = self.inode_allocator.free
+		sb.first_block = self.superblock_at_block
+		sb.block_size_log2 = num_of_trailing_bin_zeros(self.block_size) - 10
+		sb.fragment_size_log2 = sb.block_size_log2
+		sb.blocks_per_group = self.blocks_per_group
+		sb.fragments_per_group = self.blocks_per_group
+		sb.inodes_per_group = self.inodes_per_group
+		curtime = int(time.time())
+		sb.mount_time = curtime
+		sb.write_time = curtime
+		sb.mount_count = 0
+		sb.max_mount_count = 21
+		sb.magic = 0xEF53
+		sb.state = 5 # clean
+		sb.error_behavior = 1 # continue on errors
+		sb.rev_minor = 0
+		sb.last_check_time = curtime
+		sb.max_check_interval = 15552000 # 6 months
+		sb.os = 0 # Linux
+		sb.rev_major = 1
+		sb.first_inode = self.reserved_inode_count + 1
+		sb.inode_size = self.inode_size
+		sb.block_group_number = block_group
+		sb.features_compatible = 0
+		sb.features_incompatible = 2 # filetype
+		sb.features_read_only = 0
+		sb.uuid = self.uuid.bytes_le
+		sb.volume_name = 'HelenOS rdimage\0'
+		self.outf.write(bytes(sb.pack()))
+	
+	def write_all_metadata(self):
+		"Write superblocks, block group tables, block and inode bitmaps"
+		
+		bbpg = self.blocks_per_group // 8
+		bipg = self.inodes_per_group // 8
+		def window(arr, index, size):
+			return arr[index * size:(index + 1) * size]
+		
+		for bg_index in xrange(len(self.gdt)):
+			sbpos = self.superblock_positions[bg_index]
+			sbblock = (sbpos + 1023) // self.block_size
+			gde = self.gdt[bg_index]
+			
+			self.outf.seek(sbpos)
+			self.write_superblock(bg_index)
+			
+			self.seek_to_block(sbblock+1)
+			self.write_gdt()
+			
+			self.seek_to_block(gde.block_bitmap_block)
+			self.outf.write(window(self.block_allocator.bitmap, bg_index, bbpg))
+			
+			self.seek_to_block(gde.inode_bitmap_block)
+			self.outf.write(window(self.inode_allocator.bitmap, bg_index, bipg))
+	
+	def close(self):
+		"Write all remaining data to the filesystem and close the file"
+		
+		self.write_inode(self.root_inode)
+		self.write_inode(self.lost_plus_found)
+		self.write_all_metadata()
+		self.outf.close()
+
+class Allocator:
+	def __init__(self, base, count):
+		self.count = count
+		self.base = base
+		self.free = count
+		self.nextidx = 0
+		self.bitmap = array.array('B', [0] * (count // 8))
+		self.mark_cb = None
+	
+	def __contains__(self, item):
+		"Check if the item is already used"
+		
+		bitidx = item - self.base
+		return get_bit(self.bitmap[bitidx // 8], bitidx % 8)
+	
+	def alloc(self, **options):
+		"Allocate a new item"
+		
+		while self.nextidx < self.count and (self.base + self.nextidx) in self:
+			self.nextidx += 1
+		if self.nextidx == self.count:
+			raise Exception("No free item available")
+		item = self.base + self.nextidx
+		self.nextidx += 1
+		self.mark_used(item, **options)
+		return item
+	
+	def mark_used(self, item, **options):
+		"Mark the specified item as used"
+		
+		bitidx = item - self.base
+		if item in self:
+			raise Exception("Item already used: " + str(item))
+		self.free -= 1
+		index = bitidx // 8
+		self.bitmap[index] = set_bit(self.bitmap[index], bitidx % 8)
+		if self.mark_cb:
+			self.mark_cb(item, **options)
+	
+	def mark_used_all(self, items, **options):
+		"Mark all specified items as used"
+		
+		for item in items:
+			self.mark_used(item, **options)
+
+class Inode:
+	TYPE_FILE = 1
+	TYPE_DIR = 2
+	TYPE2MODE = {TYPE_FILE: 8, TYPE_DIR: 4}
+	
+	def __init__(self, fs, index, typ):
+		self.fs = fs
+		self.direct = [None] * 12
+		self.indirect = [None] * 3
+		self.pos = 0
+		self.size = 0
+		self.blocks = 0
+		self.index = index
+		self.type = typ
+		self.refcount = 0
+	
+	def as_dirent(self, name):
+		"Return a DirEntry corresponding to this inode"
+		self.refcount += 1
+		return DirEntry(name, self.index, self.type)
+	
+	def new_block(self, data=True):
+		"Get a new block index from allocator and count it here as belonging to the file"
+		
+		block = self.fs.block_allocator.alloc()
+		self.blocks += 1
+		return block
+	
+	def get_or_add_block(self, block):
+		"Get or add a real block to the file"
+		
+		if block < 12:
+			return self.get_or_add_block_direct(block)
+		return self.get_or_add_block_indirect(block)
+	
+	def get_or_add_block_direct(self, block):
+		"Get or add a real block to the file (direct blocks)"
+		
+		if self.direct[block] == None:
+			self.direct[block] = self.new_block()
+		return self.direct[block]
+	
+	def get_or_add_block_indirect(self, block):
+		"Get or add a real block to the file (indirect blocks)"
+		
+		# Determine the indirection level for the desired block
+		level = None
+		for i in range(4):
+			if block < self.fs.indirect_limits[i]:
+				level = i
+				break
+
+		assert level != None
+	
+		# Compute offsets for the topmost level
+		block_offset_in_level = block - self.fs.indirect_limits[level-1];
+		if self.indirect[level-1] == None:
+			self.indirect[level-1] = self.new_block(data = False)
+		current_block = xstruct.create(STRUCT_BLOCK_REFERENCE)
+		current_block.block_id = self.indirect[level-1]
+		offset_in_block = block_offset_in_level // self.fs.indirect_blocks_per_level[level-1]
+	
+		# Navigate through other levels
+		while level > 0:		
+			assert offset_in_block < self.fs.block_ids_per_block
+			
+			level -= 1
+			
+			self.fs.seek_to_block(current_block.block_id, offset_in_block*4)
+			current_block.unpack(self.fs.outf.read(4))
+			
+			if current_block.block_id == 0:
+				# The block does not exist, so alloc one and write it there
+				self.fs.outf.seek(-4, os.SEEK_CUR)
+				current_block.block_id = self.new_block(data=(level==0))
+				self.fs.outf.write(current_block.pack())
+		
+			# If we are on the last level, break here as
+			# there is no next level to visit
+			if level == 0:
+				break
+		
+			# Visit the next level
+			block_offset_in_level %= self.fs.indirect_blocks_per_level[level];
+			offset_in_block = block_offset_in_level // self.fs.indirect_blocks_per_level[level-1]
+
+		return current_block.block_id
+	
+	def do_seek(self):
+		"Perform a seek to the position indicated by self.pos"
+		
+		block = self.pos // self.fs.block_size
+		real_block = self.get_or_add_block(block)
+		offset = self.pos % self.fs.block_size
+		self.fs.seek_to_block(real_block, offset)
+		
+	def write(self, data):
+		"Write a piece of data (arbitrarily long) as the contents of the inode"
+		
+		data_pos = 0		
+		while data_pos < len(data):
+			bytes_remaining_in_block = self.fs.block_size - (self.pos % self.fs.block_size)
+			bytes_to_write = min(bytes_remaining_in_block, len(data)-data_pos)
+			self.do_seek()
+			self.fs.outf.write(data[data_pos:data_pos + bytes_to_write])
+			self.pos += bytes_to_write
+			data_pos += bytes_to_write
+			self.size = max(self.pos, self.size)
+	
+	def align_size_to_block(self):
+		"Align the size of the inode up to block size"
+		
+		self.size = align_up(self.size, self.fs.block_size)
+	
+	def align_pos(self, bytes):
+		"Align the current position up to bytes boundary"
+		
+		self.pos = align_up(self.pos, bytes)
+	
+	def pack(self):
+		"Pack the inode structure and return the result"
+		
+		data = xstruct.create(STRUCT_INODE)
+		data.mode = (Inode.TYPE2MODE[self.type] << 12)
+		data.mode |= 0x1ff # ugo+rwx
+		data.user_id = 0
+		data.size = self.size & 0xFFFFFFFF
+		data.group_id = 0
+		curtime = int(time.time())
+		data.access_time = curtime
+		data.modification_time = curtime
+		data.creation_time = curtime
+		data.deletion_time = 0
+		data.usage_count = self.refcount
+		data.reserved_512_blocks = self.blocks * (self.fs.block_size // 512)
+		data.flags = 0
+		blockconv = lambda x: 0 if x == None else x
+		data.direct_blocks = map(blockconv, self.direct)
+		data.indirect_blocks = map(blockconv, self.indirect)
+		data.version = 0
+		data.file_acl = 0
+		if self.type == Inode.TYPE_FILE:
+			data.size_high = (self.size >> 32)
+		else:
+			# size_high represents dir_acl in this case
+			data.size_high = 0
+		data.mode_high = 0
+		data.user_id_high = 0
+		data.group_id_high = 0
+		return data.pack()
+		
+class DirEntry:
+	"Represents a linked list directory entry"
+	
+	def __init__(self, name, inode, typ):
+		self.name = name.encode('UTF-8')
+		self.inode = inode
+		self.skip = None
+		self.type = typ
+	
+	def size(self):
+		"Return size of the entry in bytes"
+		
+		return align_up(8 + len(self.name)+1, 4)
+	
+	def write(self, inode):
+		"Write the directory entry into the inode"
+		
+		head = xstruct.create(STRUCT_DIR_ENTRY_HEAD)
+		head.inode = self.inode
+		head.skip = self.skip
+		head.name_length = len(self.name)
+		head.inode_type = self.type
+		inode.write(head.pack())
+		inode.write(self.name+'\0')
+		inode.align_pos(4)
+
+class DirWriter:
+	"Manages writing directory entries into an inode (alignment, etc.)"
+	
+	def __init__(self, inode):
+		self.pos = 0
+		self.inode = inode
+		self.prev_entry = None
+		self.prev_pos = None
+	
+	def prev_write(self):
+		"Write a previously remembered entry"
+		
+		if self.prev_entry:
+			self.prev_entry.skip = self.pos - self.prev_pos
+			if self.inode:
+				self.prev_entry.write(self.inode)
+	
+	def add(self, entry):
+		"Add a directory entry to the directory"
+		
+		size = entry.size()
+		block_size = self.inode.fs.block_size
+		if align_up(self.pos, block_size) < align_up(self.pos + size, block_size):
+			self.pos = align_up(self.pos, block_size)
+		self.prev_write()
+		self.prev_entry = entry
+		self.prev_pos = self.pos
+		self.pos += size
+	
+	def finish(self):
+		"Write the last entry and finish writing the directory contents"
+		
+		if not self.inode:
+			return
+		self.pos = align_up(self.pos, self.inode.fs.block_size)
+		self.prev_write()
+		self.inode.align_size_to_block()
+
+def subtree_stats(root, block_size):
+	"Recursively calculate statistics"
+	
+	blocks = 0
+	inodes = 1
+	dir_writer = DirWriter(None)
+	
+	for item in listdir_items(root):
+		inodes += 1
+		if item.is_file:
+			blocks += count_up(item.size, block_size)
+		elif item.is_dir:
+			subtree_blocks, subtree_inodes = subtree_stats(item.path, block_size)
+			blocks += subtree_blocks
+			inodes += subtree_inodes
+	
+	dir_writer.finish()
+	blocks += count_up(dir_writer.pos, block_size)
+	return (blocks, inodes)
+
+def usage(prname):
+	"Print usage syntax"
+	print(prname + " <EXTRA_BYTES> <PATH> <IMAGE>")
+
+def main():
+	if (len(sys.argv) < 4):
+		usage(sys.argv[0])
+		return
+	
+	if (not sys.argv[1].isdigit()):
+		print("<EXTRA_BYTES> must be a number")
+		return
+	
+	extra_bytes = int(sys.argv[1])
+	
+	path = os.path.abspath(sys.argv[2])
+	if (not os.path.isdir(path)):
+		print("<PATH> must be a directory")
+		return
+	
+	block_size = 4096
+	inode_size = 128
+	reserved_inode_count = 10
+	blocks_per_group = 1024
+	inodes_per_group = 512
+	
+	blocks, inodes = subtree_stats(path, block_size)
+	blocks += count_up(extra_bytes, block_size)
+	inodes += reserved_inode_count
+	
+	inodes_per_group = align_up(inodes_per_group, 8)
+	blocks_per_group = align_up(blocks_per_group, 8)
+	
+	inode_table_blocks_per_group = (inodes_per_group * inode_size) // block_size
+	inode_bitmap_blocks_per_group = count_up(inodes_per_group // 8, block_size)
+	block_bitmap_blocks_per_group = count_up(blocks_per_group // 8, block_size)
+	free_blocks_per_group = blocks_per_group
+	free_blocks_per_group -= inode_table_blocks_per_group
+	free_blocks_per_group -= inode_bitmap_blocks_per_group
+	free_blocks_per_group -= block_bitmap_blocks_per_group
+	free_blocks_per_group -= 10 # one for SB and some reserve for GDT
+	
+	block_groups = max(count_up(inodes, inodes_per_group), count_up(blocks, free_blocks_per_group))
+	
+	fs = Filesystem(sys.argv[3], block_groups, blocks_per_group, inodes_per_group,
+	                        block_size, inode_size, reserved_inode_count)
+	
+	fs.subtree_add(fs.root_inode, fs.root_inode, path, is_root=True)
+	fs.close()
+	
+if __name__ == '__main__':
+	main()
Index: tools/mkfat.py
===================================================================
--- tools/mkfat.py	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ tools/mkfat.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,14 +37,5 @@
 import xstruct
 import array
-
-exclude_names = set(['.svn', '.bzr'])
-
-def align_up(size, alignment):
-	"Return size aligned up to alignment"
-	
-	if (size % alignment == 0):
-		return size
-	
-	return ((size // alignment) + 1) * alignment
+from imgutil import *
 
 def subtree_size(root, cluster_size, dirent_size):
@@ -54,13 +45,10 @@
 	files = 2
 	
-	for name in os.listdir(root):
-		canon = os.path.join(root, name)
-		
-		if (os.path.isfile(canon) and (not name in exclude_names)):
-			size += align_up(os.path.getsize(canon), cluster_size)
+	for item in listdir_items(root):
+		if item.is_file:
+			size += align_up(item.size, cluster_size)
 			files += 1
-		
-		if (os.path.isdir(canon) and (not name in exclude_names)):
-			size += subtree_size(canon, cluster_size, dirent_size)
+		elif item.is_dir:
+			size += subtree_size(item.path, cluster_size, dirent_size)
 			files += 1
 	
@@ -72,14 +60,11 @@
 	return len(os.listdir(root))
 
-def write_file(path, outf, cluster_size, data_start, fat, reserved_clusters):
+def write_file(item, outf, cluster_size, data_start, fat, reserved_clusters):
 	"Store the contents of a file"
 	
-	size = os.path.getsize(path)
 	prev = -1
 	first = 0
 	
-	inf = open(path, "rb")
-	rd = 0;
-	while (rd < size):
+	for data in chunks(item, cluster_size):
 		empty_cluster = fat.index(0)
 		fat[empty_cluster] = 0xffff
@@ -92,11 +77,8 @@
 		prev = empty_cluster
 		
-		data = bytes(inf.read(cluster_size));
 		outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size)
 		outf.write(data)
-		rd += len(data)
-	inf.close()
-	
-	return first, size
+	
+	return first, item.size
 
 def write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster):
@@ -190,9 +172,14 @@
 	parts = name.split('.')
 	
-	if (len(parts) > 0):
+	if len(parts) > 0:
 		fname = parts[0]
 	else:
 		fname = ''
-		
+	
+	if len(fname) > 8:
+		sys.stdout.write("mkfat.py: error: Directory entry " + name +
+		    " base name is longer than 8 characters\n")
+		sys.exit(1);
+	
 	return (fname + '          ').upper()[0:8]
 
@@ -201,8 +188,18 @@
 	parts = name.split('.')
 	
-	if (len(parts) > 1):
+	if len(parts) > 1:
 		ext = parts[1]
 	else:
 		ext = ''
+	
+	if len(parts) > 2:
+		sys.stdout.write("mkfat.py: error: Directory entry " + name +
+		    " has more than one extension\n")
+		sys.exit(1);
+	
+	if len(ext) > 3:
+		sys.stdout.write("mkfat.py: error: Directory entry " + name +
+		    " extension is longer than 3 characters\n")
+		sys.exit(1);
 	
 	return (ext + '   ').upper()[0:3]
@@ -288,14 +285,11 @@
 		empty_cluster = 0
 	
-	for name in os.listdir(root):
-		canon = os.path.join(root, name)
-		
-		if (os.path.isfile(canon) and (not name in exclude_names)):
-			rv = write_file(canon, outf, cluster_size, data_start, fat, reserved_clusters)
-			directory.append(create_dirent(name, False, rv[0], rv[1]))
-		
-		if (os.path.isdir(canon) and (not name in exclude_names)):
-			rv = recursion(False, canon, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
-			directory.append(create_dirent(name, True, rv[0], rv[1]))
+	for item in listdir_items(root):		
+		if item.is_file:
+			rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters)
+			directory.append(create_dirent(item.name, False, rv[0], rv[1]))
+		elif item.is_dir:
+			rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
+			directory.append(create_dirent(item.name, True, rv[0], rv[1]))
 	
 	if (head):
Index: tools/mktmpfs.py
===================================================================
--- tools/mktmpfs.py	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ tools/mktmpfs.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,6 +35,5 @@
 import os
 import xstruct
-
-exclude_names = set(['.svn', '.bzr'])
+from imgutil import listdir_items, chunks
 
 HEADER = """little:
@@ -71,35 +70,26 @@
 	"Recursive directory walk"
 	
-	for name in os.listdir(root):
-		canon = os.path.join(root, name)
-		
-		if (os.path.isfile(canon) and (not name in exclude_names)):
-			size = os.path.getsize(canon)
-			
-			dentry = xstruct.create(DENTRY_FILE % len(name))
+	for item in listdir_items(root):		
+		if item.is_file:			
+			dentry = xstruct.create(DENTRY_FILE % len(item.name))
 			dentry.kind = TMPFS_FILE
-			dentry.fname_len = len(name)
-			dentry.fname = name.encode('ascii')
-			dentry.flen = size
+			dentry.fname_len = len(item.name)
+			dentry.fname = item.name.encode('ascii')
+			dentry.flen = item.size
 			
 			outf.write(dentry.pack())
 			
-			inf = open(canon, "rb")
-			rd = 0;
-			while (rd < size):
-				data = inf.read(4096);
+			for data in chunks(item, 4096):
 				outf.write(data)
-				rd += len(data)
-			inf.close()
 		
-		if (os.path.isdir(canon) and (not name in exclude_names)):
-			dentry = xstruct.create(DENTRY_DIRECTORY % len(name))
+		elif item.is_dir:
+			dentry = xstruct.create(DENTRY_DIRECTORY % len(item.name))
 			dentry.kind = TMPFS_DIRECTORY
-			dentry.fname_len = len(name)
-			dentry.fname = name.encode('ascii')
+			dentry.fname_len = len(item.name)
+			dentry.fname = item.name.encode('ascii')
 			
 			outf.write(dentry.pack())
 			
-			recursion(canon, outf)
+			recursion(item.path, outf)
 			
 			dentry = xstruct.create(DENTRY_NONE)
Index: tools/toolchain.sh
===================================================================
--- tools/toolchain.sh	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ tools/toolchain.sh	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,4 +52,15 @@
 #endif
 EOF
+
+BINUTILS_VERSION="2.21"
+GCC_VERSION="4.6.1"
+GDB_VERSION="7.2"
+
+BASEDIR="`pwd`"
+BINUTILS="binutils-${BINUTILS_VERSION}.tar.bz2"
+GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
+GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2"
+GCC_CPP="gcc-g++-${GCC_VERSION}.tar.bz2"
+GDB="gdb-${GDB_VERSION}.tar.bz2"
 
 #
@@ -139,8 +150,9 @@
 	echo " sparc64    SPARC V9"
 	echo " all        build all targets"
+	echo " parallel   same as 'all', but in parallel"
 	echo
 	echo "The toolchain will be installed to the directory specified by"
 	echo "the CROSS_PREFIX environment variable. If the variable is not"
-	echo "defined, /usr/local will be used by default."
+	echo "defined, /usr/local/cross will be used by default."
 	echo
 	
@@ -194,5 +206,5 @@
 }
 
-download_check() {
+download_fetch() {
 	SOURCE="$1"
 	FILE="$2"
@@ -208,4 +220,15 @@
 }
 
+source_check() {
+	FILE="$1"
+	
+	if [ ! -f "${FILE}" ]; then
+		echo
+		echo "File ${FILE} not found."
+		
+		exit 4
+	fi
+}
+
 cleanup_dir() {
 	DIR="$1"
@@ -241,25 +264,18 @@
 }
 
-patch_binutils() {
-	PLATFORM="$1"
-	
-	if [ "${PLATFORM}" == "arm32" ] ; then
-		patch -p1 <<EOF
-diff -Naur binutils-2.20.orig/gas/config/tc-arm.c binutils-2.20/gas/config/tc-arm.c
---- binutils-2.20.orig/gas/config/tc-arm.c	2009-08-30 00:10:59.000000000 +0200
-+++ binutils-2.20/gas/config/tc-arm.c	2009-11-02 14:25:11.000000000 +0100
-@@ -2485,8 +2485,9 @@
-       know (frag->tc_frag_data.first_map == NULL);
-       frag->tc_frag_data.first_map = symbolP;
-     }
--  if (frag->tc_frag_data.last_map != NULL)
-+  if (frag->tc_frag_data.last_map != NULL) {
-     know (S_GET_VALUE (frag->tc_frag_data.last_map) < S_GET_VALUE (symbolP));
-+  }
-   frag->tc_frag_data.last_map = symbolP;
- }
-EOF
-		check_error $? "Error patching binutils"
-	fi
+prepare() {
+	show_dependencies
+	check_dependecies
+	show_countdown 10
+	
+	BINUTILS_SOURCE="ftp://ftp.gnu.org/gnu/binutils/"
+	GCC_SOURCE="ftp://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/"
+	GDB_SOURCE="ftp://ftp.gnu.org/gnu/gdb/"
+	
+	download_fetch "${BINUTILS_SOURCE}" "${BINUTILS}" "c84c5acc9d266f1a7044b51c85a823f5"
+	download_fetch "${GCC_SOURCE}" "${GCC_CORE}" "0c0e7e35d2215e19de9c97efba507553"
+	download_fetch "${GCC_SOURCE}" "${GCC_OBJC}" "cbf0d4b701827922cf37ba6a4ace0079"
+	download_fetch "${GCC_SOURCE}" "${GCC_CPP}" "0d75ca7ca35b1e7f252223f9d23a6ad1"
+	download_fetch "${GDB_SOURCE}" "${GDB}" "64260e6c56979ee750a01055f16091a5"
 }
 
@@ -268,22 +284,12 @@
 	TARGET="$2"
 	
-	BINUTILS_VERSION="2.20"
-	GCC_VERSION="4.5.1"
-	
-	BINUTILS="binutils-${BINUTILS_VERSION}.tar.bz2"
-	GCC_CORE="gcc-core-${GCC_VERSION}.tar.bz2"
-	GCC_OBJC="gcc-objc-${GCC_VERSION}.tar.bz2"
-	GCC_CPP="gcc-g++-${GCC_VERSION}.tar.bz2"
-	
-	BINUTILS_SOURCE="ftp://ftp.gnu.org/gnu/binutils/"
-	GCC_SOURCE="ftp://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/"
-	
-	WORKDIR="`pwd`"
+	WORKDIR="${BASEDIR}/${PLATFORM}"
 	BINUTILSDIR="${WORKDIR}/binutils-${BINUTILS_VERSION}"
 	GCCDIR="${WORKDIR}/gcc-${GCC_VERSION}"
 	OBJDIR="${WORKDIR}/gcc-obj"
+	GDBDIR="${WORKDIR}/gdb-${GDB_VERSION}"
 	
 	if [ -z "${CROSS_PREFIX}" ] ; then
-		CROSS_PREFIX="/usr/local"
+		CROSS_PREFIX="/usr/local/cross"
 	fi
 	
@@ -291,14 +297,13 @@
 	
 	echo ">>> Downloading tarballs"
-	download_check "${BINUTILS_SOURCE}" "${BINUTILS}" "ee2d3e996e9a2d669808713360fa96f8"
-	download_check "${GCC_SOURCE}" "${GCC_CORE}" "dc8959e31b01a65ce10d269614815054"
-	download_check "${GCC_SOURCE}" "${GCC_OBJC}" "3c11b7037896e967eddf8178af2ddd98"
-	download_check "${GCC_SOURCE}" "${GCC_CPP}" "b294953ff0bb2f20c7acb2bf005d832a"
+	source_check "${BASEDIR}/${BINUTILS}"
+	source_check "${BASEDIR}/${GCC_CORE}"
+	source_check "${BASEDIR}/${GCC_OBJC}"
+	source_check "${BASEDIR}/${GCC_CPP}"
+	source_check "${BASEDIR}/${GDB}"
 	
 	echo ">>> Removing previous content"
 	cleanup_dir "${PREFIX}"
-	cleanup_dir "${OBJDIR}"
-	cleanup_dir "${BINUTILSDIR}"
-	cleanup_dir "${GCCDIR}"
+	cleanup_dir "${WORKDIR}"
 	
 	create_dir "${PREFIX}" "destination directory"
@@ -306,16 +311,19 @@
 	
 	echo ">>> Unpacking tarballs"
-	unpack_tarball "${BINUTILS}" "binutils"
-	unpack_tarball "${GCC_CORE}" "GCC Core"
-	unpack_tarball "${GCC_OBJC}" "Objective C"
-	unpack_tarball "${GCC_CPP}" "C++"
+	cd "${WORKDIR}"
+	check_error $? "Change directory failed."
+	
+	unpack_tarball "${BASEDIR}/${BINUTILS}" "binutils"
+	unpack_tarball "${BASEDIR}/${GCC_CORE}" "GCC Core"
+	unpack_tarball "${BASEDIR}/${GCC_OBJC}" "Objective C"
+	unpack_tarball "${BASEDIR}/${GCC_CPP}" "C++"
+	unpack_tarball "${BASEDIR}/${GDB}" "GDB"
 	
 	echo ">>> Processing binutils (${PLATFORM})"
 	cd "${BINUTILSDIR}"
 	check_error $? "Change directory failed."
-	patch_binutils "${PLATFORM}"
 	
 	change_title "binutils: configure (${PLATFORM})"
-	./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --disable-nls
+	CFLAGS=-Wno-error ./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" --disable-nls
 	check_error $? "Error configuring binutils."
 	
@@ -336,11 +344,21 @@
 	check_error $? "Error compiling/installing GCC."
 	
-	cd "${WORKDIR}"
+	echo ">>> Processing GDB (${PLATFORM})"
+	cd "${GDBDIR}"
 	check_error $? "Change directory failed."
 	
+	change_title "GDB: configure (${PLATFORM})"
+	./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-"
+	check_error $? "Error configuring GDB."
+	
+	change_title "GDB: make (${PLATFORM})"
+	make all install
+	check_error $? "Error compiling/installing GDB."
+	
+	cd "${BASEDIR}"
+	check_error $? "Change directory failed."
+	
 	echo ">>> Cleaning up"
-	cleanup_dir "${OBJDIR}"
-	cleanup_dir "${BINUTILSDIR}"
-	cleanup_dir "${GCCDIR}"
+	cleanup_dir "${WORKDIR}"
 	
 	echo
@@ -352,47 +370,50 @@
 fi
 
-show_dependencies
-check_dependecies
-show_countdown 10
-
 case "$1" in
 	"amd64")
+		prepare
 		build_target "amd64" "amd64-linux-gnu"
 		;;
 	"arm32")
+		prepare
 		build_target "arm32" "arm-linux-gnu"
 		;;
 	"ia32")
+		prepare
 		build_target "ia32" "i686-pc-linux-gnu"
 		;;
 	"ia64")
+		prepare
 		build_target "ia64" "ia64-pc-linux-gnu"
 		;;
-	"ia64")
-		build_target "ia64" "ia64-pc-linux-gnu"
-		;;
 	"mips32")
+		prepare
 		build_target "mips32" "mipsel-linux-gnu"
 		;;
 	"mips32eb")
+		prepare
 		build_target "mips32eb" "mips-linux-gnu"
 		;;
 	"mips64")
+		prepare
 		build_target "mips64" "mips64el-linux-gnu"
 		;;
 	"ppc32")
+		prepare
 		build_target "ppc32" "ppc-linux-gnu"
 		;;
 	"ppc64")
+		prepare
 		build_target "ppc64" "ppc64-linux-gnu"
 		;;
 	"sparc64")
+		prepare
 		build_target "sparc64" "sparc64-linux-gnu"
 		;;
 	"all")
+		prepare
 		build_target "amd64" "amd64-linux-gnu"
 		build_target "arm32" "arm-linux-gnu"
 		build_target "ia32" "i686-pc-linux-gnu"
-		build_target "ia64" "ia64-pc-linux-gnu"
 		build_target "ia64" "ia64-pc-linux-gnu"
 		build_target "mips32" "mipsel-linux-gnu"
@@ -403,4 +424,18 @@
 		build_target "sparc64" "sparc64-linux-gnu"
 		;;
+	"parallel")
+		prepare
+		build_target "amd64" "amd64-linux-gnu" &
+		build_target "arm32" "arm-linux-gnu" &
+		build_target "ia32" "i686-pc-linux-gnu" &
+		build_target "ia64" "ia64-pc-linux-gnu" &
+		build_target "mips32" "mipsel-linux-gnu" &
+		build_target "mips32eb" "mips-linux-gnu" &
+		build_target "mips64" "mips64el-linux-gnu" &
+		build_target "ppc32" "ppc-linux-gnu" &
+		build_target "ppc64" "ppc64-linux-gnu" &
+		build_target "sparc64" "sparc64-linux-gnu" &
+		wait
+		;;
 	*)
 		show_usage
Index: tools/xstruct.py
===================================================================
--- tools/xstruct.py	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ tools/xstruct.py	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,4 +1,5 @@
 #
 # Copyright (c) 2008 Martin Decky
+# Copyright (c) 2011 Martin Sucha
 # All rights reserved.
 #
@@ -31,4 +32,29 @@
 
 import struct
+import types
+
+ranges = {
+	'B': ((int, long), 0x00, 0xff),
+	'H': ((int, long), 0x0000, 0xffff),
+	'L': ((int, long), 0x00000000, 0xffffffff),
+	'Q': ((int, long), 0x0000000000000000, 0xffffffffffffffff),
+	'b': ((int, long), -0x80, 0x7f),
+	'h': ((int, long), -0x8000, 0x7fff),
+	'l': ((int, long), -0x80000000, 0x7fffffff) ,
+	'q': ((int, long), -0x8000000000000000, 0x7fffffffffffffff),
+}
+
+def check_range(varname, fmt, value):
+	if value == None:
+		raise ValueError('Variable "%s" not set' % varname)
+	if not fmt in ranges:
+		return
+	vartype, varmin, varmax = ranges[fmt]
+	if not isinstance(value, vartype):
+		raise ValueError('Variable "%s" is %s but should be %s' %
+		                 (varname, str(type(value)), str(vartype)))
+	if value < varmin or value > varmax:
+		raise ValueError('Variable "%s" value %s out of range %s..%s' % 
+		                 (varname, repr(value), repr(varmin), repr(varmax)))
 
 class Struct:
@@ -38,12 +64,24 @@
 	def pack(self):
 		args = []
-		for variable in self._args_:
-			if (isinstance(self.__dict__[variable], list)):
-				for item in self.__dict__[variable]:
+		for variable, fmt, length in self._args_:
+			value = self.__dict__[variable]
+			if isinstance(value, list):
+				if length != None and length != len(value):
+					raise ValueError('Variable "%s" length %u does not match %u' %
+				                      (variable, len(value), length))
+				for index, item in enumerate(value):
+					check_range(variable + '[' + repr(index) + ']', fmt, item)
 					args.append(item)
 			else:
-				args.append(self.__dict__[variable])
-		
+				check_range(variable, fmt, value)
+				args.append(value)		
 		return struct.pack(self._format_, *args)
+	
+	def unpack(self, data):
+		values = struct.unpack(self._format_, data)
+		i = 0
+		for variable, fmt, length in self._args_:
+			self.__dict__[variable] = values[i]
+			i += 1
 
 def create(definition):
@@ -77,11 +115,13 @@
 			subtokens = token.split("[")
 			
+			length = None
 			if (len(subtokens) > 1):
-				format += "%d" % int(subtokens[1].split("]")[0])
+				length = int(subtokens[1].split("]")[0])
+				format += "%d" % length
 			
 			format += variable
 			
 			inst.__dict__[subtokens[0]] = None
-			args.append(subtokens[0])
+			args.append((subtokens[0], variable, length))
 			
 			variable = None
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,9 @@
 DIRS = \
 	app/bdsh \
+	app/blkdump \
+	app/bnchmark \
+	app/devctl \
 	app/edit \
+	app/ext2info \
 	app/getterm \
 	app/init \
@@ -41,4 +45,6 @@
 	app/killall \
 	app/klog \
+	app/locinfo \
+	app/lsusb \
 	app/mkfat \
 	app/redir \
@@ -47,7 +53,10 @@
 	app/taskdump \
 	app/tester \
+	app/testread \
 	app/tetris \
 	app/trace \
 	app/top \
+	app/usbinfo \
+	app/vuhid \
 	app/netecho \
 	app/nettest1 \
@@ -56,6 +65,7 @@
 	app/websrv \
 	app/sysinfo \
+	app/mkbd \
 	srv/clip \
-	srv/devmap \
+	srv/loc \
 	srv/devman \
 	srv/loader \
@@ -71,10 +81,10 @@
 	srv/fs/fat \
 	srv/fs/tmpfs \
-	srv/fs/devfs \
-	srv/hid/adb_mouse \
-	srv/hid/char_mouse \
+	srv/fs/locfs \
+	srv/fs/ext2fs \
+	srv/hid/console \
 	srv/hid/s3c24xx_ts \
 	srv/hid/fb \
-	srv/hid/kbd \
+	srv/hid/input \
 	srv/hw/char/i8042 \
 	srv/hw/char/s3c24xx_uart \
@@ -87,8 +97,20 @@
 	srv/net/tl/tcp \
 	srv/net/net \
-	drv/root \
-	drv/rootvirt \
-	drv/test1 \
-	drv/test2
+	drv/infrastructure/root \
+	drv/infrastructure/rootvirt \
+	drv/test/test1 \
+	drv/test/test2 \
+	drv/test/test3 \
+	drv/bus/usb/ehci \
+	drv/bus/usb/ohci \
+	drv/bus/usb/uhci \
+	drv/bus/usb/uhcirh \
+	drv/bus/usb/usbflbk \
+	drv/bus/usb/usbhid \
+	drv/bus/usb/usbhub \
+	drv/bus/usb/usbmast \
+	drv/bus/usb/usbmid \
+	drv/bus/usb/usbmouse \
+	drv/bus/usb/vhc
 
 ## Networking
@@ -102,14 +124,10 @@
 #
 
-ifneq ($(UARCH),abs32le)
-	DIRS += srv/hid/console
-endif
-
 ifeq ($(UARCH),amd64)
 	DIRS += \
-		drv/rootpc \
-		drv/pciintel \
-		drv/isa \
-		drv/ns8250 \
+		drv/infrastructure/rootpc \
+		drv/bus/pci/pciintel \
+		drv/bus/isa \
+		drv/char/ns8250 \
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259
@@ -118,8 +136,8 @@
 ifeq ($(UARCH),ia32)
 	DIRS += \
-		drv/rootpc \
-		drv/pciintel \
-		drv/isa \
-		drv/ns8250 \
+		drv/infrastructure/rootpc \
+		drv/bus/pci/pciintel \
+		drv/bus/isa \
+		drv/char/ns8250 \
 		srv/hw/irc/apic \
 		srv/hw/irc/i8259
@@ -127,10 +145,11 @@
 
 ifeq ($(UARCH),ppc32)
-	DIRS += srv/hw/bus/cuda_adb
+	DIRS += \
+		drv/infrastructure/rootmac \
+		srv/hw/bus/cuda_adb
 endif
 
 ifeq ($(UARCH),sparc64)
 	DIRS += \
-		srv/hw/irc/fhc \
 		srv/hw/irc/obio
 endif
@@ -144,9 +163,17 @@
 	lib/block \
 	lib/clui \
+	lib/scsi \
 	lib/softint \
 	lib/softfloat \
 	lib/drv \
 	lib/packet \
-	lib/net
+	lib/imgmap \
+	lib/net \
+	lib/ext2 \
+	lib/usb \
+	lib/usbhost \
+	lib/usbdev \
+	lib/usbhid \
+	lib/usbvirt
 
 LIBC_BUILD = $(addsuffix .build,$(LIBC))
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/Makefile.common	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,6 +40,17 @@
 #   BINARY         (/) binary output name (like appname)
 #   LIBRARY        (/) library output name (like libname)
+#
 #   EXTRA_OUTPUT       additional output targets
 #   EXTRA_CLEAN        additional cleanup targets
+#
+# Optionally, for a binary:
+#   STATIC_NEEDED      set to 'y' for init binaries, will build statically
+#                      linked version
+#   STATIC_ONLY        set to 'y' if binary cannot be linked dynamically
+#                      (e.g. uses thread-local variables)
+#
+# Optionally, for a libary:
+#   SLIBRARY           Name with full version, e.g. libfoo.so.0.0 
+#   LSONAME            Soname / name with short version, e.g. libfoo.so.0
 #
 # (x) required variables
@@ -73,4 +84,15 @@
 endif
 
+ifeq ($(CONFIG_BUILD_SHARED_LIBS), y)
+	ifneq ($(SLIBRARY),)
+		LARCHIVE = $(LIBRARY).la
+		LOUTPUT = $(SLIBRARY)
+		EXTRA_OUTPUT += $(LOUTPUT).disasm $(LIBRARY).so $(LSONAME)
+		EXTRA_CLEAN += $(LOUTPUT).map $(LOUTPUT).ldisasm \
+		    $(LIBC_PREFIX)/shared/arch/$(UARCH)/_lib.ld \
+		    $(LIBRARY).so $(LSONAME)
+	endif
+endif
+
 DEPEND = Makefile.depend
 DEPEND_PREV = $(DEPEND).prev
@@ -84,5 +106,14 @@
 LIBBLOCK_PREFIX = $(LIB_PREFIX)/block
 LIBFS_PREFIX = $(LIB_PREFIX)/fs
+LIBIMGMAP_PREFIX = $(LIB_PREFIX)/imgmap
 LIBCLUI_PREFIX = $(LIB_PREFIX)/clui
+
+LIBEXT2_PREFIX = $(LIB_PREFIX)/ext2
+
+LIBUSB_PREFIX = $(LIB_PREFIX)/usb
+LIBUSBHOST_PREFIX = $(LIB_PREFIX)/usbhost
+LIBUSBDEV_PREFIX = $(LIB_PREFIX)/usbdev
+LIBUSBHID_PREFIX = $(LIB_PREFIX)/usbhid
+LIBUSBVIRT_PREFIX = $(LIB_PREFIX)/usbvirt
 
 LIBDRV_PREFIX = $(LIB_PREFIX)/drv
@@ -90,7 +121,34 @@
 LIBNET_PREFIX = $(LIB_PREFIX)/net
 
+LIBSCSI_PREFIX = $(LIB_PREFIX)/scsi
+
+ifeq ($(STATIC_NEEDED),y)
+	STATIC_BUILD = y
+else
+	ifeq ($(STATIC_ONLY),y)
+		STATIC_BUILD = y
+	else
+		ifeq ($(CONFIG_USE_SHARED_LIBS), y)
+			STATIC_BUILD = n
+		else
+			STATIC_BUILD = y
+		endif
+	endif
+endif
+
+# Build static whenever we use libusb because that library uses 
+# thread local variables
+ifneq ($(findstring usb, $(LIBS)),)
+	STATIC_BUILD = y
+endif
+
+ifeq ($(STATIC_BUILD), y)
 BASE_LIBS = $(LIBC_PREFIX)/libc.a $(LIBSOFTINT_PREFIX)/libsoftint.a
-
 LINKER_SCRIPT ?= $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld
+else
+BASE_LIBS = $(LIBC_PREFIX)/libc.so0 $(LIBSOFTINT_PREFIX)/libsofti.so0
+LFLAGS = -Bdynamic
+LINKER_SCRIPT ?= $(LIBC_PREFIX)/arch/$(UARCH)/_link-dlexe.ld
+endif
 
 ifeq ($(CONFIG_OPTIMIZE_FOR_SIZE),y)
@@ -102,10 +160,11 @@
 .PHONY: all clean
 
-all: $(VERSION_DEF) $(COMMON_MAKEFILE) $(CONFIG_MAKEFILE) $(CONFIG_HEADER) $(LIBS) $(OUTPUT) $(EXTRA_OUTPUT)
+all: $(VERSION_DEF) $(COMMON_MAKEFILE) $(CONFIG_MAKEFILE) $(CONFIG_HEADER) $(LIBS) $(OUTPUT) $(LOUTPUT) $(EXTRA_OUTPUT)
 	-[ -f $(DEPEND) ] && cp -a $(DEPEND) $(DEPEND_PREV)
 
 clean:
-	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(EXTRA_OUTPUT) $(EXTRA_CLEAN)
+	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(LARCHIVE) $(LOUTPUT) $(EXTRA_OUTPUT) $(EXTRA_CLEAN)
 	find . -name '*.o' -follow -exec rm \{\} \;
+	find . -name '*.lo' -follow -exec rm \{\} \;
 
 GCC_CFLAGS = -I$(LIBC_PREFIX)/include -O$(OPTIMIZATION) -imacros $(CONFIG_HEADER) \
@@ -113,5 +172,5 @@
 	-finput-charset=UTF-8 -ffreestanding -fno-builtin -nostdlib -nostdinc \
 	-Wall -Wextra -Wno-clobbered -Wno-unused-parameter -Wmissing-prototypes \
-	-Werror-implicit-function-declaration -Wwrite-strings \
+	-std=gnu99 -Werror-implicit-function-declaration -Wwrite-strings \
 	-pipe -g -D__$(ENDIANESS)__
 
@@ -130,4 +189,7 @@
 	-pipe -g -arch $(CLANG_ARCH) -D__$(ENDIANESS)__
 
+LIB_CFLAGS = $(CFLAGS) -fPIC -D__IN_SHARED_LIBC__
+LIB_LFLAGS = $(LFLAGS) -shared -soname $(LSONAME) --whole-archive
+
 ifeq ($(CONFIG_DEBUG),y)
 	GCC_CFLAGS += -Werror
@@ -175,4 +237,5 @@
 
 OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
+LOBJECTS := $(addsuffix .lo,$(basename $(SOURCES)))
 
 ifneq ($(BINARY),)
@@ -185,8 +248,26 @@
 
 $(BINARY): $(LINKER_SCRIPT) $(OBJECTS) $(LIBS) $(BASE_LIBS)
-	$(LD) -N $(LFLAGS) -T $(LINKER_SCRIPT) -M -Map $(BINARY).map -o $(BINARY) $(OBJECTS) $(LIBS) $(BASE_LIBS)
+	$(LD) -n $(LFLAGS) -T $(LINKER_SCRIPT) -M -Map $(BINARY).map -o $(BINARY) $(OBJECTS) $(LIBS) $(BASE_LIBS)
 ifeq ($(CONFIG_STRIP_BINARIES),y)
 	$(STRIP) $(BINARY)
 endif
+endif
+
+ifneq ($(SLIBRARY),)
+%.disasm: $(LOUTPUT)
+ifeq ($(CONFIG_LINE_DEBUG),y)
+	$(OBJDUMP) -d -S $< > $@
+else
+	$(OBJDUMP) -d $< > $@
+endif
+
+$(LOUTPUT): $(LARCHIVE) $(LIBC_PREFIX)/arch/$(UARCH)/_link-shlib.ld
+	$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link-shlib.ld $(LIB_LFLAGS) $(LARCHIVE) -o $@ -Map $(LOUTPUT).map
+
+$(LIBRARY).so:
+	ln -s $(SLIBRARY) $@
+
+$(LSONAME):
+	ln -s $(SLIBRARY) $@
 endif
 
@@ -196,4 +277,9 @@
 endif
 
+ifneq ($(SLIBRARY),)
+%.la: $(LOBJECTS)
+	$(AR) rc $@ $(LOBJECTS)
+endif
+
 %.o: %.S $(DEPEND)
 	$(CC) $(DEFS) $(CFLAGS) -D__ASM__ -c $< -o $@
@@ -210,4 +296,22 @@
 %.o: %.c $(DEPEND)
 	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
+ifeq ($(PRECHECK),y)
+	$(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS)
+endif
+
+%.lo: %.S $(DEPEND)
+	$(CC) $(DEFS) $(LIB_CFLAGS) -D__ASM__ -c $< -o $@
+ifeq ($(PRECHECK),y)
+	$(JOBFILE) $(JOB) $< $@ as asm/preproc $(DEFS) $(CFLAGS) -D__ASM__
+endif
+
+%.lo: %.s $(DEPEND)
+	$(AS) $(AFLAGS) -o $@ $<
+ifeq ($(PRECHECK),y)
+	$(JOBFILE) $(JOB) $< $@ as asm
+endif
+
+%.lo: %.c $(DEPEND)
+	$(CC) $(DEFS) $(LIB_CFLAGS) -c $< -o $@
 ifeq ($(PRECHECK),y)
 	$(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS)
@@ -223,2 +327,3 @@
 $(OUTPUT): $(OBJECTS)
 
+$(LARCHIVE): $(LOBJECTS)
Index: uspace/app/bdsh/Makefile
===================================================================
--- uspace/app/bdsh/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -54,9 +54,11 @@
 	cmds/mod_cmds.c \
 	cmds/builtin_cmds.c \
+	compl.c \
 	errors.c \
 	input.c \
 	util.c \
 	exec.c \
-	scli.c
+	scli.c \
+	tok.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/bdsh/cmds/builtin_cmds.c
===================================================================
--- uspace/app/bdsh/cmds/builtin_cmds.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/builtin_cmds.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -38,4 +36,5 @@
 #include "cmds.h"
 #include "builtin_aliases.h"
+#include "scli.h"
 
 extern volatile unsigned int cli_interactive;
@@ -97,17 +96,27 @@
 		cmd->help(extended);
 		return CL_EOK;
-	} else
+	} else {
 		return CL_ENOENT;
+	}
 }
 
-int run_builtin(int builtin, char *argv[], cliuser_t *usr)
+int run_builtin(int builtin, char *argv[], cliuser_t *usr, iostate_t *new_iostate)
 {
+	int rc;
 	builtin_t *cmd = builtins;
 
 	cmd += builtin;
+	
+	iostate_t *old_iostate = get_iostate();
+	set_iostate(new_iostate);
+	
+	if (NULL != cmd->entry) {
+		rc = ((int)cmd->entry(argv, usr));
+	} else {
+		rc = CL_ENOENT;
+	}
+	
+	set_iostate(old_iostate);
 
-	if (NULL != cmd->entry)
-		return((int)cmd->entry(argv, usr));
-
-	return CL_ENOENT;
+	return rc;
 }
Index: uspace/app/bdsh/cmds/builtins/cd/cd.c
===================================================================
--- uspace/app/bdsh/cmds/builtins/cd/cd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/builtins/cd/cd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
Index: uspace/app/bdsh/cmds/builtins/exit/exit.c
===================================================================
--- uspace/app/bdsh/cmds/builtins/exit/exit.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/builtins/exit/exit.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
Index: uspace/app/bdsh/cmds/cmds.h
===================================================================
--- uspace/app/bdsh/cmds/cmds.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/cmds.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef CMDS_H
 #define CMDS_H
@@ -59,5 +87,5 @@
 extern char *alias_for_module(const char *);
 extern int help_module(int, unsigned int);
-extern int run_module(int, char *[]);
+extern int run_module(int, char *[], iostate_t *);
 
 /* Prototypes for builtin launchers */
@@ -67,5 +95,5 @@
 extern char *alias_for_builtin(const char *);
 extern int help_builtin(int, unsigned int);
-extern int run_builtin(int, char *[], cliuser_t *);
+extern int run_builtin(int, char *[], cliuser_t *, iostate_t *);
 
 #endif
Index: uspace/app/bdsh/cmds/mod_cmds.c
===================================================================
--- uspace/app/bdsh/cmds/mod_cmds.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/mod_cmds.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -118,19 +116,29 @@
 		mod->help(extended);
 		return CL_EOK;
-	} else
+	} else {
 		return CL_ENOENT;
+	}
 }
 
 /* Invokes the module entry point modules[module], passing argv[] as an argument
  * stack. */
-int run_module(int module, char *argv[])
+int run_module(int module, char *argv[], iostate_t *new_iostate)
 {
+	int rc;
 	module_t *mod = modules;
 
 	mod += module;
+	
+	iostate_t *old_iostate = get_iostate();
+	set_iostate(new_iostate);
 
-	if (NULL != mod->entry)
-		return ((int)mod->entry(argv));
+	if (NULL != mod->entry) {
+		rc = ((int)mod->entry(argv));
+	} else {
+		rc = CL_ENOENT;
+	}
+	
+	set_iostate(old_iostate);
 
-	return CL_ENOENT;
+	return rc;
 }
Index: uspace/app/bdsh/cmds/modules/bdd/bdd.c
===================================================================
--- uspace/app/bdsh/cmds/modules/bdd/bdd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/bdd/bdd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,5 @@
 
 #include <libblock.h>
-#include <devmap.h>
+#include <loc.h>
 #include <errno.h>
 #include <assert.h>
@@ -69,5 +69,5 @@
 	unsigned int argc;
 	unsigned int i, j;
-	devmap_handle_t handle;
+	service_id_t service_id;
 	aoff64_t offset;
 	uint8_t *blk;
@@ -96,5 +96,5 @@
 		size = 256;
 
-	rc = devmap_device_get_handle(argv[1], &handle, 0);
+	rc = loc_service_get_id(argv[1], &service_id, 0);
 	if (rc != EOK) {
 		printf("%s: Error resolving device `%s'.\n", cmdname, argv[1]);
@@ -102,5 +102,5 @@
 	}
 
-	rc = block_init(handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
 	if (rc != EOK)  {
 		printf("%s: Error initializing libblock.\n", cmdname);
@@ -108,5 +108,5 @@
 	}
 
-	rc = block_get_bsize(handle, &block_size);
+	rc = block_get_bsize(service_id, &block_size);
 	if (rc != EOK) {
 		printf("%s: Error determining device block size.\n", cmdname);
@@ -117,5 +117,5 @@
 	if (blk == NULL) {
 		printf("%s: Error allocating memory.\n", cmdname);
-		block_fini(handle);
+		block_fini(service_id);
 		return CMD_FAILURE;
 	}
@@ -124,9 +124,9 @@
 
 	while (size > 0) {
-		rc = block_read_direct(handle, ba, 1, blk);
+		rc = block_read_direct(service_id, ba, 1, blk);
 		if (rc != EOK) {
 			printf("%s: Error reading block %" PRIuOFF64 "\n", cmdname, ba);
 			free(blk);
-			block_fini(handle);
+			block_fini(service_id);
 			return CMD_FAILURE;
 		}
@@ -170,5 +170,5 @@
 
 	free(blk);
-	block_fini(handle);
+	block_fini(service_id);
 
 	return CMD_SUCCESS;
Index: uspace/app/bdsh/cmds/modules/cat/cat.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/cat/cat.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,29 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
+ * Copyright (c) 2011, Martin Sucha
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -35,4 +34,11 @@
 #include <str.h>
 #include <fcntl.h>
+#include <io/console.h>
+#include <io/color.h>
+#include <io/style.h>
+#include <io/keycode.h>
+#include <errno.h>
+#include <vfs/vfs.h>
+#include <assert.h>
 
 #include "config.h"
@@ -48,4 +54,14 @@
 
 static const char *cat_oops = "That option is not yet supported\n";
+static const char *hexchars = "0123456789abcdef";
+
+static bool paging_enabled = false;
+static size_t chars_remaining = 0;
+static size_t lines_remaining = 0;
+static sysarg_t console_cols = 0;
+static sysarg_t console_rows = 0;
+static bool should_quit = false;
+
+static console_ctrl_t *console = NULL;
 
 static struct option const long_options[] = {
@@ -56,4 +72,5 @@
 	{ "buffer", required_argument, 0, 'b' },
 	{ "more", no_argument, 0, 'm' },
+	{ "hex", no_argument, 0, 'x' },
 	{ 0, 0, 0, 0 }
 };
@@ -75,4 +92,5 @@
 		"  -b, --buffer ##  Set the read buffer size to ##\n"
 		"  -m, --more       Pause after each screen full\n"
+		"  -x, --hex        Print bytes as hex values\n"
 		"Currently, %s is under development, some options don't work.\n",
 		cmdname, cmdname);
@@ -82,9 +100,73 @@
 }
 
-static unsigned int cat_file(const char *fname, size_t blen)
+static void waitprompt()
+{
+	console_set_pos(console, 0, console_rows-1);
+	console_set_color(console, COLOR_BLUE, COLOR_WHITE, 0);
+	
+	printf("ENTER/SPACE/PAGE DOWN - next page, "
+	       "ESC/Q - quit, C - continue unpaged");
+	fflush(stdout);
+	
+	console_set_style(console, STYLE_NORMAL);
+}
+
+static void waitkey()
+{
+	kbd_event_t ev;
+	
+	while (true) {
+		if (!console_get_kbd_event(console, &ev)) {
+			return;
+		}
+		if (ev.type == KEY_PRESS) {
+			if (ev.key == KC_ESCAPE || ev.key == KC_Q) {
+				should_quit = true;
+				return;
+			}
+			if (ev.key == KC_C) {
+				paging_enabled = false;
+				return;
+			}
+			if (ev.key == KC_ENTER || ev.key == KC_SPACE ||
+			    ev.key == KC_PAGE_DOWN) {
+				return;
+			}
+		}
+	}
+	assert(false);
+}
+
+static void newpage()
+{
+	console_clear(console);
+	chars_remaining = console_cols;
+	lines_remaining = console_rows - 1;
+}
+
+static void paged_char(wchar_t c)
+{
+	putchar(c);
+	if (paging_enabled) {
+		chars_remaining--;
+		if (c == '\n' || chars_remaining == 0) {
+			chars_remaining = console_cols;
+			lines_remaining--;
+		}
+		if (lines_remaining == 0) {
+			fflush(stdout);
+			waitprompt();
+			waitkey();
+			newpage();
+		}
+	}
+}
+
+static unsigned int cat_file(const char *fname, size_t blen, bool hex)
 {
 	int fd, bytes = 0, count = 0, reads = 0;
-	off64_t total = 0;
 	char *buff = NULL;
+	int i;
+	size_t offset = 0;
 
 	fd = open(fname, O_RDONLY);
@@ -93,7 +175,4 @@
 		return 1;
 	}
-
-	total = lseek(fd, 0, SEEK_END);
-	lseek(fd, 0, SEEK_SET);
 
 	if (NULL == (buff = (char *) malloc(blen + 1))) {
@@ -109,8 +188,23 @@
 			count += bytes;
 			buff[bytes] = '\0';
-			printf("%s", buff);
+			offset = 0;
+			for (i = 0; i < bytes && !should_quit; i++) {
+				if (hex) {
+					paged_char(hexchars[((uint8_t)buff[i])/16]);
+					paged_char(hexchars[((uint8_t)buff[i])%16]);
+				}
+				else {
+					wchar_t c = str_decode(buff, &offset, bytes);
+					if (c == 0) {
+						/* Reached end of string */
+						break;
+					}
+					paged_char(c);
+				}
+				
+			}
 			reads++;
 		}
-	} while (bytes > 0);
+	} while (bytes > 0 && !should_quit);
 
 	close(fd);
@@ -131,9 +225,25 @@
 	unsigned int argc, i, ret = 0, buffer = 0;
 	int c, opt_ind;
+	bool hex = false;
+	bool more = false;
+	sysarg_t rows, cols;
+	int rc;
+	
+	/*
+	 * reset global state
+	 * TODO: move to structure?
+	 */
+	paging_enabled = false;
+	chars_remaining = 0;
+	lines_remaining = 0;
+	console_cols = 0;
+	console_rows = 0;
+	should_quit = false;
+	console = console_init(stdin, stdout);
 
 	argc = cli_count_args(argv);
 
 	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
-		c = getopt_long(argc, argv, "hvmH:t:b:", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "xhvmH:t:b:", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
@@ -153,6 +263,9 @@
 			break;
 		case 'm':
-			printf("%s", cat_oops);
-			return CMD_FAILURE;
+			more = true;
+			break;
+		case 'x':
+			hex = true;
+			break;
 		}
 	}
@@ -168,7 +281,19 @@
 	if (buffer <= 0)
 		buffer = CAT_DEFAULT_BUFLEN;
-
-	for (i = optind; argv[i] != NULL; i++)
-		ret += cat_file(argv[i], buffer);
+	
+	if (more) {
+		rc = console_get_size(console, &cols, &rows);
+		if (rc != EOK) {
+			printf("%s - cannot get console size\n", cmdname);
+			return CMD_FAILURE;
+		}
+		console_cols = cols;
+		console_rows = rows;
+		paging_enabled = true;
+		newpage();
+	}
+
+	for (i = optind; argv[i] != NULL && !should_quit; i++)
+		ret += cat_file(argv[i], buffer, hex);
 
 	if (ret)
Index: uspace/app/bdsh/cmds/modules/cat/cat.h
===================================================================
--- uspace/app/bdsh/cmds/modules/cat/cat.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/cat/cat.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -4,5 +4,5 @@
 /* Prototypes for the cat command, excluding entry points */
 
-static unsigned int cat_file(const char *, size_t);
+static unsigned int cat_file(const char *, size_t, bool);
 
 #endif /* CAT_H */
Index: uspace/app/bdsh/cmds/modules/cp/cp.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cp/cp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/cp/cp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -73,6 +71,6 @@
 	size_t blen, int vb)
 {
-	int fd1, fd2, bytes = 0;
-	off64_t total = 0;
+	int fd1, fd2, bytes;
+	off64_t total;
 	int64_t copied = 0;
 	char *buff = NULL;
@@ -106,35 +104,11 @@
 	}
 
-	for (;;) {
-		ssize_t res;
-
-		bytes = read(fd1, buff, blen);
-		if (bytes <= 0)
+	while ((bytes = read_all(fd1, buff, blen)) > 0) {
+		if ((bytes = write_all(fd2, buff, bytes)) < 0)
 			break;
 		copied += bytes;
-		res = bytes;
-		do {
-			/*
-			 * Theoretically, it may not be enough to call write()
-			 * only once. Also the previous read() may have
-			 * returned less data than requested.
-			 */
-			bytes = write(fd2, buff, res);
-			if (bytes < 0)
-				goto err;
-			res -= bytes;
-		} while (res > 0);
-
-		/* TODO: re-insert assert() once this is stand alone,
-		 * removed as abort() exits the entire shell
-		 */
-		if (res != 0) {
-			printf("\n%zd more bytes than actually exist were copied\n", res);
-			goto err;
-		}
 	}
 
 	if (bytes < 0) {
-err:
 		printf("\nError copying %s, (%d)\n", src, bytes);
 		copied = bytes;
Index: uspace/app/bdsh/cmds/modules/help/help.c
===================================================================
--- uspace/app/bdsh/cmds/modules/help/help.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/help/help.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
Index: uspace/app/bdsh/cmds/modules/kcon/kcon.c
===================================================================
--- uspace/app/bdsh/cmds/modules/kcon/kcon.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/kcon/kcon.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -32,5 +30,4 @@
 #include <stdlib.h>
 #include <io/console.h>
-#include <vfs/vfs.h>
 #include "config.h"
 #include "util.h"
@@ -42,13 +39,12 @@
 static const char *cmdname = "kcon";
 
-/* Dispays help for kcon in various levels */
+/* Display help for kcon in various levels */
 void help_cmd_kcon(unsigned int level)
 {
 	printf("`kcon' switches to the kernel debug console.\n");
-
-	if (level != HELP_SHORT) {
-		printf("Usage:  %s\n", cmdname);
-	}
-
+	
+	if (level != HELP_SHORT)
+		printf("Usage: %s\n", cmdname);
+	
 	return;
 }
@@ -57,17 +53,15 @@
 int cmd_kcon(char **argv)
 {
-	unsigned int argc;
-
-	argc = cli_count_args(argv);
-
+	unsigned int argc = cli_count_args(argv);
+	
 	if (argc != 1) {
 		printf("%s - incorrect number of arguments. Try `%s --help'\n",
-			cmdname, cmdname);
+		    cmdname, cmdname);
 		return CMD_FAILURE;
 	}
-
-	console_kcon_enable(fphone(stdout));
-
-	return CMD_SUCCESS;
+	
+	if (console_kcon())
+		return CMD_SUCCESS;
+	else
+		return CMD_FAILURE;
 }
-
Index: uspace/app/bdsh/cmds/modules/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * 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.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -38,7 +36,9 @@
 #include <dirent.h>
 #include <fcntl.h>
+#include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <str.h>
+#include <sort.h>
 
 #include "errors.h"
@@ -46,64 +46,160 @@
 #include "util.h"
 #include "entry.h"
-#include "ls.h"
 #include "cmds.h"
 
+/* Various values that can be returned by ls_scope() */
+#define LS_BOGUS 0
+#define LS_FILE  1
+#define LS_DIR   2
+
+/** Structure to represent a directory entry.
+ *
+ * Useful to keep together important information
+ * for sorting directory entries.
+ */
+struct dir_elem_t {
+	char *name;
+	struct stat s;
+};
+
 static const char *cmdname = "ls";
 
-static void ls_scan_dir(const char *d, DIR *dirp)
-{
+static struct option const long_options[] = {
+	{ "help", no_argument, 0, 'h' },
+	{ "unsort", no_argument, 0, 'u' },
+	{ 0, 0, 0, 0 }
+};
+
+/** Print an entry.
+ *
+ * ls_print currently does nothing more than print the entry.
+ * In the future, we will likely pass the absolute path, and
+ * some sort of ls_options structure that controls how each
+ * entry is printed and what is printed about it.
+ *
+ * Now we just print basic DOS style lists.
+ *
+ * @param de		Directory element.
+ */
+static void ls_print(struct dir_elem_t *de)
+{
+	if (de->s.is_file)
+		printf("%-40s\t%llu\n", de->name, (long long) de->s.size);
+	else if (de->s.is_directory)
+		printf("%-40s\t<dir>\n", de->name);
+	else
+		printf("%-40s\n", de->name);
+}
+
+
+/** Compare 2 directory elements.
+ *
+ * It compares 2 elements of a directory : a file is considered
+ * as bigger than a directory, and if they have the same type,
+ * they are compared alphabetically.
+ *
+ * @param a		Pointer to the structure of the first element.
+ * @param b		Pointer to the structure of the second element.
+ * @param arg		Pointer for an other and optionnal argument.
+ *
+ * @return		-1 if a < b, 1 otherwise.
+ */
+static int ls_cmp(void *a, void *b, void *arg)
+{
+	struct dir_elem_t *da = a;
+	struct dir_elem_t *db = b;
+	
+	if ((da->s.is_directory && db->s.is_file) ||
+	    ((da->s.is_directory == db->s.is_directory) &&
+	    str_cmp(da->name, db->name) < 0))
+		return -1;
+	else
+		return 1;
+}
+
+/** Scan a directory.
+ *
+ * Scan the content of a directory and print it.
+ *
+ * @param d		Name of the directory.
+ * @param dirp	Directory stream.
+ * @param sort	1 if the output must be sorted,
+ *				0 otherwise.
+ */
+static void ls_scan_dir(const char *d, DIR *dirp, int sort)
+{
+	int alloc_blocks = 20;
+	int i;
+	int nbdirs = 0;
+	int rc;
+	int len;
+	char *buff;
+	struct dir_elem_t *tmp;
+	struct dir_elem_t *tosort;
 	struct dirent *dp;
-	char *buff;
-
-	if (! dirp)
+	
+	if (!dirp)
 		return;
 
-	buff = (char *)malloc(PATH_MAX);
-	if (NULL == buff) {
+	buff = (char *) malloc(PATH_MAX);
+	if (!buff) {
 		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
 		return;
 	}
-
+	
+	tosort = (struct dir_elem_t *) malloc(alloc_blocks * sizeof(*tosort));
+	if (!tosort) {
+		cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+		free(buff);
+		return;
+	}
+	
 	while ((dp = readdir(dirp))) {
-		memset(buff, 0, sizeof(buff));
-		/* Don't worry if inserting a double slash, this will be fixed by
-		 * absolutize() later with subsequent calls to open() or readdir() */
-		snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name);
-		ls_print(dp->d_name, buff);
-	}
-
+		if (nbdirs + 1 > alloc_blocks) {
+			alloc_blocks += alloc_blocks;
+			
+			tmp = (struct dir_elem_t *) realloc(tosort,
+			    alloc_blocks * sizeof(struct dir_elem_t));
+			if (!tmp) {
+				cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+				goto out;
+			}
+			tosort = tmp;
+		}
+		
+		/* fill the name field */
+		tosort[nbdirs].name = (char *) malloc(str_size(dp->d_name) + 1);
+		if (!tosort[nbdirs].name) {
+			cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
+			goto out;
+		}
+
+		str_cpy(tosort[nbdirs].name, str_size(dp->d_name) + 1, dp->d_name);
+		len = snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[nbdirs].name);
+		buff[len] = '\0';
+
+		rc = stat(buff, &tosort[nbdirs++].s);
+		if (rc != 0) {
+			printf("ls: skipping bogus node %s\n", buff);
+			printf("rc=%d\n", rc);
+			goto out;
+		}
+	}
+	
+	if (sort) {
+		if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t),
+		    ls_cmp, NULL)) {
+			printf("Sorting error.\n");
+		}
+	}
+	
+	for (i = 0; i < nbdirs; i++)
+		ls_print(&tosort[i]);
+	
+out:
+	for(i = 0; i < nbdirs; i++)
+		free(tosort[i].name);
+	free(tosort);
 	free(buff);
-
-	return;
-}
-
-/* ls_print currently does nothing more than print the entry.
- * in the future, we will likely pass the absolute path, and
- * some sort of ls_options structure that controls how each
- * entry is printed and what is printed about it.
- *
- * Now we just print basic DOS style lists */
-
-static void ls_print(const char *name, const char *pathname)
-{
-	struct stat s;
-	int rc;
-
-	rc = stat(pathname, &s);
-	if (rc != 0) {
-		/* Odd chance it was deleted from the time readdir() found it */
-		printf("ls: skipping bogus node %s\n", pathname);
-		printf("rc=%d\n", rc);
-		return;
-	}
-	
-	if (s.is_file)
-		printf("%-40s\t%llu\n", name, (long long) s.size);
-	else if (s.is_directory)
-		printf("%-40s\t<dir>\n", name);
-	else
-		printf("%-40s\n", name);
-
-	return;
 }
 
@@ -114,6 +210,11 @@
 	} else {
 		help_cmd_ls(HELP_SHORT);
-		printf("  `%s' [path], if no path is given the current "
-				"working directory is used.\n", cmdname);
+		printf(
+		"Usage:  %s [options] [path]\n"
+		"If not path is given, the current working directory is used.\n"
+		"Options:\n"
+		"  -h, --help       A short option summary\n"
+		"  -u, --unsort     Do not sort directory entries\n",
+		cmdname);
 	}
 
@@ -124,43 +225,58 @@
 {
 	unsigned int argc;
-	struct stat s;
-	char *buff;
+	struct dir_elem_t de;
 	DIR *dirp;
+	int c, opt_ind;
+	int sort = 1;
 
 	argc = cli_count_args(argv);
-
-	buff = (char *) malloc(PATH_MAX);
-	if (NULL == buff) {
+	
+	for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
+		c = getopt_long(argc, argv, "hu", long_options, &opt_ind);
+		switch (c) {
+		case 'h':
+			help_cmd_ls(HELP_LONG);
+			return CMD_SUCCESS;
+		case 'u':
+			sort = 0;
+			break;
+		}
+	}
+	
+	argc -= optind;
+	
+	de.name = (char *) malloc(PATH_MAX);
+	if (!de.name) {
 		cli_error(CL_ENOMEM, "%s: ", cmdname);
 		return CMD_FAILURE;
 	}
-	memset(buff, 0, sizeof(buff));
-
-	if (argc == 1)
-		getcwd(buff, PATH_MAX);
+	memset(de.name, 0, sizeof(PATH_MAX));
+	
+	if (argc == 0)
+		getcwd(de.name, PATH_MAX);
 	else
-		str_cpy(buff, PATH_MAX, argv[1]);
-
-	if (stat(buff, &s)) {
-		cli_error(CL_ENOENT, buff);
-		free(buff);
+		str_cpy(de.name, PATH_MAX, argv[optind]);
+	
+	if (stat(de.name, &de.s)) {
+		cli_error(CL_ENOENT, de.name);
+		free(de.name);
 		return CMD_FAILURE;
 	}
 
-	if (s.is_file) {
-		ls_print(buff, buff);
+	if (de.s.is_file) {
+		ls_print(&de);
 	} else {
-		dirp = opendir(buff);
+		dirp = opendir(de.name);
 		if (!dirp) {
 			/* May have been deleted between scoping it and opening it */
-			cli_error(CL_EFAIL, "Could not stat %s", buff);
-			free(buff);
+			cli_error(CL_EFAIL, "Could not stat %s", de.name);
+			free(de.name);
 			return CMD_FAILURE;
 		}
-		ls_scan_dir(buff, dirp);
+		ls_scan_dir(de.name, dirp, sort);
 		closedir(dirp);
 	}
 
-	free(buff);
+	free(de.name);
 
 	return CMD_SUCCESS;
Index: pace/app/bdsh/cmds/modules/ls/ls.h
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,13 +1,0 @@
-#ifndef LS_H
-#define LS_H
-
-/* Various values that can be returned by ls_scope() */
-#define LS_BOGUS 0
-#define LS_FILE  1
-#define LS_DIR   2
-
-static void ls_scan_dir(const char *, DIR *);
-static void ls_print(const char *, const char *);
-
-#endif /* LS_H */
-
Index: uspace/app/bdsh/cmds/modules/mkdir/mkdir.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mkdir/mkdir.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/mkdir/mkdir.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,32 +1,29 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 
 #include <stdio.h>
Index: uspace/app/bdsh/cmds/modules/mkfile/mkfile.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mkfile/mkfile.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/mkfile/mkfile.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -26,5 +26,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 
 #include <stdio.h>
Index: uspace/app/bdsh/cmds/modules/module_aliases.h
===================================================================
--- uspace/app/bdsh/cmds/modules/module_aliases.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/module_aliases.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef MODULE_ALIASES_H
 #define MODULE_ALIASES_H
Index: uspace/app/bdsh/cmds/modules/modules.h
===================================================================
--- uspace/app/bdsh/cmds/modules/modules.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/modules.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef MODULES_H
 #define MODULES_H
Index: uspace/app/bdsh/cmds/modules/mount/mount.c
===================================================================
--- uspace/app/bdsh/cmds/modules/mount/mount.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/mount/mount.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -51,5 +51,5 @@
 {
 	static char helpfmt[] =
-	    "Usage:  %s <fstype> <mp> <dev> [<moptions>]\n";
+	    "Usage:  %s <fstype> <mp> [dev] [<moptions>]\n";
 	if (level == HELP_SHORT) {
 		printf("'%s' mounts a file system.\n", cmdname);
@@ -66,4 +66,5 @@
 	unsigned int argc;
 	const char *mopts = "";
+	const char *dev = "";
 	int rc, c, opt_ind;
 
@@ -79,13 +80,15 @@
 	}
 
-	if ((argc < 4) || (argc > 5)) {
+	if ((argc < 3) || (argc > 5)) {
 		printf("%s: invalid number of arguments. Try `mount --help'\n",
 		    cmdname);
 		return CMD_FAILURE;
 	}
+	if (argc > 3)
+		dev = argv[3];
 	if (argc == 5)
 		mopts = argv[4];
 
-	rc = mount(argv[1], argv[2], argv[3], mopts, 0);
+	rc = mount(argv[1], argv[2], dev, mopts, 0);
 	if (rc != EOK) {
 		printf("Unable to mount %s filesystem to %s on %s (rc=%d)\n",
Index: uspace/app/bdsh/cmds/modules/pwd/pwd.c
===================================================================
--- uspace/app/bdsh/cmds/modules/pwd/pwd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/pwd/pwd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
Index: uspace/app/bdsh/cmds/modules/rm/rm.c
===================================================================
--- uspace/app/bdsh/cmds/modules/rm/rm.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/rm/rm.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -101,7 +99,42 @@
 }
 
+static unsigned int rm_recursive_not_empty_dirs(const char *path)
+{
+	DIR *dirp;
+	struct dirent *dp;
+	char buff[PATH_MAX];
+	unsigned int scope;
+	unsigned int ret = 0;
+
+	dirp = opendir(path);
+	if (!dirp) {
+		/* May have been deleted between scoping it and opening it */
+		cli_error(CL_EFAIL, "Could not open %s", path);
+		return ret;
+	}
+
+	memset(buff, 0, sizeof(buff));
+	while ((dp = readdir(dirp))) {
+		snprintf(buff, PATH_MAX - 1, "%s/%s", path, dp->d_name);
+		scope = rm_scope(buff);
+		switch (scope) {
+		case RM_BOGUS:
+			break;
+		case RM_FILE:
+			ret += rm_single(buff);
+			break;
+		case RM_DIR:
+			ret += rm_recursive(buff);
+			break;
+		}
+	}
+	
+	return ret;
+}
+
 static unsigned int rm_recursive(const char *path)
 {
 	int rc;
+	unsigned int ret = 0;
 
 	/* First see if it will just go away */
@@ -111,7 +144,14 @@
 
 	/* Its not empty, recursively scan it */
-	cli_error(CL_ENOTSUP,
-		"Can not remove %s, directory not empty", path);
-	return 1;
+	ret = rm_recursive_not_empty_dirs(path);
+
+	/* Delete directory */
+	rc = rmdir(path);
+	if (rc == 0)
+		return ret;
+
+	cli_error(CL_ENOTSUP, "Can not remove %s", path);
+
+	return ret + 1;
 }
 
Index: uspace/app/bdsh/cmds/modules/sleep/sleep.c
===================================================================
--- uspace/app/bdsh/cmds/modules/sleep/sleep.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/sleep/sleep.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
Index: uspace/app/bdsh/cmds/modules/touch/touch.c
===================================================================
--- uspace/app/bdsh/cmds/modules/touch/touch.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/cmds/modules/touch/touch.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
Index: uspace/app/bdsh/compl.c
===================================================================
--- uspace/app/bdsh/compl.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/bdsh/compl.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2011 Martin Sucha
+ * 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 <bool.h>
+#include <dirent.h>
+#include <errno.h>
+#include <macros.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "cmds/cmds.h"
+#include "compl.h"
+#include "exec.h"
+#include "tok.h"
+
+static int compl_init(wchar_t *text, size_t pos, size_t *cstart, void **state);
+static int compl_get_next(void *state, char **compl);
+static void compl_fini(void *state);
+
+/** Bdsh implementation of completion ops. */
+tinput_compl_ops_t compl_ops = {
+	.init = compl_init,
+	.get_next = compl_get_next,
+	.fini = compl_fini
+};
+
+/** Completion state object.
+ *
+ * The state object contains 'iterators' for modules, builtins and
+ * executables in directories.
+ */
+typedef struct {
+	/** String prefix which we are trying to complete. */
+	char *prefix;
+	/** Length of string prefix (number of characters) */
+	size_t prefix_len;
+
+	/** Pointer inside list of modules */
+	module_t *module;
+	/** Pointer inside list of builtins */
+	builtin_t *builtin;
+
+	/** Pointer inside list of directories */
+	const char **path;
+	/** If not @c NULL, should be freed in the end. */
+	const char **path_list;
+	/** Current open directory */
+	DIR *dir;
+
+	char *last_compl;
+
+	/**
+	 * @c true if we are completing a command, @c false if we are
+	 * completing an argument
+	 */
+	bool is_command;
+} compl_t;
+
+/** Init completion.
+ *
+ * Set up iterators in completion object, based on current token.
+ */
+static int compl_init(wchar_t *text, size_t pos, size_t *cstart, void **state)
+{
+	compl_t *cs = NULL;
+	size_t pref_size;
+	char *stext = NULL;
+	char *prefix = NULL;
+	char *dirname = NULL;
+	char *rpath_sep;
+	static const char *dirlist_arg[] = { ".", NULL };
+	int retval;
+	tokenizer_t tok;
+	token_t tokens[WORD_MAX];
+	unsigned int current_token;
+	size_t tokens_length;
+
+	cs = calloc(1, sizeof(compl_t));
+	if (!cs) {
+		retval = ENOMEM;
+		goto error;
+	}
+
+	/* Convert text buffer to string */
+	stext = wstr_to_astr(text);
+	if (stext == NULL) {
+		retval = ENOMEM;
+		goto error;
+	}
+	
+	/* Tokenize the input string */
+	retval = tok_init(&tok, stext, tokens, WORD_MAX);
+	if (retval != EOK) {
+		goto error;
+	}
+	
+	retval = tok_tokenize(&tok, &tokens_length);
+	if (retval != EOK) {
+		goto error;
+	}
+	
+	/* Find the current token */
+	for (current_token = 0; current_token < tokens_length; current_token++) {
+		token_t *t = &tokens[current_token];
+		size_t end = t->char_start + t->char_length;
+		/* Check if the caret lies inside the token or immediately
+		 * after it
+		 */
+		if (t->char_start <= pos && pos <= end) {
+			break;
+		}
+	}
+	
+	if (tokens[current_token].type != TOKTYPE_SPACE) {
+		*cstart = tokens[current_token].char_start;
+	}
+	else {
+		*cstart = pos;
+	}
+	
+	/* Extract the prefix being completed
+	 * XXX: handle strings, etc.
+	 */
+	pref_size = str_lsize(stext, pos - *cstart);
+	prefix = malloc(pref_size + 1);
+	if (prefix == NULL) {
+		retval = ENOMEM;
+		goto error;
+	}
+
+	str_ncpy(prefix, pref_size + 1, stext +
+	    tokens[current_token].byte_start, pref_size);
+
+	/*
+	 * Determine if the token being completed is a command or argument.
+	 * We look at the previous token. If there is none or it is a pipe
+	 * ('|'), it is a command, otherwise it is an argument.
+	 */
+
+	/* Skip any whitespace before current token */
+	int prev_token = current_token - 1;
+	if (prev_token != -1 && tokens[prev_token].type == TOKTYPE_SPACE) {
+		prev_token--;
+	}
+
+	/*
+	 * It is a command if it is the first token or if it immediately
+	 * follows a pipe token.
+	 */
+	if (prev_token == -1 || tokens[prev_token].type == TOKTYPE_SPACE)
+		cs->is_command = true;
+	else
+		cs->is_command = false;
+
+	rpath_sep = str_rchr(prefix, '/');
+	if (rpath_sep != NULL) {
+		/* Extract path. For path beginning with '/' keep the '/'. */
+		dirname = str_ndup(prefix, max(1, rpath_sep - prefix));
+		if (dirname == NULL) {
+			retval = ENOMEM;
+			goto error;
+		}
+
+		/* Extract name prefix */
+		cs->prefix = str_dup(rpath_sep + 1);
+		if (cs->prefix == NULL) {
+			retval = ENOMEM;
+			goto error;
+		}
+		*cstart += rpath_sep + 1 - prefix;
+		free(prefix);
+
+		cs->path_list = malloc(sizeof(char *) * 2);
+		if (cs->path_list == NULL) {
+			retval = ENOMEM;
+			goto error;
+		}
+		cs->path_list[0] = dirname;
+		cs->path_list[1] = NULL;
+		cs->path = cs->path_list;
+
+	} else if (cs->is_command) {
+		/* Command without path */
+		cs->module = modules;
+		cs->builtin = builtins;
+		cs->prefix = prefix;
+		cs->path = &search_dir[0];
+	} else {
+		/* Argument without path */
+		cs->prefix = prefix;
+		cs->path = &dirlist_arg[0];
+	}
+
+	cs->prefix_len = str_length(cs->prefix);
+	
+	tok_fini(&tok);
+
+	*state = cs;
+	return EOK;
+
+error:
+	/* Error cleanup */
+	
+	tok_fini(&tok);
+
+	if (cs != NULL && cs->path_list != NULL) {
+		size_t i = 0;
+		while (cs->path_list[i] != NULL) {
+			free(cs->path_list[i]);
+			++i;
+		}
+		free(cs->path_list);
+	}
+
+	if (cs != NULL && cs->prefix != NULL)
+		free(cs->prefix);
+	if (dirname != NULL)
+		free(dirname);
+	if (prefix != NULL)
+		free(prefix);
+	if (stext != NULL)
+		free(stext);
+	if (cs != NULL)
+		free(cs);
+
+	return retval;
+}
+
+/** Determine if completion matches the required prefix.
+ *
+ * Required prefix is stored in @a cs->prefix.
+ *
+ * @param cs	Completion state object
+ * @param compl	Completion string
+ * @return	@c true when @a compl matches, @c false otherwise
+ */
+static bool compl_match_prefix(compl_t *cs, const char *compl)
+{
+	return str_lcmp(compl, cs->prefix, cs->prefix_len) == 0;
+}
+
+/** Get next match. */
+static int compl_get_next(void *state, char **compl)
+{
+	compl_t *cs = (compl_t *) state;
+	struct dirent *dent;
+
+	*compl = NULL;
+
+	if (cs->last_compl != NULL) {
+		free(cs->last_compl);
+		cs->last_compl = NULL;
+	}
+
+	/* Modules */
+	if (cs->module != NULL) {
+		while (*compl == NULL && cs->module->name != NULL) {
+			if (compl_match_prefix(cs, cs->module->name)) {
+				asprintf(compl, "%s ", cs->module->name);
+				cs->last_compl = *compl;
+				if (*compl == NULL)
+					return ENOMEM;
+			}
+			cs->module++;
+		}
+	}
+
+	/* Builtins */
+	if (cs->builtin != NULL) {
+		while (*compl == NULL && cs->builtin->name != NULL) {
+			if (compl_match_prefix(cs, cs->builtin->name)) {
+				asprintf(compl, "%s ", cs->builtin->name);
+				cs->last_compl = *compl;
+				if (*compl == NULL)
+					return ENOMEM;
+			}
+			cs->builtin++;
+		}
+	}
+
+	/* Files and directories. We scan entries from a set of directories. */
+	if (cs->path != NULL) {
+		while (*compl == NULL) {
+			/* Open next directory */
+			while (cs->dir == NULL) {
+				if (*cs->path == NULL)
+					break;
+
+				cs->dir = opendir(*cs->path);
+
+				/* Skip directories that we fail to open. */
+				if (cs->dir == NULL)
+					cs->path++;
+			}
+
+			/* If it was the last one, we are done */
+			if (cs->dir == NULL)
+				break;
+
+			/* Read next directory entry */
+			dent = readdir(cs->dir);
+			if (dent == NULL) {
+				/* Error. Close directory, go to next one */
+				closedir(cs->dir);
+				cs->dir = NULL;
+				cs->path++;
+				continue;
+			}
+
+			if (compl_match_prefix(cs, dent->d_name)) {
+				/* Construct pathname */
+				char *ent_path;
+				asprintf(&ent_path, "%s/%s", *cs->path, dent->d_name);
+				struct stat ent_stat;
+				if (stat(ent_path, &ent_stat) != EOK) {
+					/* Error */
+					free(ent_path);
+					continue;
+				}
+
+				free(ent_path);
+
+				/* If completing command, do not match directories. */
+				if (!ent_stat.is_directory || !cs->is_command) {
+					asprintf(compl, "%s%c", dent->d_name,
+					    ent_stat.is_directory ? '/' : ' ');
+					cs->last_compl = *compl;
+					if (*compl == NULL)
+						return ENOMEM;
+				}
+			}
+		}
+	}
+
+	if (*compl == NULL)
+		return ENOENT;
+
+	return EOK;
+}
+
+/** Finish completion operation. */
+static void compl_fini(void *state)
+{
+	compl_t *cs = (compl_t *) state;
+
+	if (cs->path_list != NULL) {
+		size_t i = 0;
+		while (cs->path_list[i] != NULL) {
+			free(cs->path_list[i]);
+			++i;
+		}
+		free(cs->path_list);
+	}
+
+	if (cs->last_compl != NULL)
+		free(cs->last_compl);
+	if (cs->dir != NULL)
+		closedir(cs->dir);
+
+	free(cs->prefix);
+	free(cs);
+}
Index: uspace/app/bdsh/compl.h
===================================================================
--- uspace/app/bdsh/compl.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/bdsh/compl.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
+#ifndef COMPL_H
+#define COMPL_H
+
+#include <tinput.h>
+
+extern tinput_compl_ops_t compl_ops;
+
+#endif
Index: uspace/app/bdsh/config.h
===================================================================
--- uspace/app/bdsh/config.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/config.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 /* Various things that are used in many places including a few
  * tidbits left over from autoconf prior to the HelenOS port */
@@ -11,8 +39,4 @@
 #define EXIT_FAILURE 1
 #endif
-
-/* Work around for getenv() */
-#define PATH "/srv:/app"
-#define PATH_DELIM ":"
 
 /* Used in many places */
Index: uspace/app/bdsh/errors.c
===================================================================
--- uspace/app/bdsh/errors.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/errors.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -38,4 +36,5 @@
 #include "errors.h"
 #include "errstr.h"
+#include "scli.h"
 
 volatile int cli_errno = CL_EOK;
Index: uspace/app/bdsh/errors.h
===================================================================
--- uspace/app/bdsh/errors.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/errors.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef ERRORS_H
 #define ERRORS_H
Index: uspace/app/bdsh/errstr.h
===================================================================
--- uspace/app/bdsh/errstr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/errstr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef ERRSTR_H
 #define ERRSTR_H
Index: uspace/app/bdsh/exec.c
===================================================================
--- uspace/app/bdsh/exec.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/exec.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -42,4 +40,5 @@
 #include <str_error.h>
 #include <errno.h>
+#include <vfs/vfs.h>
 
 #include "config.h"
@@ -53,4 +52,6 @@
 static char *find_command(char *);
 static int try_access(const char *);
+
+const char *search_dir[] = { "/app", "/srv", NULL };
 
 /* work-around for access() */
@@ -71,8 +72,5 @@
 static char *find_command(char *cmd)
 {
-	char *path_tok;
-	char *path[PATH_MAX];
-	int n = 0, i = 0;
-	size_t x = str_size(cmd) + 2;
+	size_t i;
 
 	found = (char *)malloc(PATH_MAX);
@@ -83,24 +81,9 @@
 	}
 
-	path_tok = str_dup(PATH);
-
-	/* Extract the PATH env to a path[] array */
-	path[n] = strtok(path_tok, PATH_DELIM);
-	while (NULL != path[n]) {
-		if ((str_size(path[n]) + x ) > PATH_MAX) {
-			cli_error(CL_ENOTSUP,
-				"Segment %d of path is too large, search ends at segment %d",
-				n, n-1);
-			break;
-		}
-		path[++n] = strtok(NULL, PATH_DELIM);
-	}
-
 	/* We now have n places to look for the command */
-	for (i=0; path[i]; i++) {
+	for (i = 0; search_dir[i] != NULL; i++) {
 		memset(found, 0, sizeof(found));
-		snprintf(found, PATH_MAX, "%s/%s", path[i], cmd);
+		snprintf(found, PATH_MAX, "%s/%s", search_dir[i], cmd);
 		if (-1 != try_access(found)) {
-			free(path_tok);
 			return (char *) found;
 		}
@@ -108,19 +91,35 @@
 
 	/* We didn't find it, just give it back as-is. */
-	free(path_tok);
 	return (char *) cmd;
 }
 
-unsigned int try_exec(char *cmd, char **argv)
+unsigned int try_exec(char *cmd, char **argv, iostate_t *io)
 {
 	task_id_t tid;
 	task_exit_t texit;
 	char *tmp;
-	int rc, retval;
+	int rc, retval, i;
+	int file_handles[3];
+	int *file_handles_p[4];
+	FILE *files[3];
 
 	tmp = str_dup(find_command(cmd));
 	free(found);
+	
+	files[0] = io->stdin;
+	files[1] = io->stdout;
+	files[2] = io->stderr;
+	
+	for (i = 0; i < 3 && files[i] != NULL; i++) {
+		if (fhandle(files[i], &file_handles[i]) == EOK) {
+			file_handles_p[i] = &file_handles[i];
+		}
+		else {
+			file_handles_p[i] = NULL;
+		}
+	}
+	file_handles_p[i] = NULL;
 
-	rc = task_spawnv(&tid, tmp, (const char **) argv);
+	rc = task_spawnvf(&tid, tmp, (const char **) argv, file_handles_p);
 	free(tmp);
 
Index: uspace/app/bdsh/exec.h
===================================================================
--- uspace/app/bdsh/exec.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/exec.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,8 +1,39 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef EXEC_H
 #define EXEC_H
 
 #include <task.h>
+#include "scli.h"
 
-extern unsigned int try_exec(char *, char **);
+extern const char *search_dir[];
+
+extern unsigned int try_exec(char *, char **, iostate_t *);
 
 #endif
Index: uspace/app/bdsh/input.c
===================================================================
--- uspace/app/bdsh/input.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/input.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,30 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
+ * Copyright (c) 2011 Jiri Svoboda
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -45,4 +45,5 @@
 
 #include "config.h"
+#include "compl.h"
 #include "util.h"
 #include "scli.h"
@@ -50,4 +51,5 @@
 #include "errors.h"
 #include "exec.h"
+#include "tok.h"
 
 extern volatile unsigned int cli_quit;
@@ -55,44 +57,150 @@
 /** Text input field. */
 static tinput_t *tinput;
+
+/* Private helpers */
+static int run_command(char **, cliuser_t *, iostate_t *);
+static void print_pipe_usage(void);
 
 /* Tokenizes input from console, sees if the first word is a built-in, if so
  * invokes the built-in entry point (a[0]) passing all arguments in a[] to
  * the handler */
-int tok_input(cliuser_t *usr)
+int process_input(cliuser_t *usr)
 {
 	char *cmd[WORD_MAX];
-	int n = 0, i = 0;
+	token_t tokens_space[WORD_MAX];
+	token_t *tokens = tokens_space;
 	int rc = 0;
-	char *tmp;
+	tokenizer_t tok;
+	unsigned int i, pipe_count, processed_pipes;
+	unsigned int pipe_pos[2];
+	char *redir_from = NULL;
+	char *redir_to = NULL;
 
 	if (NULL == usr->line)
 		return CL_EFAIL;
 
-	tmp = str_dup(usr->line);
-
-	cmd[n] = strtok(tmp, " ");
-	while (cmd[n] && n < WORD_MAX) {
-		cmd[++n] = strtok(NULL, " ");
-	}
-
-	/* We have rubbish */
-	if (NULL == cmd[0]) {
-		rc = CL_ENOENT;
-		goto finit;
-	}
-
-	/* Its a builtin command ? */
-	if ((i = (is_builtin(cmd[0]))) > -1) {
-		rc = run_builtin(i, cmd, usr);
-		goto finit;
-	/* Its a module ? */
-	} else if ((i = (is_module(cmd[0]))) > -1) {
-		rc = run_module(i, cmd);
-		goto finit;
-	}
-
-	/* See what try_exec thinks of it */
-	rc = try_exec(cmd[0], cmd);
-
+	rc = tok_init(&tok, usr->line, tokens, WORD_MAX);
+	if (rc != EOK) {
+		goto finit;
+	}
+	
+	size_t tokens_length;
+	rc = tok_tokenize(&tok, &tokens_length);
+	if (rc != EOK) {
+		goto finit;
+	}
+	
+	if (tokens_length > 0 && tokens[0].type == TOKTYPE_SPACE) {
+		tokens++;
+		tokens_length--;
+	}
+	
+	if (tokens_length > 0 && tokens[tokens_length-1].type == TOKTYPE_SPACE) {
+		tokens_length--;
+	}
+	
+	/* Until full support for pipes is implemented, allow for a simple case:
+	 * [from <file> |] command [| to <file>]
+	 * 
+	 * First find the pipes and check that there are no more
+	 */
+	for (i = 0, pipe_count = 0; i < tokens_length; i++) {
+		if (tokens[i].type == TOKTYPE_PIPE) {
+			if (pipe_count >= 2) {
+				print_pipe_usage();
+				rc = ENOTSUP;
+				goto finit;
+			}
+			pipe_pos[pipe_count] = i;
+			pipe_count++;
+		}
+	}
+	
+	unsigned int cmd_token_start = 0;
+	unsigned int cmd_token_end = tokens_length;
+	
+	processed_pipes = 0;
+	
+	/* Check if the first part (from <file> |) is present */
+	if (pipe_count > 0 && (pipe_pos[0] == 3 || pipe_pos[0] == 4) && str_cmp(tokens[0].text, "from") == 0) {
+		/* Ignore the first three tokens (from, file, pipe) and set from */
+		redir_from = tokens[2].text;
+		cmd_token_start = pipe_pos[0]+1;
+		processed_pipes++;
+	}
+	
+	/* Check if the second part (| to <file>) is present */
+	if ((pipe_count - processed_pipes) > 0 &&
+	    (pipe_pos[processed_pipes] == tokens_length - 4 ||
+	    (pipe_pos[processed_pipes] == tokens_length - 5 &&
+	    tokens[tokens_length-4].type == TOKTYPE_SPACE )) &&
+	    str_cmp(tokens[tokens_length-3].text, "to") == 0) {
+		/* Ignore the last three tokens (pipe, to, file) and set to */
+		redir_to = tokens[tokens_length-1].text;
+		cmd_token_end = pipe_pos[processed_pipes];
+		processed_pipes++;
+	}
+	
+	if (processed_pipes != pipe_count) {
+		print_pipe_usage();
+		rc = ENOTSUP;
+		goto finit;
+	}
+	
+	/* Convert tokens of the command to string array */
+	unsigned int cmd_pos = 0;
+	for (i = cmd_token_start; i < cmd_token_end; i++) {
+		if (tokens[i].type != TOKTYPE_SPACE) {
+			cmd[cmd_pos++] = tokens[i].text;
+		}
+	}
+	cmd[cmd_pos++] = NULL;
+	
+	if (cmd[0] == NULL) {
+		print_pipe_usage();
+		rc = ENOTSUP;
+		goto finit;
+	}
+	
+	iostate_t new_iostate = {
+		.stdin = stdin,
+		.stdout = stdout,
+		.stderr = stderr
+	};
+	
+	FILE *from = NULL;
+	FILE *to = NULL;
+	
+	if (redir_from) {
+		from = fopen(redir_from, "r");
+		if (from == NULL) {
+			printf("Cannot open file %s\n", redir_from);
+			rc = errno;
+			goto finit_with_files;
+		}
+		new_iostate.stdin = from;
+	}
+	
+	
+	if (redir_to) {
+		to = fopen(redir_to, "w");
+		if (to == NULL) {
+			printf("Cannot open file %s\n", redir_to);
+			rc = errno;
+			goto finit_with_files;
+		}
+		new_iostate.stdout = to;
+	}
+	
+	rc = run_command(cmd, usr, &new_iostate);
+	
+finit_with_files:
+	if (from != NULL) {
+		fclose(from);
+	}
+	if (to != NULL) {
+		fclose(to);
+	}
+	
 finit:
 	if (NULL != usr->line) {
@@ -100,8 +208,40 @@
 		usr->line = (char *) NULL;
 	}
-	if (NULL != tmp)
-		free(tmp);
+	tok_fini(&tok);
 
 	return rc;
+}
+
+void print_pipe_usage()
+{
+	printf("Invalid syntax!\n");
+	printf("Usage of redirection (pipes in the future):\n");
+	printf("from filename | command ...\n");
+	printf("from filename | command ... | to filename\n");
+	printf("command ... | to filename\n");
+	
+}
+
+int run_command(char **cmd, cliuser_t *usr, iostate_t *new_iostate)
+{
+	int id = 0;
+	
+	/* We have rubbish */
+	if (NULL == cmd[0]) {
+		return CL_ENOENT;
+	}
+	
+	/* Is it a builtin command ? */
+	if ((id = (is_builtin(cmd[0]))) > -1) {
+		return run_builtin(id, cmd, usr, new_iostate);
+	}
+	
+	/* Is it a module ? */
+	if ((id = (is_module(cmd[0]))) > -1) {
+		return run_module(id, cmd, new_iostate);
+	}
+
+	/* See what try_exec thinks of it */
+	return try_exec(cmd[0], cmd, new_iostate);
 }
 
@@ -110,10 +250,6 @@
 	char *str;
 	int rc;
-
-	fflush(stdout);
-	console_set_style(fphone(stdout), STYLE_EMPHASIS);
-	printf("%s", usr->prompt);
-	fflush(stdout);
-	console_set_style(fphone(stdout), STYLE_NORMAL);
+	
+	tinput_set_prompt(tinput, usr->prompt);
 
 	rc = tinput_read(tinput, &str);
@@ -148,4 +284,6 @@
 	}
 
+	tinput_set_compl_ops(tinput, &compl_ops);
+
 	return 0;
 }
Index: uspace/app/bdsh/input.h
===================================================================
--- uspace/app/bdsh/input.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/input.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef INPUT_H
 #define INPUT_H
@@ -7,5 +35,5 @@
 
 extern void get_input(cliuser_t *);
-extern int tok_input(cliuser_t *);
+extern int process_input(cliuser_t *);
 extern int input_init(void);
 
Index: uspace/app/bdsh/scli.c
===================================================================
--- uspace/app/bdsh/scli.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/scli.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,30 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com>
+/*
+ * Copyright (c) 2008 Tim Post
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -42,4 +40,6 @@
 /* See scli.h */
 static cliuser_t usr;
+static iostate_t *iostate;
+static iostate_t stdiostate;
 
 /* Globals that are modified during start-up that modules/builtins
@@ -82,7 +82,26 @@
 }
 
+iostate_t *get_iostate(void)
+{
+	return iostate;
+}
+
+
+void set_iostate(iostate_t *ios)
+{
+	iostate = ios;
+	stdin = ios->stdin;
+	stdout = ios->stdout;
+	stderr = ios->stderr;
+}
+
 int main(int argc, char *argv[])
 {
 	int ret = 0;
+	
+	stdiostate.stdin = stdin;
+	stdiostate.stdout = stdout;
+	stdiostate.stderr = stderr;
+	iostate = &stdiostate;
 
 	if (cli_init(&usr))
@@ -92,5 +111,5 @@
 		get_input(&usr);
 		if (NULL != usr.line) {
-			ret = tok_input(&usr);
+			ret = process_input(&usr);
 			cli_set_prompt(&usr);
 			usr.lasterr = ret;
Index: uspace/app/bdsh/scli.h
===================================================================
--- uspace/app/bdsh/scli.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/scli.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef SCLI_H
 #define SCLI_H
@@ -4,4 +32,5 @@
 #include "config.h"
 #include <stdint.h>
+#include <stdio.h>
 
 typedef struct {
@@ -13,5 +42,14 @@
 } cliuser_t;
 
+typedef struct {
+	FILE *stdin;
+	FILE *stdout;
+	FILE *stderr;
+} iostate_t;
+
 extern const char *progname;
 
+extern iostate_t *get_iostate(void);
+extern void set_iostate(iostate_t *);
+
 #endif
Index: uspace/app/bdsh/tok.c
===================================================================
--- uspace/app/bdsh/tok.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/bdsh/tok.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 <str.h>
+#include <assert.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "tok.h"
+
+/* Forward declarations of static functions */
+static wchar_t tok_get_char(tokenizer_t *);
+static wchar_t tok_look_char(tokenizer_t *);
+static int tok_push_char(tokenizer_t *, wchar_t);
+static int tok_push_token(tokenizer_t *);
+static bool tok_pending_chars(tokenizer_t *);
+static int tok_finish_string(tokenizer_t *);
+static void tok_start_token(tokenizer_t *, token_type_t);
+
+/** Initialize the token parser
+ * 
+ * @param tok the tokenizer structure to initialize
+ * @param input the input string to tokenize
+ * @param out_tokens array of strings where to store the result
+ * @param max_tokens number of elements of the out_tokens array
+ */
+int tok_init(tokenizer_t *tok, char *input, token_t *out_tokens,
+    size_t max_tokens)
+{	
+	tok->in = input;
+	tok->in_offset = 0;
+	tok->last_in_offset = 0;
+	tok->in_char_offset = 0;
+	tok->last_in_char_offset = 0;
+	
+	tok->outtok = out_tokens;
+	tok->outtok_offset = 0;
+	tok->outtok_size = max_tokens;
+	
+	/* Prepare a buffer where all the token strings will be stored */
+	size_t len = str_size(input) + max_tokens + 1;
+	char *tmp = malloc(len);
+	
+	if (tmp == NULL) {
+		return ENOMEM;
+	}
+	
+	tok->outbuf = tmp;
+	tok->outbuf_offset = 0;
+	tok->outbuf_size = len;
+	tok->outbuf_last_start = 0;
+	
+	return EOK;
+}
+
+/** Finalize the token parser */
+void tok_fini(tokenizer_t *tok)
+{
+	if (tok->outbuf != NULL) {
+		free(tok->outbuf);
+	}
+}
+
+/** Tokenize the input string into the tokens */
+int tok_tokenize(tokenizer_t *tok, size_t *tokens_length)
+{
+	int rc;
+	wchar_t next_char;
+	
+	/* Read the input line char by char and append tokens */
+	while ((next_char = tok_look_char(tok)) != 0) {
+		if (next_char == ' ') {
+			/* Push the token if there is any.
+			 * There may not be any pending char for a token in case
+			 * there are several spaces in the input.
+			 */
+			if (tok_pending_chars(tok)) {
+				rc = tok_push_token(tok);
+				if (rc != EOK) {
+					return rc;
+				}
+			}
+			tok_start_token(tok, TOKTYPE_SPACE);
+			/* Eat all the spaces */
+			while (tok_look_char(tok) == ' ') {
+				tok_push_char(tok, tok_get_char(tok));
+			}
+			tok_push_token(tok);
+			
+		}
+		else if (next_char == '|') {
+			/* Pipes are tokens that are delimiters and should be
+			 * output as a separate token
+			 */
+			if (tok_pending_chars(tok)) {
+				rc = tok_push_token(tok);
+				if (rc != EOK) {
+					return rc;
+				}
+			}
+			
+			tok_start_token(tok, TOKTYPE_PIPE);
+			
+			rc = tok_push_char(tok, tok_get_char(tok));
+			if (rc != EOK) {
+				return rc;
+			}
+			
+			rc = tok_push_token(tok);
+			if (rc != EOK) {
+				return rc;
+			}
+		}
+		else if (next_char == '\'') {
+			/* A string starts with a quote (') and ends again with a quote.
+			 * A literal quote is written as ''
+			 */
+			tok_start_token(tok, TOKTYPE_TEXT);
+			/* Eat the quote */
+			tok_get_char(tok);
+			rc = tok_finish_string(tok);
+			if (rc != EOK) {
+				return rc;
+			}
+		}
+		else {
+			if (!tok_pending_chars(tok)) {
+				tok_start_token(tok, TOKTYPE_TEXT);
+			}
+			/* If we are handling any other character, just append it to
+			 * the current token.
+			 */
+			rc = tok_push_char(tok, tok_get_char(tok));
+			if (rc != EOK) {
+				return rc;
+			}
+		}
+	}
+	
+	/* Push the last token */
+	if (tok_pending_chars(tok)) {
+		rc = tok_push_token(tok);
+		if (rc != EOK) {
+			return rc;
+		}
+	}
+	
+	*tokens_length = tok->outtok_offset;
+	
+	return EOK;
+}
+
+/** Finish tokenizing an opened string */
+int tok_finish_string(tokenizer_t *tok)
+{
+	int rc;
+	wchar_t next_char;
+	
+	while ((next_char = tok_look_char(tok)) != 0) {
+		if (next_char == '\'') {
+			/* Eat the quote */
+			tok_get_char(tok);
+			if (tok_look_char(tok) == '\'') {
+				/* Encode a single literal quote */
+				rc = tok_push_char(tok, '\'');
+				if (rc != EOK) {
+					return rc;
+				}
+				
+				/* Swallow the additional one in the input */
+				tok_get_char(tok);
+			}
+			else {
+				/* The string end */
+				return tok_push_token(tok);
+			}
+		}
+		else {
+			rc = tok_push_char(tok, tok_get_char(tok));
+			if (rc != EOK) {
+				return rc;
+			}
+		}
+	}
+	
+	/* If we are here, the string run to the end without being closed */
+	return EINVAL;
+}
+
+/** Get a char from input, advancing the input position */
+wchar_t tok_get_char(tokenizer_t *tok)
+{
+	tok->in_char_offset++;
+	return str_decode(tok->in, &tok->in_offset, STR_NO_LIMIT);
+}
+
+/** Get a char from input, while staying on the same input position */
+wchar_t tok_look_char(tokenizer_t *tok)
+{
+	unsigned int old_offset = tok->in_offset;
+	unsigned int old_char_offset = tok->in_char_offset;
+	wchar_t ret = tok_get_char(tok);
+	tok->in_offset = old_offset;
+	tok->in_char_offset = old_char_offset;
+	return ret;
+}
+
+/** Append a char to the end of the current token */
+int tok_push_char(tokenizer_t *tok, wchar_t ch)
+{
+	return chr_encode(ch, tok->outbuf, &tok->outbuf_offset, tok->outbuf_size);
+}
+
+void tok_start_token(tokenizer_t *tok, token_type_t type)
+{
+	tok->current_type = type;
+}
+
+/** Push the current token to the output array */
+int tok_push_token(tokenizer_t *tok)
+{
+	if (tok->outtok_offset >= tok->outtok_size) {
+		return EOVERFLOW;
+	}
+	
+	if (tok->outbuf_offset >= tok->outbuf_size) {
+		return EOVERFLOW;
+	}
+	
+	tok->outbuf[tok->outbuf_offset++] = 0;
+	token_t *tokinfo = &tok->outtok[tok->outtok_offset++];
+	tokinfo->type = tok->current_type;
+	tokinfo->text = tok->outbuf + tok->outbuf_last_start;
+	tokinfo->byte_start = tok->last_in_offset;
+	tokinfo->byte_length = tok->in_offset - tok->last_in_offset;
+	tokinfo->char_start = tok->last_in_char_offset;
+	tokinfo->char_length = tok->in_char_offset - tok->last_in_char_offset;
+	tok->outbuf_last_start = tok->outbuf_offset;
+	
+	/* We have consumed the first char of the next token already */
+	tok->last_in_offset = tok->in_offset;
+	tok->last_in_char_offset = tok->in_char_offset;
+	
+	return EOK;
+}
+
+/** Return true, if the current token is not empty */
+bool tok_pending_chars(tokenizer_t *tok)
+{
+	assert(tok->outbuf_offset >= tok->outbuf_last_start);
+	return (tok->outbuf_offset != tok->outbuf_last_start);
+}
Index: uspace/app/bdsh/tok.h
===================================================================
--- uspace/app/bdsh/tok.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/bdsh/tok.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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.
+ */
+
+#ifndef TOK_H
+#define TOK_H
+
+typedef enum {
+	TOKTYPE_TEXT,
+	TOKTYPE_PIPE,
+	TOKTYPE_SPACE
+} token_type_t;
+
+typedef struct {
+	char *text;
+	unsigned int byte_start;
+	unsigned int char_start;
+	size_t byte_length;
+	size_t char_length;
+ 	token_type_t type;
+} token_t;
+
+typedef struct {
+	char *in;
+	unsigned int in_offset;
+	unsigned int last_in_offset;
+	unsigned int in_char_offset;
+	unsigned int last_in_char_offset;
+	
+	char *outbuf;
+	size_t outbuf_offset;
+	size_t outbuf_size;
+	size_t outbuf_last_start;
+	
+	token_t *outtok;
+	token_type_t current_type;
+	size_t outtok_offset;
+	size_t outtok_size;
+} tokenizer_t;
+
+extern int tok_init(tokenizer_t *, char *, token_t *, size_t);
+extern void tok_fini(tokenizer_t *);
+extern int tok_tokenize(tokenizer_t *, size_t *);
+
+#endif
Index: uspace/app/bdsh/util.c
===================================================================
--- uspace/app/bdsh/util.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/util.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,29 +1,28 @@
-/* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> - All rights reserved
+/*
+ * Copyright (c) 2008 Tim Post
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
+ * 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 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.
  *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of the original program's authors nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  */
 
@@ -69,4 +68,2 @@
 	return 0;
 }
-
-
Index: uspace/app/bdsh/util.h
===================================================================
--- uspace/app/bdsh/util.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/bdsh/util.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,2 +1,30 @@
+/*
+ * Copyright (c) 2008 Tim Post
+ * 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.
+ */
+
 #ifndef UTIL_H
 #define UTIL_H
Index: uspace/app/blkdump/Makefile
===================================================================
--- uspace/app/blkdump/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/blkdump/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
+BINARY = blkdump
+
+SOURCES = \
+	blkdump.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/blkdump/blkdump.c
===================================================================
--- uspace/app/blkdump/blkdump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/blkdump/blkdump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+/**
+ * @file	blockdump.c
+ * @brief	Tool for dumping content of block devices
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libblock.h>
+#include <mem.h>
+#include <loc.h>
+#include <byteorder.h>
+#include <sys/types.h>
+#include <sys/typefmt.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#define NAME	"blkdump"
+
+static void syntax_print(void);
+static void print_hex_row(uint8_t *data, size_t length, size_t bytes_per_row);
+
+int main(int argc, char **argv)
+{
+
+	int rc;
+	char *dev_path;
+	service_id_t service_id;
+	size_t block_size;
+	char *endptr;
+	aoff64_t block_offset = 0;
+	aoff64_t block_count = 1;
+	aoff64_t dev_nblocks;
+	uint8_t *data;
+	size_t data_offset;
+	aoff64_t current;
+	aoff64_t limit;
+	bool relative = false;
+	
+	if (argc < 2) {
+		printf(NAME ": Error, argument missing.\n");
+		syntax_print();
+		return 1;
+	}
+
+	--argc; ++argv;
+
+	if (str_cmp(*argv, "--relative") == 0) {
+		--argc; ++argv;
+		relative = true;
+	}
+	
+	if (str_cmp(*argv, "--offset") == 0) {
+		--argc; ++argv;
+		if (*argv == NULL) {
+			printf(NAME ": Error, argument missing (offset).\n");
+			syntax_print();
+			return 1;
+		}
+
+		block_offset = strtol(*argv, &endptr, 10);
+		if (*endptr != '\0') {
+			printf(NAME ": Error, invalid argument (offset).\n");
+			syntax_print();
+			return 1;
+		}
+
+		--argc; ++argv;
+	}
+	
+	if (str_cmp(*argv, "--count") == 0) {
+		--argc; ++argv;
+		if (*argv == NULL) {
+			printf(NAME ": Error, argument missing (count).\n");
+			syntax_print();
+			return 1;
+		}
+
+		block_count = strtol(*argv, &endptr, 10);
+		if (*endptr != '\0') {
+			printf(NAME ": Error, invalid argument (count).\n");
+			syntax_print();
+			return 1;
+		}
+
+		--argc; ++argv;
+	}
+
+	if (argc != 1) {
+		printf(NAME ": Error, unexpected argument.\n");
+		syntax_print();
+		return 1;
+	}
+
+	dev_path = *argv;
+
+	rc = loc_service_get_id(dev_path, &service_id, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving device `%s'.\n", dev_path);
+		return 2;
+	}
+
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
+	if (rc != EOK)  {
+		printf(NAME ": Error initializing libblock.\n");
+		return 2;
+	}
+
+	rc = block_get_bsize(service_id, &block_size);
+	if (rc != EOK) {
+		printf(NAME ": Error determining device block size.\n");
+		return 2;
+	}
+
+	rc = block_get_nblocks(service_id, &dev_nblocks);
+	if (rc != EOK) {
+		printf(NAME ": Warning, failed to obtain block device size.\n");
+	}
+
+	printf("Device %s has %" PRIuOFF64 " blocks, %" PRIuOFF64 " bytes each\n", dev_path, dev_nblocks, (aoff64_t) block_size);
+
+	data = malloc(block_size);
+	if (data == NULL) {
+		printf(NAME ": Error allocating data buffer of %" PRIuOFF64 " bytes", (aoff64_t) block_size);
+		block_fini(service_id);
+		return 3;
+	}
+	
+	limit = block_offset + block_count;
+	for (current = block_offset; current < limit; current++) {
+		rc = block_read_direct(service_id, current, 1, data);
+		if (rc != EOK) {
+			printf(NAME ": Error reading block at %" PRIuOFF64 " \n", current);
+			free(data);
+			return 3;
+		}
+		
+		printf("---- Block %" PRIuOFF64 " (at %" PRIuOFF64 ") ----\n", current, current*block_size);
+		
+		for (data_offset = 0; data_offset < block_size; data_offset += 16) {
+			if (relative) {
+				printf("%8" PRIxOFF64 ": ", (aoff64_t) data_offset);
+			}
+			else {
+				printf("%8" PRIxOFF64 ": ", current*block_size + data_offset);
+			}
+			print_hex_row(data+data_offset, block_size-data_offset, 16);
+			printf("\n");
+		}
+		printf("\n");
+	}
+	
+	free(data);
+
+	block_fini(service_id);
+
+	return 0;
+}
+
+/**
+ * Print a row of 16 bytes as commonly seen in hexadecimal dumps
+ */
+static void print_hex_row(uint8_t *data, size_t length, size_t bytes_per_row) {
+	size_t pos;
+	uint8_t b;
+	
+	if (length > bytes_per_row) {
+		length = bytes_per_row;
+	}
+	
+	/* Print hexadecimal values */
+	for (pos = 0; pos < length; pos++) {
+		if (pos == length/2) {
+			printf(" ");
+		}
+		printf("%02hhX ", data[pos]);
+	}
+	
+	/* Pad with spaces if we have less than 16 bytes */
+	for (pos = length; pos < bytes_per_row; pos++) {
+		if (pos == length/2) {
+			printf(" ");
+		}
+		printf("   ");
+	}
+	
+	/* Print printable characters */
+	for (pos = 0; pos < length; pos++) {
+		if (pos == length/2) {
+			printf(" ");
+		}
+		b = data[pos];
+		if (b >= 32 && b < 128) {
+			putchar(b);
+		}
+		else {
+			putchar('.');
+		}
+	}
+}
+
+static void syntax_print(void)
+{
+	printf("syntax: blkdump [--relative] [--offset <num_blocks>] [--count <num_blocks>] <device_name>\n");
+}
+
+/**
+ * @}
+ */
Index: uspace/app/bnchmark/Makefile
===================================================================
--- uspace/app/bnchmark/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/bnchmark/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2011 Martin Sucha
+# 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 = bnchmark
+
+SOURCES = \
+	bnchmark.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/bnchmark/bnchmark.c
===================================================================
--- uspace/app/bnchmark/bnchmark.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/bnchmark/bnchmark.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 test
+ * @{
+ */
+
+/**
+ * @file	bnchmark.c
+ * This program measures time for various actions and writes the results
+ * to a file.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mem.h>
+#include <loc.h>
+#include <byteorder.h>
+#include <sys/types.h>
+#include <sys/typefmt.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <time.h>
+#include <dirent.h>
+
+#define NAME	"bnchmark"
+#define BUFSIZE 8096
+#define MBYTE (1024*1024)
+
+typedef int(*measure_func_t)(void *);
+typedef unsigned long umseconds_t; /* milliseconds */
+
+static void syntax_print(void);
+
+static int measure(measure_func_t fn, void* data, umseconds_t *result)
+{
+	struct timeval start_time;
+	int rc;
+	rc = gettimeofday(&start_time, NULL);
+	if (rc != EOK) {
+		fprintf(stderr, "gettimeofday failed\n");
+		return rc;
+	}
+	
+	rc = fn(data);
+	if (rc != EOK) {
+		fprintf(stderr, "measured function failed\n");
+		return rc;
+	}
+
+	struct timeval final_time;
+	rc = gettimeofday(&final_time, NULL);
+	if (rc != EOK) {
+		fprintf(stderr, "gettimeofday failed\n");
+		return rc;
+	}
+	
+	/* Calculate time difference in milliseconds */
+	*result = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
+	    ((final_time.tv_sec - start_time.tv_sec) * 1000);
+	return EOK;
+}
+
+static int sequential_read_file(void *data)
+{
+	char *path = (char *) data;
+	char *buf = malloc(BUFSIZE);
+
+	if (buf == NULL) {
+		return ENOMEM;
+	}
+	
+	FILE *file = fopen(path, "r");
+	if (file == NULL) {
+		fprintf(stderr, "Failed opening file: %s\n", path);
+		free(buf);
+		return EIO;
+	}
+	
+	while (!feof(file)) {
+		fread(buf, 1, BUFSIZE, file);
+		if (ferror(file)) {
+			fprintf(stderr, "Failed reading file\n");
+			fclose(file);
+			free(buf);
+			return EIO;
+		}
+	}
+	
+	fclose(file);
+	free(buf);
+	return EOK;
+}
+
+static int sequential_read_dir(void *data)
+{
+	char *path = (char *) data;
+	
+	DIR *dir = opendir(path);
+	if (dir == NULL) {
+		fprintf(stderr, "Failed opening directory: %s\n", path);
+		return EIO;
+	}
+
+	struct dirent *dp;
+	
+	while ((dp = readdir(dir))) {
+		/* Do nothing */
+	}
+	
+	closedir(dir);
+	return EOK;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	umseconds_t milliseconds_taken;
+	char *path = NULL;
+	measure_func_t fn = NULL;
+	int iteration;
+	int iterations;
+	char *log_str = NULL;
+	char *test_type = NULL;
+	char *endptr;
+	
+	if (argc < 5) {
+		fprintf(stderr, NAME ": Error, argument missing.\n");
+		syntax_print();
+		return 1;
+	}
+	
+	if (argc > 5) {
+		fprintf(stderr, NAME ": Error, too many arguments.\n");
+		syntax_print();
+		return 1;
+	}
+	
+	// Skip program name
+	--argc; ++argv;
+
+	iterations = strtol(*argv, &endptr, 10);
+	if (*endptr != '\0') {
+		printf(NAME ": Error, invalid argument (iterations).\n");
+		syntax_print();
+		return 1;
+	}
+	
+	--argc; ++argv;
+	test_type = *argv;
+
+	--argc; ++argv;
+	log_str = *argv;
+
+	--argc; ++argv;
+	path = *argv;
+	
+	if (str_cmp(test_type, "sequential-file-read") == 0) {
+		fn = sequential_read_file;
+	}
+	else if (str_cmp(test_type, "sequential-dir-read") == 0) {
+		fn = sequential_read_dir;
+	}
+	else {
+		fprintf(stderr, "Error, unknown test type\n");
+		syntax_print();
+		return 1;
+	}
+
+	for (iteration = 0; iteration < iterations; iteration++) {
+		rc = measure(fn, path, &milliseconds_taken);
+		if (rc != EOK) {
+			fprintf(stderr, "Error %d\n", rc);
+			return 1;
+		}
+	
+		printf("%s;%s;%s;%lu;ms\n", test_type, path, log_str, milliseconds_taken);
+	}
+
+	return 0;
+}
+
+
+static void syntax_print(void)
+{
+	fprintf(stderr, "syntax: " NAME " <iterations> <test type> <log-str> <path>\n");
+	fprintf(stderr, "  <iterations>    number of times to run a given test\n");
+	fprintf(stderr, "  <test-type>     one of:\n");
+	fprintf(stderr, "                    sequential-file-read\n");
+	fprintf(stderr, "                    sequential-dir-read\n");
+	fprintf(stderr, "  <log-str>       a string to attach to results\n");
+	fprintf(stderr, "  <path>          file/directory to use for testing\n");
+}
+
+/**
+ * @}
+ */
Index: uspace/app/devctl/Makefile
===================================================================
--- uspace/app/devctl/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/devctl/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2011 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+BINARY = devctl
+
+SOURCES = \
+	devctl.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/devctl/devctl.c
===================================================================
--- uspace/app/devctl/devctl.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/devctl/devctl.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup devctl
+ * @{
+ */
+/** @file Control device framework (devman server).
+ */
+
+#include <devman.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/typefmt.h>
+
+#define NAME "devctl"
+
+#define MAX_NAME_LENGTH 1024
+
+static int fun_tree_print(devman_handle_t funh, int lvl)
+{
+	char name[MAX_NAME_LENGTH];
+	devman_handle_t devh;
+	devman_handle_t *cfuns;
+	size_t count, i;
+	int rc;
+	int j;
+
+	for (j = 0; j < lvl; j++)
+		printf("    ");
+
+	rc = devman_fun_get_name(funh, name, MAX_NAME_LENGTH);
+	if (rc != EOK) {
+		str_cpy(name, MAX_NAME_LENGTH, "unknown");
+		return ENOMEM;
+	}
+
+	if (name[0] == '\0')
+		str_cpy(name, MAX_NAME_LENGTH, "/");
+
+	printf("%s (%" PRIun ")\n", name, funh);
+
+	rc = devman_fun_get_child(funh, &devh);
+	if (rc == ENOENT)
+		return EOK;
+
+	if (rc != EOK) {
+		printf(NAME ": Failed getting child device for function "
+		    "%s.\n", "xxx");
+		return rc;
+	}
+
+	rc = devman_dev_get_functions(devh, &cfuns, &count);
+	if (rc != EOK) {
+		printf(NAME ": Failed getting list of functions for "
+		    "device %s.\n", "xxx");
+		return rc;
+	}
+
+	for (i = 0; i < count; i++)
+		fun_tree_print(cfuns[i], lvl + 1);
+
+	free(cfuns);
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	devman_handle_t root_fun;
+	int rc;
+
+	rc = devman_fun_get_handle("/", &root_fun, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving root function.\n");
+		return 1;
+	}
+
+	rc = fun_tree_print(root_fun, 0);
+	if (rc != EOK)
+		return 1;
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/edit/edit.c
===================================================================
--- uspace/app/edit/edit.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/edit/edit.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -94,5 +94,5 @@
 } doc_t;
 
-static int con;
+static console_ctrl_t *con;
 static doc_t doc;
 static bool done;
@@ -115,7 +115,7 @@
 static void cursor_setvis(bool visible);
 
-static void key_handle_unmod(console_event_t const *ev);
-static void key_handle_ctrl(console_event_t const *ev);
-static void key_handle_shift(console_event_t const *ev);
+static void key_handle_unmod(kbd_event_t const *ev);
+static void key_handle_ctrl(kbd_event_t const *ev);
+static void key_handle_shift(kbd_event_t const *ev);
 static void key_handle_movement(unsigned int key, bool shift);
 
@@ -158,5 +158,5 @@
 int main(int argc, char *argv[])
 {
-	console_event_t ev;
+	kbd_event_t ev;
 	coord_t coord;
 	bool new_file;
@@ -164,5 +164,5 @@
 	spt_t pt;
 
-	con = fphone(stdout);
+	con = console_init(stdin, stdout);
 	console_clear(con);
 
@@ -219,5 +219,5 @@
 
 	while (!done) {
-		console_get_event(con, &ev);
+		console_get_kbd_event(con, &ev);
 		pane.rflags = 0;
 
@@ -277,5 +277,5 @@
 
 /** Handle key without modifier. */
-static void key_handle_unmod(console_event_t const *ev)
+static void key_handle_unmod(kbd_event_t const *ev)
 {
 	switch (ev->key) {
@@ -320,5 +320,5 @@
 
 /** Handle Shift-key combination. */
-static void key_handle_shift(console_event_t const *ev)
+static void key_handle_shift(kbd_event_t const *ev)
 {
 	switch (ev->key) {
@@ -344,5 +344,5 @@
 
 /** Handle Ctrl-key combination. */
-static void key_handle_ctrl(console_event_t const *ev)
+static void key_handle_ctrl(kbd_event_t const *ev)
 {
 	switch (ev->key) {
@@ -497,5 +497,5 @@
 static char *filename_prompt(char const *prompt, char const *init_value)
 {
-	console_event_t ev;
+	kbd_event_t ev;
 	char *str;
 	wchar_t buffer[INFNAME_MAX_LEN + 1];
@@ -517,5 +517,5 @@
 
 	while (!done) {
-		console_get_event(con, &ev);
+		console_get_kbd_event(con, &ev);
 
 		if (ev.type == KEY_PRESS) {
@@ -531,5 +531,5 @@
 					if (nc > 0) {
 						putchar('\b');
-						fflush(stdout);
+						console_flush(con);
 						--nc;
 					}
@@ -541,5 +541,5 @@
 					if (ev.c >= 32 && nc < max_len) {
 						putchar(ev.c);
-						fflush(stdout);
+						console_flush(con);
 						buffer[nc++] = ev.c;
 					}
@@ -689,5 +689,5 @@
 		for (j = 0; j < scr_columns; ++j)
 			putchar(' ');
-		fflush(stdout);
+		console_flush(con);
 	}
 
@@ -757,7 +757,7 @@
 		if (coord_cmp(&csel_start, &rbc) <= 0 &&
 		    coord_cmp(&rbc, &csel_end) < 0) {
-			fflush(stdout);
+			console_flush(con);
 			console_set_style(con, STYLE_SELECTED);
-			fflush(stdout);
+			console_flush(con);
 		}
 
@@ -768,13 +768,13 @@
 		while (pos < size) {
 			if ((csel_start.row == rbc.row) && (csel_start.column == s_column)) {
-				fflush(stdout);
+				console_flush(con);
 				console_set_style(con, STYLE_SELECTED);
-				fflush(stdout);
+				console_flush(con);
 			}
 	
 			if ((csel_end.row == rbc.row) && (csel_end.column == s_column)) {
-				fflush(stdout);
+				console_flush(con);
 				console_set_style(con, STYLE_NORMAL);
-				fflush(stdout);
+				console_flush(con);
 			}
 	
@@ -794,7 +794,7 @@
 
 		if ((csel_end.row == rbc.row) && (csel_end.column == s_column)) {
-			fflush(stdout);
+			console_flush(con);
 			console_set_style(con, STYLE_NORMAL);
-			fflush(stdout);
+			console_flush(con);
 		}
 
@@ -808,5 +808,5 @@
 		for (j = 0; j < fill; ++j)
 			putchar(' ');
-		fflush(stdout);
+		console_flush(con);
 		console_set_style(con, STYLE_NORMAL);
 	}
@@ -833,5 +833,5 @@
 	int pos = scr_columns - 1 - n;
 	printf("%*s", pos, "");
-	fflush(stdout);
+	console_flush(con);
 	console_set_style(con, STYLE_NORMAL);
 
@@ -1158,5 +1158,5 @@
 	int pos = -(scr_columns - 3);
 	printf(" %*s ", pos, str);
-	fflush(stdout);
+	console_flush(con);
 	console_set_style(con, STYLE_NORMAL);
 
Index: uspace/app/edit/sheet.c
===================================================================
--- uspace/app/edit/sheet.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/edit/sheet.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -75,5 +75,5 @@
 		return ENOMEM;
 
-	list_initialize(&sh->tags_head);
+	list_initialize(&sh->tags);
 
 	return EOK;
@@ -97,5 +97,4 @@
 	char *ipp;
 	size_t sz;
-	link_t *link;
 	tag_t *tag;
 	char *newp;
@@ -121,6 +120,5 @@
 	/* Adjust tags. */
 
-	link = sh->tags_head.next;
-	while (link != &sh->tags_head) {
+	list_foreach(sh->tags, link) {
 		tag = list_get_instance(link, tag_t, link);
 
@@ -129,6 +127,4 @@
 		else if (tag->b_off == pos->b_off && dir == dir_before)
 			tag->b_off += sz;
-
-		link = link->next;
 	}
 
@@ -150,5 +146,4 @@
 	char *spp;
 	size_t sz;
-	link_t *link;
 	tag_t *tag;
 	char *newp;
@@ -162,6 +157,5 @@
 
 	/* Adjust tags. */
-	link = sh->tags_head.next;
-	while (link != &sh->tags_head) {
+	list_foreach(sh->tags, link) {
 		tag = list_get_instance(link, tag_t, link);
 
@@ -170,6 +164,4 @@
 		else if (tag->b_off >= spos->b_off)
 			tag->b_off = spos->b_off;
-
-		link = link->next;
 	}
 
@@ -328,5 +320,5 @@
 	tag->b_off = pt->b_off;
 	tag->sh = sh;
-	list_append(&tag->link, &sh->tags_head);
+	list_append(&tag->link, &sh->tags);
 }
 
Index: uspace/app/edit/sheet.h
===================================================================
--- uspace/app/edit/sheet.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/edit/sheet.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -57,5 +57,5 @@
 	char *data;
 
-	link_t tags_head;
+	list_t tags;
 } sheet_t;
 
@@ -91,5 +91,5 @@
 	/* Note: This structure is opaque for the user. */
 
-	/** Link to list of all tags in the sheet (see sheet_t.tags_head) */
+	/** Link to list of all tags in the sheet (see sheet_t.tags) */
 	link_t link;
 	sheet_t *sh;
Index: uspace/app/ext2info/Makefile
===================================================================
--- uspace/app/ext2info/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/ext2info/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBEXT2_PREFIX)/libext2.a
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBEXT2_PREFIX)
+BINARY = ext2info
+
+SOURCES = \
+	ext2info.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/ext2info/ext2info.c
===================================================================
--- uspace/app/ext2info/ext2info.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/ext2info/ext2info.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,624 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+/**
+ * @file	ext2info.c
+ * @brief	Tool for displaying information about ext2 filesystem
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <libblock.h>
+#include <mem.h>
+#include <loc.h>
+#include <byteorder.h>
+#include <sys/types.h>
+#include <sys/typefmt.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <libext2.h>
+#include <assert.h>
+
+#define NAME	"ext2info"
+
+static void syntax_print(void);
+static void print_superblock(ext2_superblock_t *);
+static void print_block_groups(ext2_filesystem_t *);
+static void print_block_group(ext2_block_group_t *);
+static void print_inode_by_number(ext2_filesystem_t *, uint32_t, bool, uint32_t,
+    bool, bool);
+static void print_data(unsigned char *, size_t);
+static void print_inode(ext2_filesystem_t *, ext2_inode_t *, bool);
+static void print_inode_data(ext2_filesystem_t *, ext2_inode_t *, uint32_t);
+static void print_directory_contents(ext2_filesystem_t *, ext2_inode_ref_t *);
+
+#define ARG_SUPERBLOCK 1
+#define ARG_BLOCK_GROUPS 2
+#define ARG_INODE 4
+#define ARG_NO_CHECK 8
+#define ARG_INODE_DATA 16
+#define ARG_INODE_LIST 32
+#define ARG_INODE_BLOCKS 64
+#define ARG_COMMON (ARG_SUPERBLOCK)
+#define ARG_ALL 127
+
+
+int main(int argc, char **argv)
+{
+
+	int rc;
+	char *endptr;
+	char *dev_path;
+	service_id_t service_id;
+	ext2_filesystem_t filesystem;
+	int arg_flags;
+	uint32_t inode = 0;
+	uint32_t inode_data = 0;
+	
+	arg_flags = 0;
+	
+	if (argc < 2) {
+		printf(NAME ": Error, argument missing.\n");
+		syntax_print();
+		return 1;
+	}
+	
+	/* Skip program name */
+	--argc; ++argv;
+	
+	if (argc > 0 && str_cmp(*argv, "--no-check") == 0) {
+		--argc; ++argv;
+		arg_flags |= ARG_NO_CHECK;
+	}
+	
+	if (argc > 0 && str_cmp(*argv, "--superblock") == 0) {
+		--argc; ++argv;
+		arg_flags |= ARG_SUPERBLOCK;
+	}
+	
+	if (argc > 0 && str_cmp(*argv, "--block-groups") == 0) {
+		--argc; ++argv;
+		arg_flags |= ARG_BLOCK_GROUPS;
+	}
+	
+	if (argc > 0 && str_cmp(*argv, "--inode") == 0) {
+		--argc; ++argv;
+		if (argc == 0) {
+			printf(NAME ": Argument expected for --inode\n");
+			return 2;
+		}
+		
+		inode = strtol(*argv, &endptr, 10);
+		if (*endptr != '\0') {
+			printf(NAME ": Error, invalid argument for --inode.\n");
+			syntax_print();
+			return 1;
+		}
+		
+		arg_flags |= ARG_INODE;
+		--argc; ++argv;
+		
+		if (argc > 0 && str_cmp(*argv, "--blocks") == 0) {
+			--argc; ++argv;
+			arg_flags |= ARG_INODE_BLOCKS;
+		}
+		
+		if (argc > 0 && str_cmp(*argv, "--data") == 0) {
+			--argc; ++argv;
+			if (argc == 0) {
+				printf(NAME ": Argument expected for --data\n");
+				return 2;
+			}
+			
+			inode_data = strtol(*argv, &endptr, 10);
+			if (*endptr != '\0') {
+				printf(NAME ": Error, invalid argument for --data.\n");
+				syntax_print();
+				return 1;
+			}
+			
+			arg_flags |= ARG_INODE_DATA;
+			--argc; ++argv;
+		}
+		
+		if (argc > 0 && str_cmp(*argv, "--list") == 0) {
+			--argc; ++argv;
+			arg_flags |= ARG_INODE_LIST;
+		}
+	}
+
+	if (argc < 1) {
+		printf(NAME ": Error, argument missing.\n");
+		syntax_print();
+		return 1;
+	}
+	else if (argc > 1) {
+		printf(NAME ": Error, unexpected argument.\n");
+		syntax_print();
+		return 1;
+	}
+	assert(argc == 1);
+	
+	/* Display common things by default */
+	if ((arg_flags & ARG_ALL) == 0) {
+		arg_flags = ARG_COMMON;
+	}
+
+	dev_path = *argv;
+
+	rc = loc_service_get_id(dev_path, &service_id, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving device `%s'.\n", dev_path);
+		return 2;
+	}
+
+	rc = ext2_filesystem_init(&filesystem, service_id);
+	if (rc != EOK)  {
+		printf(NAME ": Error initializing libext2.\n");
+		return 3;
+	}
+	
+	rc = ext2_filesystem_check_sanity(&filesystem);
+	if (rc != EOK) {
+		printf(NAME ": Filesystem did not pass sanity check.\n");
+		if (!(arg_flags & ARG_NO_CHECK)) {
+			return 3;
+		}
+	}
+	
+	if (arg_flags & ARG_SUPERBLOCK) {
+		print_superblock(filesystem.superblock);
+	}
+	
+	if (arg_flags & ARG_BLOCK_GROUPS) {
+		print_block_groups(&filesystem);
+	}
+	
+	if (arg_flags & ARG_INODE) {
+		print_inode_by_number(&filesystem, inode, arg_flags & ARG_INODE_DATA,
+		    inode_data, arg_flags & ARG_INODE_LIST,
+		    arg_flags & ARG_INODE_BLOCKS);
+	}
+
+	ext2_filesystem_fini(&filesystem);
+
+	return 0;
+}
+
+
+static void syntax_print(void)
+{
+	printf("syntax: ext2info [--no-check] [--superblock] [--block-groups] "
+	    "[--inode <i-number> [--blocks] [--data <block-number>] [--list]] "
+	    "<device_name>\n");
+}
+
+static void print_superblock(ext2_superblock_t *superblock)
+{
+	uint16_t magic;
+	uint32_t first_block;
+	uint32_t block_size;
+	uint32_t fragment_size;
+	uint32_t blocks_per_group;
+	uint32_t fragments_per_group;
+	uint32_t rev_major;
+	uint16_t rev_minor;
+	uint16_t state;
+	uint32_t first_inode;
+	uint16_t inode_size;
+	uint32_t total_blocks;
+	uint32_t reserved_blocks;
+	uint32_t free_blocks;
+	uint32_t total_inodes;
+	uint32_t free_inodes;	
+	uint32_t os;
+	
+	int pos;
+	unsigned char c;
+	
+	magic = ext2_superblock_get_magic(superblock);
+	first_block = ext2_superblock_get_first_block(superblock);
+	block_size = ext2_superblock_get_block_size(superblock);
+	fragment_size = ext2_superblock_get_fragment_size(superblock);
+	blocks_per_group = ext2_superblock_get_blocks_per_group(superblock);
+	fragments_per_group = ext2_superblock_get_fragments_per_group(superblock);
+	rev_major = ext2_superblock_get_rev_major(superblock);
+	rev_minor = ext2_superblock_get_rev_minor(superblock);
+	state = ext2_superblock_get_state(superblock);
+	first_inode = ext2_superblock_get_first_inode(superblock);
+	inode_size = ext2_superblock_get_inode_size(superblock);
+	total_blocks = ext2_superblock_get_total_block_count(superblock);
+	reserved_blocks = ext2_superblock_get_reserved_block_count(superblock);
+	free_blocks = ext2_superblock_get_free_block_count(superblock);
+	total_inodes = ext2_superblock_get_total_inode_count(superblock);
+	free_inodes = ext2_superblock_get_free_inode_count(superblock);
+	os = ext2_superblock_get_os(superblock);
+	
+	printf("Superblock:\n");
+	
+	if (magic == EXT2_SUPERBLOCK_MAGIC) {
+		printf("  Magic value: %X (correct)\n", magic);
+	}
+	else {
+		printf("  Magic value: %X (incorrect)\n", magic);
+	}
+	
+	printf("  Revision: %u.%hu\n", rev_major, rev_minor);
+	printf("  State: %hu\n", state);
+	printf("  Creator OS: %u\n", os);
+	printf("  First block: %u\n", first_block);
+	printf("  Block size: %u bytes (%u KiB)\n", block_size, block_size/1024);
+	printf("  Blocks per group: %u\n", blocks_per_group);
+	printf("  Total blocks: %u\n", total_blocks);
+	printf("  Reserved blocks: %u\n", reserved_blocks);
+	printf("  Free blocks: %u\n", free_blocks);
+	printf("  Fragment size: %u bytes (%u KiB)\n", fragment_size,
+	    fragment_size/1024);
+	printf("  Fragments per group: %u\n", fragments_per_group);
+	printf("  First inode: %u\n", first_inode);
+	printf("  Inode size: %hu bytes\n", inode_size);
+	printf("  Total inodes: %u\n", total_inodes);
+	printf("  Free inodes: %u\n", free_inodes);
+	
+	
+	if (rev_major == 1) {
+		printf("  UUID: ");
+		for (pos = 0; pos < 16; pos++) {
+			printf("%02x", superblock->uuid[pos]);
+		}
+		printf("\n");
+		
+		printf("  Volume label: ");
+		for (pos = 0; pos < 16; pos++) {
+			c = superblock->volume_name[pos];
+			if (c >= 32 && c < 128) {
+				putchar(c);
+			}
+			else {
+				putchar(' ');
+			}
+		}
+		printf("\n");
+	}
+	
+}
+
+void print_block_groups(ext2_filesystem_t *filesystem)
+{
+	uint32_t block_group_count;
+	uint32_t i;
+	ext2_block_group_ref_t *block_group_ref;
+	int rc;
+	
+	printf("Block groups:\n");
+	
+	block_group_count = ext2_superblock_get_block_group_count(
+	    filesystem->superblock);
+	
+	for (i = 0; i < block_group_count; i++) {
+		printf("  Block group %u\n", i);
+		rc = ext2_filesystem_get_block_group_ref(filesystem, i, &block_group_ref);
+		if (rc != EOK) {
+			printf("    Failed reading block group\n");
+			continue;
+		}
+		
+		print_block_group(block_group_ref->block_group);
+		
+		rc = ext2_filesystem_put_block_group_ref(block_group_ref);
+		if (rc != EOK) {
+			printf("    Failed freeing block group\n");
+		}
+	}
+	
+}
+
+void print_block_group(ext2_block_group_t *bg)
+{
+	uint32_t block_bitmap_block;
+	uint32_t inode_bitmap_block;
+	uint32_t inode_table_first_block;
+	uint16_t free_block_count;
+	uint16_t free_inode_count;
+	uint16_t directory_inode_count;
+	
+	block_bitmap_block = ext2_block_group_get_block_bitmap_block(bg);
+	inode_bitmap_block = ext2_block_group_get_inode_bitmap_block(bg);
+	inode_table_first_block = ext2_block_group_get_inode_table_first_block(bg);
+	free_block_count = ext2_block_group_get_free_block_count(bg);
+	free_inode_count = ext2_block_group_get_free_inode_count(bg);
+	directory_inode_count = ext2_block_group_get_directory_inode_count(bg);
+	
+	printf("    Block bitmap block: %u\n", block_bitmap_block);
+	printf("    Inode bitmap block: %u\n", inode_bitmap_block);
+	printf("    Inode table's first block: %u\n", inode_table_first_block);
+	printf("    Free blocks: %u\n", free_block_count);
+	printf("    Free inodes: %u\n", free_inode_count);
+	printf("    Directory inodes: %u\n", directory_inode_count);
+}
+
+void print_inode_by_number(ext2_filesystem_t *fs, uint32_t inode, 
+    bool print_data, uint32_t data, bool list, bool blocks)
+{
+	int rc;
+	ext2_inode_ref_t *inode_ref;
+	
+	printf("Inode %u\n", inode);
+	
+	rc = ext2_filesystem_get_inode_ref(fs, inode, &inode_ref);
+	if (rc != EOK) {
+		printf("  Failed getting inode ref\n");
+		return;
+	}
+	
+	print_inode(fs, inode_ref->inode, blocks);
+	if (print_data) {
+		print_inode_data(fs, inode_ref->inode, data);
+	}
+	
+	if (list && ext2_inode_is_type(fs->superblock, inode_ref->inode,
+	    EXT2_INODE_MODE_DIRECTORY)) {
+		print_directory_contents(fs, inode_ref);
+	}
+	
+	rc = ext2_filesystem_put_inode_ref(inode_ref);
+	if (rc != EOK) {
+		printf("  Failed putting inode ref\n");
+	}
+}
+
+void print_inode(ext2_filesystem_t *fs, ext2_inode_t *inode, bool blocks)
+{
+	uint32_t mode;
+	uint32_t mode_type;
+	uint32_t user_id;
+	uint32_t group_id;
+	uint64_t size;
+	uint16_t usage_count;
+	uint32_t flags;
+	uint16_t access;
+	const char *type;
+	uint32_t total_blocks;
+	uint32_t i;
+	uint32_t range_start;
+	uint32_t range_last;
+	uint32_t range_start_file;
+	uint32_t range_last_file;
+	uint32_t range_current;
+	uint32_t range_expected;
+	uint32_t block_size;
+	uint64_t file_blocks;
+	bool printed_range;
+	int rc;
+	
+	block_size = ext2_superblock_get_block_size(fs->superblock);
+	mode = ext2_inode_get_mode(fs->superblock, inode);
+	mode_type = mode & EXT2_INODE_MODE_TYPE_MASK;
+	user_id = ext2_inode_get_user_id(fs->superblock, inode);
+	group_id = ext2_inode_get_group_id(fs->superblock, inode);
+	size = ext2_inode_get_size(fs->superblock, inode);
+	usage_count = ext2_inode_get_usage_count(inode);
+	flags = ext2_inode_get_flags(inode);
+	total_blocks = ext2_inode_get_reserved_blocks(fs->superblock, inode);
+	file_blocks = 0;
+	if (size > 0) {
+		file_blocks = ((size-1)/block_size)+1;
+	}
+	
+	type = "Unknown";
+	if (mode_type == EXT2_INODE_MODE_BLOCKDEV) {
+		type = "Block device";
+	}
+	else if (mode_type == EXT2_INODE_MODE_FIFO) {
+		type = "Fifo (pipe)";
+	}
+	else if (mode_type == EXT2_INODE_MODE_CHARDEV) {
+		type = "Character device";
+	}
+	else if (mode_type == EXT2_INODE_MODE_DIRECTORY) {
+		type = "Directory";
+	}
+	else if (mode_type == EXT2_INODE_MODE_FILE) {
+		type = "File";
+	}
+	else if (mode_type == EXT2_INODE_MODE_SOFTLINK) {
+		type = "Soft link";
+	}
+	else if (mode_type == EXT2_INODE_MODE_SOCKET) {
+		type = "Socket";
+	}
+	
+	access = mode & EXT2_INODE_MODE_ACCESS_MASK;
+	
+	
+	printf("  Mode: %08x (Type: %s, Access bits: %04ho)\n", mode, type, access);
+	printf("  User ID: %u\n", user_id);
+	printf("  Group ID: %u\n", group_id);
+	printf("  Size: %" PRIu64 "\n", size);
+	printf("  Usage (link) count: %u\n", usage_count);
+	printf("  Flags: %u\n", flags);
+	printf("  Total allocated blocks: %u\n", total_blocks);
+	
+	if (blocks) {
+		printf("  Block list: ");
+		
+		range_start = 0;
+		range_current = 0;
+		range_last = 0;
+		
+		printed_range = false;
+		
+		for (i = 0; i <= file_blocks; i++) {
+			if (i < file_blocks) {
+				rc = ext2_filesystem_get_inode_data_block_index(fs, inode, i, &range_current);
+				if (rc != EOK) {
+					printf("Error reading data block indexes\n");
+					return;
+				}
+			}
+			if (range_last == 0) {
+				range_expected = 0;
+			}
+			else {
+				range_expected = range_last + 1;
+			}
+			if (range_current != range_expected) {
+				if (i > 0) {
+					if (printed_range) {
+						printf(", ");
+					}
+					if (range_start == 0 && range_last == 0) {
+						if (range_start_file == range_last_file) {
+							printf("%u N/A", range_start_file);
+						}
+						else {
+							printf("[%u, %u] N/A", range_start_file,
+								range_last_file);
+						}
+					}
+					else {
+						if (range_start_file == range_last_file) {
+							printf("%u -> %u", range_start_file, range_start);
+						}
+						else {
+							printf("[%u, %u] -> [%u, %u]", range_start_file,
+								range_last_file, range_start, range_last);
+						}
+					}
+					printed_range = true;
+				}
+				range_start = range_current;
+				range_start_file = i;
+			}
+			range_last = range_current;
+			range_last_file = i;
+		}
+		printf("\n");
+	}
+}
+
+void print_data(unsigned char *data, size_t size)
+{
+	unsigned char c;
+	size_t i;
+	
+	for (i = 0; i < size; i++) {
+		c = data[i];
+		if (c >= 32 && c < 127) {
+			putchar(c);
+		}
+		else {
+			putchar('.');
+		}
+	}
+}
+
+void print_inode_data(ext2_filesystem_t *fs, ext2_inode_t *inode, uint32_t data)
+{
+	int rc;
+	uint32_t data_block_index;
+	block_t *block;
+	
+	rc = ext2_filesystem_get_inode_data_block_index(fs, inode, data,
+	    &data_block_index);
+	
+	if (rc != EOK) {
+		printf("Failed getting data block #%u\n", data);
+		return;
+	}
+	
+	printf("Data for inode contents block #%u is located in filesystem "
+	    "block %u\n", data, data_block_index);
+	
+	printf("Data preview (only printable characters):\n");
+	
+	rc = block_get(&block, fs->device, data_block_index, 0);
+	if (rc != EOK) {
+		printf("Failed reading filesystem block %u\n", data_block_index);
+		return;
+	}
+	
+	print_data(block->data, block->size);
+	printf("\n");	
+	
+	rc = block_put(block);
+	if (rc != EOK) {
+		printf("Failed putting filesystem block\n");
+	}
+	
+}
+
+void print_directory_contents(ext2_filesystem_t *fs,
+    ext2_inode_ref_t *inode_ref)
+{
+	int rc;
+	ext2_directory_iterator_t it;
+	size_t name_size;
+	uint32_t inode;
+	
+	printf("  Directory contents:\n");
+	
+	rc = ext2_directory_iterator_init(&it, fs, inode_ref, 0);
+	if (rc != EOK) {
+		printf("Failed initializing directory iterator\n");
+		return;
+	}
+	
+	while (it.current != NULL) {
+		name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
+		    it.current);
+		printf("    ");
+		print_data(&it.current->name, name_size);
+		
+		inode = ext2_directory_entry_ll_get_inode(it.current);
+		printf(" --> %u\n", inode);
+		
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK) {
+			printf("Failed reading directory contents\n");
+			goto cleanup;
+		}
+	}
+
+cleanup:
+	rc = ext2_directory_iterator_fini(&it);
+	if (rc != EOK) {
+		printf("Failed cleaning-up directory iterator\n");
+	}
+	
+}
+
+/**
+ * @}
+ */
Index: uspace/app/getterm/version.c
===================================================================
--- uspace/app/getterm/version.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/getterm/version.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -61,5 +61,5 @@
 	printf("HelenOS release %s (%s)%s%s\n", release, name, revision, timestamp);
 	printf("Running on %s (%s)\n", arch, term);
-	printf("Copyright (c) 2001-2010 HelenOS project\n\n");
+	printf("Copyright (c) 2001-2011 HelenOS project\n\n");
 }
 
Index: uspace/app/init/Makefile
===================================================================
--- uspace/app/init/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/init/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../..
 BINARY = init
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/init/init.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -46,5 +46,5 @@
 #include <macros.h>
 #include <str.h>
-#include <devmap.h>
+#include <loc.h>
 #include <str_error.h>
 #include "init.h"
@@ -53,6 +53,6 @@
 #define ROOT_MOUNT_POINT  "/"
 
-#define DEVFS_FS_TYPE      "devfs"
-#define DEVFS_MOUNT_POINT  "/dev"
+#define LOCFS_FS_TYPE      "locfs"
+#define LOCFS_MOUNT_POINT  "/loc"
 
 #define TMPFS_FS_TYPE      "tmpfs"
@@ -66,4 +66,5 @@
 #define APP_GETTERM  "/app/getterm"
 
+/** Print banner */
 static void info_print(void)
 {
@@ -71,4 +72,5 @@
 }
 
+/** Report mount operation success */
 static bool mount_report(const char *desc, const char *mntpt,
     const char *fstype, const char *dev, int rc)
@@ -100,4 +102,15 @@
 }
 
+/** Mount root filesystem
+ *
+ * The operation blocks until the root filesystem
+ * server is ready for mounting.
+ *
+ * @param[in] fstype Root filesystem type.
+ *
+ * @return True on success.
+ * @return False on failure.
+ *
+ */
 static bool mount_root(const char *fstype)
 {
@@ -113,10 +126,19 @@
 }
 
-static bool mount_devfs(void)
-{
-	int rc = mount(DEVFS_FS_TYPE, DEVFS_MOUNT_POINT, "", "",
+/** Mount locfs filesystem
+ *
+ * The operation blocks until the locfs filesystem
+ * server is ready for mounting.
+ *
+ * @return True on success.
+ * @return False on failure.
+ *
+ */
+static bool mount_locfs(void)
+{
+	int rc = mount(LOCFS_FS_TYPE, LOCFS_MOUNT_POINT, "", "",
 	    IPC_FLAG_BLOCKING);
-	return mount_report("Device filesystem", DEVFS_MOUNT_POINT, DEVFS_FS_TYPE,
-	    NULL, rc);
+	return mount_report("Location service filesystem", LOCFS_MOUNT_POINT,
+	    LOCFS_FS_TYPE, NULL, rc);
 }
 
@@ -157,5 +179,5 @@
 	rc = task_wait(id, &texit, &retval);
 	if (rc != EOK) {
-		printf("%s: Error waiting for %s (%s(\n", NAME, fname,
+		printf("%s: Error waiting for %s (%s)\n", NAME, fname,
 		    str_error(rc));
 		return;
@@ -174,41 +196,36 @@
 }
 
-static void console(const char *dev)
-{
-	char hid_in[DEVMAP_NAME_MAXLEN];
+static void console(const char *svc)
+{
+	printf("%s: Spawning %s %s\n", NAME, SRV_CONSOLE, svc);
+	
+	/* Wait for the input service to be ready */
+	service_id_t service_id;
+	int rc = loc_service_get_id(svc, &service_id, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Error waiting on %s (%s)\n", NAME, svc,
+		    str_error(rc));
+		return;
+	}
+	
+	rc = task_spawnl(NULL, SRV_CONSOLE, SRV_CONSOLE, svc, NULL);
+	if (rc != EOK) {
+		printf("%s: Error spawning %s %s (%s)\n", NAME, SRV_CONSOLE,
+		    svc, str_error(rc));
+	}
+}
+
+static void getterm(const char *svc, const char *app, bool wmsg)
+{
+	char term[LOC_NAME_MAXLEN];
 	int rc;
 	
-	snprintf(hid_in, DEVMAP_NAME_MAXLEN, "%s/%s", DEVFS_MOUNT_POINT, dev);
-	
-	printf("%s: Spawning %s %s\n", NAME, SRV_CONSOLE, hid_in);
-	
-	/* Wait for the input device to be ready */
-	devmap_handle_t handle;
-	rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		printf("%s: Error waiting on %s (%s)\n", NAME, hid_in,
-		    str_error(rc));
-		return;
-	}
-	
-	rc = task_spawnl(NULL, SRV_CONSOLE, SRV_CONSOLE, hid_in, NULL);
-	if (rc != EOK) {
-		printf("%s: Error spawning %s %s (%s)\n", NAME, SRV_CONSOLE,
-		    hid_in, str_error(rc));
-	}
-}
-
-static void getterm(const char *dev, const char *app, bool wmsg)
-{
-	char term[DEVMAP_NAME_MAXLEN];
-	int rc;
-	
-	snprintf(term, DEVMAP_NAME_MAXLEN, "%s/%s", DEVFS_MOUNT_POINT, dev);
+	snprintf(term, LOC_NAME_MAXLEN, "%s/%s", LOCFS_MOUNT_POINT, svc);
 	
 	printf("%s: Spawning %s %s %s\n", NAME, APP_GETTERM, term, app);
 	
-	/* Wait for the terminal device to be ready */
-	devmap_handle_t handle;
-	rc = devmap_device_get_handle(dev, &handle, IPC_FLAG_BLOCKING);
+	/* Wait for the terminal service to be ready */
+	service_id_t service_id;
+	rc = loc_service_get_id(svc, &service_id, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
 		printf("%s: Error waiting on %s (%s)\n", NAME, term,
@@ -262,8 +279,8 @@
 	}
 	
-	spawn("/srv/devfs");
+	spawn("/srv/locfs");
 	spawn("/srv/taskmon");
 	
-	if (!mount_devfs()) {
+	if (!mount_locfs()) {
 		printf("%s: Exiting\n", NAME);
 		return -2;
@@ -272,18 +289,16 @@
 	mount_tmpfs();
 	
+	spawn("/srv/devman");
 	spawn("/srv/apic");
 	spawn("/srv/i8259");
-	spawn("/srv/fhc");
 	spawn("/srv/obio");
 	srv_start("/srv/cuda_adb");
 	srv_start("/srv/i8042");
 	srv_start("/srv/s3c24ser");
-	srv_start("/srv/adb_ms");
-	srv_start("/srv/char_ms");
 	srv_start("/srv/s3c24ts");
 	
 	spawn("/srv/fb");
-	spawn("/srv/kbd");
-	console("hid_in/kbd");
+	spawn("/srv/input");
+	console("hid/input");
 	
 	spawn("/srv/clip");
@@ -301,4 +316,8 @@
 	
 #ifdef CONFIG_MOUNT_DATA
+	/* Make sure fat is running. */
+	if (str_cmp(STRING(RDFMT), "fat") != 0) {
+		srv_start("/srv/fat");
+	}
 	mount_data();
 #else
Index: uspace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/klog/klog.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,7 +44,20 @@
 #include <io/klog.h>
 #include <sysinfo.h>
+#include <malloc.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <adt/prodcons.h>
 
 #define NAME       "klog"
 #define LOG_FNAME  "/log/klog"
+
+/* Producer/consumer buffers */
+typedef struct {
+	link_t link;
+	size_t length;
+	wchar_t *data;
+} item_t;
+
+static prodcons_t pc;
 
 /* Pointer to klog area */
@@ -52,26 +65,121 @@
 static size_t klog_length;
 
-static FILE *log;
-
-static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
-{
+/* Notification mutex */
+static FIBRIL_MUTEX_INITIALIZE(mtx);
+
+/** Klog producer
+ *
+ * Copies the contents of a character buffer to local
+ * producer/consumer queue.
+ *
+ * @param length Number of characters to copy.
+ * @param data   Pointer to the kernel klog buffer.
+ *
+ */
+static void producer(size_t length, wchar_t *data)
+{
+	item_t *item = (item_t *) malloc(sizeof(item_t));
+	if (item == NULL)
+		return;
+	
+	size_t sz = sizeof(wchar_t) * length;
+	wchar_t *buf = (wchar_t *) malloc(sz);
+	if (data == NULL) {
+		free(item);
+		return;
+	}
+	
+	memcpy(buf, data, sz);
+	
+	link_initialize(&item->link);
+	item->length = length;
+	item->data = buf;
+	prodcons_produce(&pc, &item->link);
+}
+
+/** Klog consumer
+ *
+ * Waits in an infinite loop for the character data created by
+ * the producer and outputs them to stdout and optionally into
+ * a file.
+ *
+ * @param data Unused.
+ *
+ * @return Always EOK (unreachable).
+ *
+ */
+static int consumer(void *data)
+{
+	FILE *log = fopen(LOG_FNAME, "a");
+	if (log == NULL)
+		printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,
+		    str_error(errno));
+	
+	while (true) {
+		link_t *link = prodcons_consume(&pc);
+		item_t *item = list_get_instance(link, item_t, link);
+		
+		for (size_t i = 0; i < item->length; i++)
+			putchar(item->data[i]);
+		
+		if (log != NULL) {
+			for (size_t i = 0; i < item->length; i++)
+				fputc(item->data[i], log);
+			
+			fflush(log);
+			fsync(fileno(log));
+		}
+		
+		free(item->data);
+		free(item);
+	}
+	
+	fclose(log);
+	return EOK;
+}
+
+/** Kernel notification handler
+ *
+ * Receives kernel klog notifications.
+ *
+ * @param callid IPC call ID
+ * @param call   IPC call structure
+ * @param arg    Local argument
+ *
+ */
+static void notification_received(ipc_callid_t callid, ipc_call_t *call)
+{
+	/*
+	 * Make sure we process only a single notification
+	 * at any time to limit the chance of the consumer
+	 * starving.
+	 *
+	 * Note: Usually the automatic masking of the klog
+	 * notifications on the kernel side does the trick
+	 * of limiting the chance of accidentally copying
+	 * the same data multiple times. However, due to
+	 * the non-blocking architecture of klog notifications,
+	 * this possibility cannot be generally avoided.
+	 */
+	
+	fibril_mutex_lock(&mtx);
+	
 	size_t klog_start = (size_t) IPC_GET_ARG1(*call);
 	size_t klog_len = (size_t) IPC_GET_ARG2(*call);
 	size_t klog_stored = (size_t) IPC_GET_ARG3(*call);
-	size_t i;
-	
-	for (i = klog_len - klog_stored; i < klog_len; i++) {
-		wchar_t ch = klog[(klog_start + i) % klog_length];
-		
-		putchar(ch);
-		
-		if (log != NULL)
-			fputc(ch, log);
-	}
-	
-	if (log != NULL) {
-		fflush(log);
-		fsync(fileno(log));
-	}
+	
+	size_t offset = (klog_start + klog_len - klog_stored) % klog_length;
+	
+	/* Copy data from the ring buffer */
+	if (offset + klog_stored >= klog_length) {
+		size_t split = klog_length - offset;
+		
+		producer(split, klog + offset);
+		producer(klog_stored - split, klog);
+	} else
+		producer(klog_stored, klog + offset);
+	
+	event_unmask(EVENT_KLOG);
+	fibril_mutex_unlock(&mtx);
 }
 
@@ -111,4 +219,6 @@
 	}
 	
+	prodcons_initialize(&pc);
+	async_set_interrupt_received(notification_received);
 	rc = event_subscribe(EVENT_KLOG, 0);
 	if (rc != EOK) {
@@ -118,15 +228,16 @@
 	}
 	
-	/*
-	 * Mode "a" would be definitively much better here, but it is
-	 * not well supported by the FAT driver.
-	 */
-	log = fopen(LOG_FNAME, "w");
-	if (log == NULL)
-		printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,
-		    str_error(errno));
-	
-	async_set_interrupt_received(interrupt_received);
+	fid_t fid = fibril_create(consumer, NULL);
+	if (!fid) {
+		fprintf(stderr, "%s: Unable to create consumer fibril\n",
+		    NAME);
+		return ENOMEM;
+	}
+	
+	fibril_add_ready(fid);
+	event_unmask(EVENT_KLOG);
 	klog_update();
+	
+	task_retval(0);
 	async_manager();
 	
Index: uspace/app/locinfo/Makefile
===================================================================
--- uspace/app/locinfo/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/locinfo/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2011 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+EXTRA_CFLAGS = -Iinclude
+BINARY = locinfo
+
+SOURCES = \
+	locinfo.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/locinfo/locinfo.c
===================================================================
--- uspace/app/locinfo/locinfo.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/locinfo/locinfo.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup locinfo
+ * @{
+ */
+/** @file locinfo.c Print information from location service.
+ */
+
+#include <errno.h>
+#include <loc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+#include <sys/types.h>
+#include <sys/typefmt.h>
+
+#define NAME "locinfo"
+
+int main(int argc, char *argv[])
+{
+	category_id_t *cat_ids;
+	size_t cat_cnt;
+	service_id_t *svc_ids;
+	size_t svc_cnt;
+
+	size_t i, j;
+	char *cat_name;
+	char *svc_name;
+	int rc;
+
+	rc = loc_get_categories(&cat_ids, &cat_cnt);
+	if (rc != EOK) {
+		printf(NAME ": Error getting list of categories.\n");
+		return 1;
+	}
+
+	for (i = 0; i < cat_cnt; i++) {
+		rc = loc_category_get_name(cat_ids[i], &cat_name);
+		if (rc != EOK)
+			cat_name = str_dup("<unknown>");
+
+		if (cat_name == NULL) {
+			printf(NAME ": Error allocating memory.\n");
+			return 1;
+		}
+
+		printf("%s (%" PRIun "):\n", cat_name, cat_ids[i]);
+
+		rc = loc_category_get_svcs(cat_ids[i], &svc_ids, &svc_cnt);
+		if (rc != EOK) {
+			printf(NAME ": Failed getting list of services in "
+			    "category %s, skipping.\n", cat_name);
+			free(cat_name);
+			continue;
+		}
+
+		for (j = 0; j < svc_cnt; j++) {
+			rc = loc_service_get_name(svc_ids[j], &svc_name);
+			if (rc != EOK) {
+				printf(NAME ": Unknown service name (SID %"
+				    PRIun ").\n", svc_ids[j]);
+				continue;
+			}
+			printf("\t%s (%" PRIun ")\n", svc_name, svc_ids[j]);
+		}
+
+		free(svc_ids);
+		free(cat_name);
+	}
+
+	free(cat_ids);
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/lsusb/Makefile
===================================================================
--- uspace/app/lsusb/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/lsusb/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+BINARY = lsusb
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS = \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+SOURCES = \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/lsusb/main.c
===================================================================
--- uspace/app/lsusb/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/lsusb/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2010-2011 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 lsusb
+ * @{
+ */
+/**
+ * @file
+ * Listing of USB host controllers.
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+#include <getopt.h>
+#include <devman.h>
+#include <loc.h>
+#include <usb/dev/hub.h>
+#include <usb/hc.h>
+
+#define NAME "lsusb"
+
+#define MAX_USB_ADDRESS USB11_ADDRESS_MAX
+#define MAX_PATH_LENGTH 1024
+
+static void print_found_hc(service_id_t sid, const char *path)
+{
+	printf("Bus %" PRIun ": %s\n", sid, path);
+}
+static void print_found_dev(usb_address_t addr, const char *path)
+{
+	printf("  Device %02d: %s\n", addr, path);
+}
+
+static void print_hc_devices(devman_handle_t hc_handle)
+{
+	int rc;
+	usb_hc_connection_t conn;
+
+	usb_hc_connection_initialize(&conn, hc_handle);
+	rc = usb_hc_connection_open(&conn);
+	if (rc != EOK) {
+		printf(NAME ": failed to connect to HC: %s.\n",
+		    str_error(rc));
+		return;
+	}
+	usb_address_t addr;
+	for (addr = 1; addr < MAX_USB_ADDRESS; addr++) {
+		devman_handle_t dev_handle;
+		rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
+		if (rc != EOK) {
+			continue;
+		}
+		char path[MAX_PATH_LENGTH];
+		rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
+		if (rc != EOK) {
+			continue;
+		}
+		print_found_dev(addr, path);
+	}
+	usb_hc_connection_close(&conn);
+}
+
+int main(int argc, char *argv[])
+{
+	category_id_t usbhc_cat;
+	service_id_t *svcs;
+	size_t count;
+	size_t i;
+	int rc;
+
+	rc = loc_category_get_id(USB_HC_CATEGORY, &usbhc_cat, 0);
+	if (rc != EOK) {
+		printf(NAME ": Error resolving category '%s'",
+		    USB_HC_CATEGORY);
+		return 1;
+	}
+
+	rc = loc_category_get_svcs(usbhc_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf(NAME ": Error getting list of host controllers.\n");
+		return 1;
+	}
+
+	for (i = 0; i < count; i++) {
+		devman_handle_t hc_handle = 0;
+		int rc = usb_ddf_get_hc_handle_by_sid(svcs[i], &hc_handle);
+		if (rc != EOK) {
+			printf(NAME ": Error resolving handle of HC with SID %"
+			    PRIun ", skipping.\n", svcs[i]);
+			continue;
+		}
+		char path[MAX_PATH_LENGTH];
+		rc = devman_fun_get_path(hc_handle, path, MAX_PATH_LENGTH);
+		if (rc != EOK) {
+			printf(NAME ": Error resolving path of HC with SID %"
+			    PRIun ", skipping.\n", svcs[i]);
+			continue;
+		}
+		print_found_hc(svcs[i], path);
+		print_hc_devices(hc_handle);
+	}
+
+	free(svcs);
+
+	return 0;
+}
+
+
+/** @}
+ */
Index: uspace/app/mkbd/Makefile
===================================================================
--- uspace/app/mkbd/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/mkbd/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+BINARY = mkbd
+
+LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a 
+EXTRA_CFLAGS = \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include 
+
+SOURCES = \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/mkbd/main.c
===================================================================
--- uspace/app/mkbd/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/mkbd/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 mkbd
+ * @{
+ */
+/**
+ * @file
+ * Sample application using the data from multimedia keys on keyboard
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+#include <getopt.h>
+#include <devman.h>
+#include <loc.h>
+#include <usb/dev/hub.h>
+#include <usb/hid/iface.h>
+#include <usb/dev/pipes.h>
+#include <async.h>
+#include <usb/hid/usages/core.h>
+#include <usb/hid/hidparser.h>
+#include <usb/hid/hiddescriptor.h>
+#include <usb/hid/usages/consumer.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <assert.h>
+
+#define NAME "mkbd"
+
+static async_sess_t *dev_sess = NULL;
+
+static int initialize_report_parser(async_sess_t *dev_sess,
+    usb_hid_report_t **report)
+{
+	*report = (usb_hid_report_t *) malloc(sizeof(usb_hid_report_t));
+	if (*report == NULL)
+		return ENOMEM;
+	
+	int rc = usb_hid_report_init(*report);
+	if (rc != EOK) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		return rc;
+	}
+	
+	/* Get the report descriptor length from the device */
+	size_t report_desc_size;
+	rc = usbhid_dev_get_report_descriptor_length(dev_sess,
+	    &report_desc_size);
+	if (rc != EOK) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		return rc;
+	}
+	
+	if (report_desc_size == 0) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		// TODO: other error code?
+		return EINVAL;
+	}
+	
+	uint8_t *desc = (uint8_t *) malloc(report_desc_size);
+	if (desc == NULL) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		return ENOMEM;
+	}
+	
+	/* Get the report descriptor from the device */
+	size_t actual_size;
+	rc = usbhid_dev_get_report_descriptor(dev_sess, desc, report_desc_size,
+	    &actual_size);
+	if (rc != EOK) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		free(desc);
+		return rc;
+	}
+	
+	if (actual_size != report_desc_size) {
+		usb_hid_free_report(*report);
+		*report = NULL;
+		free(desc);
+		// TODO: other error code?
+		return EINVAL;
+	}
+	
+	/* Initialize the report parser */
+	
+	rc = usb_hid_parse_report_descriptor(*report, desc, report_desc_size);
+	free(desc);
+	
+	if (rc != EOK) {
+		free(desc);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+static void print_key(uint8_t *buffer, size_t size, usb_hid_report_t *report)
+{
+	assert(buffer != NULL);
+	assert(report != NULL);
+	
+	uint8_t report_id;
+	int rc = usb_hid_parse_report(report, buffer, size, &report_id);
+	if (rc != EOK)
+		return;
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	if (path == NULL) {
+		return;
+	}
+	
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
+	
+	usb_hid_report_path_set_report_id(path, report_id);
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    report, NULL, path, USB_HID_PATH_COMPARE_END
+	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+	    USB_HID_REPORT_TYPE_INPUT);
+	
+	while (field != NULL) {
+		if (field->value != 0) {
+			const char *key_str = 
+			    usbhid_multimedia_usage_to_str(field->usage);
+			printf("Pressed key: %s\n", key_str);
+		}
+		
+		field = usb_hid_report_get_sibling(
+		    report, field, path, USB_HID_PATH_COMPARE_END
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}
+	
+	usb_hid_report_path_free(path);
+}
+
+static int wait_for_quit_fibril(void *arg)
+{
+	console_ctrl_t *con = console_init(stdin, stdout);
+
+	printf("Press <ESC> to quit the application.\n");
+
+	while (1) {
+		kbd_event_t ev;
+		bool ok = console_get_kbd_event(con, &ev);
+		if (!ok) {
+			printf("Connection with console broken: %s.\n",
+			    str_error(errno));
+			break;
+		}
+
+		if (ev.key == KC_ESCAPE) {
+			break;
+		}
+	}
+
+	console_done(con);
+
+	exit(0);
+
+	return EOK;
+}
+
+#define MAX_PATH_LENGTH 1024
+
+static void print_usage(char *app_name)
+{
+#define _INDENT "      "
+	printf(NAME ": Print out what multimedia keys were pressed.\n\n");
+	printf("Usage: %s device\n", app_name);
+	printf(_INDENT "The device is a devman path to the device.\n");
+#undef _OPTION
+#undef _INDENT
+}
+
+int main(int argc, char *argv[])
+{
+	int act_event = -1;
+	
+	if (argc <= 1) {
+		print_usage(argv[0]);
+		return -1;
+	}
+	
+	char *devpath = argv[1];
+	
+	devman_handle_t dev_handle = 0;
+	
+	int rc = usb_resolve_device_handle(devpath, NULL, NULL, &dev_handle);
+	if (rc != EOK) {
+		printf("Device not found or not of USB kind: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	async_sess_t *sess = devman_device_connect(EXCHANGE_SERIALIZE,
+	    dev_handle, 0);
+	if (!sess) {
+		printf(NAME ": failed to connect to the device (handle %"
+		       PRIun "): %s.\n", dev_handle, str_error(errno));
+		return errno;
+	}
+	
+	dev_sess = sess;
+	
+	char path[MAX_PATH_LENGTH];
+	rc = devman_fun_get_path(dev_handle, path, MAX_PATH_LENGTH);
+	if (rc != EOK) {
+		return ENOMEM;
+	}
+	
+	printf("Device path: %s\n", path);
+	
+	
+	usb_hid_report_t *report = NULL;
+	rc = initialize_report_parser(dev_sess, &report);
+	if (rc != EOK) {
+		printf("Failed to initialize report parser: %s\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	assert(report != NULL);
+	
+	size_t size;
+	rc = usbhid_dev_get_event_length(dev_sess, &size);
+	if (rc != EOK) {
+		printf("Failed to get event length: %s.\n", str_error(rc));
+		return rc;
+	}
+	
+	uint8_t *event = (uint8_t *)malloc(size);
+	if (event == NULL) {
+		// TODO: hangup phone?
+		return ENOMEM;
+	}
+	
+	fid_t quit_fibril = fibril_create(wait_for_quit_fibril, NULL);
+	if (quit_fibril == 0) {
+		printf("Failed to start extra fibril.\n");
+		return -1;
+	}
+	fibril_add_ready(quit_fibril);
+
+	size_t actual_size;
+	int event_nr;
+	
+	while (true) {
+		/** @todo Try blocking call. */
+		rc = usbhid_dev_get_event(dev_sess, event, size, &actual_size, 
+		    &event_nr, 0);
+		if (rc != EOK) {
+			// TODO: hangup phone?
+			printf("Error in getting event from the HID driver:"
+			    "%s.\n", str_error(rc));
+			break;
+		}
+		
+		if (event_nr > act_event) {
+			print_key(event, size, report);
+			act_event = event_nr;
+		}
+		
+		async_usleep(10000);
+	}
+	
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/mkfat/mkfat.c
===================================================================
--- uspace/app/mkfat/mkfat.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/mkfat/mkfat.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,5 +42,5 @@
 #include <libblock.h>
 #include <mem.h>
-#include <devmap.h>
+#include <loc.h>
 #include <byteorder.h>
 #include <sys/types.h>
@@ -85,5 +85,5 @@
     struct fat_params *par);
 static int fat_blocks_write(struct fat_params const *par,
-    devmap_handle_t handle);
+    service_id_t service_id);
 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs);
 
@@ -95,5 +95,5 @@
 	int rc;
 	char *dev_path;
-	devmap_handle_t handle;
+	service_id_t service_id;
 	size_t block_size;
 	char *endptr;
@@ -138,5 +138,5 @@
 	dev_path = *argv;
 
-	rc = devmap_device_get_handle(dev_path, &handle, 0);
+	rc = loc_service_get_id(dev_path, &service_id, 0);
 	if (rc != EOK) {
 		printf(NAME ": Error resolving device `%s'.\n", dev_path);
@@ -144,5 +144,5 @@
 	}
 
-	rc = block_init(handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": Error initializing libblock.\n");
@@ -150,5 +150,5 @@
 	}
 
-	rc = block_get_bsize(handle, &block_size);
+	rc = block_get_bsize(service_id, &block_size);
 	if (rc != EOK) {
 		printf(NAME ": Error determining device block size.\n");
@@ -156,5 +156,5 @@
 	}
 
-	rc = block_get_nblocks(handle, &dev_nblocks);
+	rc = block_get_nblocks(service_id, &dev_nblocks);
 	if (rc != EOK) {
 		printf(NAME ": Warning, failed to obtain block device size.\n");
@@ -183,5 +183,5 @@
 	}
 
-	rc = fat_blocks_write(&par, handle);
+	rc = fat_blocks_write(&par, service_id);
 	if (rc != EOK) {
 		printf(NAME ": Error writing device.\n");
@@ -189,5 +189,5 @@
 	}
 
-	block_fini(handle);
+	block_fini(service_id);
 	printf("Success.\n");
 
@@ -234,5 +234,5 @@
 
 /** Create file system with the given parameters. */
-static int fat_blocks_write(struct fat_params const *par, devmap_handle_t handle)
+static int fat_blocks_write(struct fat_params const *par, service_id_t service_id)
 {
 	aoff64_t addr;
@@ -245,5 +245,5 @@
 	fat_bootsec_create(par, &bs);
 
-	rc = block_write_direct(handle, BS_BLOCK, 1, &bs);
+	rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
 	if (rc != EOK)
 		return EIO;
@@ -257,5 +257,5 @@
 	/* Reserved sectors */
 	for (i = 0; i < par->reserved_sectors - 1; ++i) {
-		rc = block_write_direct(handle, addr, 1, buffer);
+		rc = block_write_direct(service_id, addr, 1, buffer);
 		if (rc != EOK)
 			return EIO;
@@ -277,5 +277,5 @@
 			}
 
-			rc = block_write_direct(handle, addr, 1, buffer);
+			rc = block_write_direct(service_id, addr, 1, buffer);
 			if (rc != EOK)
 				return EIO;
@@ -291,5 +291,5 @@
 	/* Root directory */
 	for (i = 0; i < par->rootdir_sectors; ++i) {
-		rc = block_write_direct(handle, addr, 1, buffer);
+		rc = block_write_direct(service_id, addr, 1, buffer);
 		if (rc != EOK)
 			return EIO;
Index: uspace/app/ping/ping.c
===================================================================
--- uspace/app/ping/ping.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/ping/ping.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -340,9 +340,9 @@
 	    config.dest_str, config.size, config.size);
 	
-	int icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
-	if (icmp_phone < 0) {
+	async_sess_t *sess = icmp_connect_module();
+	if (!sess) {
 		fprintf(stderr, "%s: Unable to connect to ICMP service (%s)\n", NAME,
-		    str_error(icmp_phone));
-		return icmp_phone;
+		    str_error(errno));
+		return errno;
 	}
 	
@@ -355,10 +355,10 @@
 			    str_error(ret));
 			
-			async_hangup(icmp_phone);
+			async_hangup(sess);
 			return ret;
 		}
 		
 		/* Ping! */
-		int result = icmp_echo_msg(icmp_phone, config.size, config.timeout,
+		int result = icmp_echo_msg(sess, config.size, config.timeout,
 		    config.ttl, config.tos, !config.fragments, config.dest_raw,
 		    config.dest_len);
@@ -370,5 +370,5 @@
 			    str_error(ret));
 			
-			async_hangup(icmp_phone);
+			async_hangup(sess);
 			return ret;
 		}
@@ -390,5 +390,5 @@
 	}
 	
-	async_hangup(icmp_phone);
+	async_hangup(sess);
 	
 	return 0;
Index: uspace/app/redir/redir.c
===================================================================
--- uspace/app/redir/redir.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/redir/redir.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -49,5 +49,5 @@
 static void usage(void)
 {
-	printf("Usage: %s [-i <stdin>] [-o <stdout>] [-e <stderr>] -- <cmd> [args ...]\n",
+	fprintf(stderr, "Usage: %s [-i <stdin>] [-o <stdout>] [-e <stderr>] -- <cmd> [args ...]\n",
 	    NAME);
 }
@@ -83,5 +83,5 @@
 	args = (const char **) calloc(argc + 1, sizeof(char *));
 	if (!args) {
-		printf("No memory available\n");
+		fprintf(stderr, "No memory available\n");
 		return 0;
 	}
@@ -98,6 +98,7 @@
 	
 	if (rc != EOK) {
-		printf("%s: Error spawning %s (%s)\n", NAME, argv[0],
+		fprintf(stderr, "%s: Error spawning %s (%s)\n", NAME, argv[0],
 		    str_error(rc));
+		return 0;
 	}
 	
Index: uspace/app/sbi/src/compat.h
===================================================================
--- uspace/app/sbi/src/compat.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/sbi/src/compat.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,7 @@
 #ifdef __HELENOS__
 
+#define list sbi_list
+#define list_t sbi_list_t
+
 /*
  * Avoid name conflicts with ADT library.
@@ -44,4 +47,6 @@
 #define list_prepend sbi_list_prepend
 #define list_remove sbi_list_remove
+#define list_first sbi_list_first
+#define list_last sbi_list_last
 
 #endif
Index: uspace/app/sbi/src/input.c
===================================================================
--- uspace/app/sbi/src/input.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/sbi/src/input.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -176,4 +176,5 @@
 int input_get_line(input_t *input, char **line)
 {
+	const char *prompt;
 	const char *sp;
 	char *dp;
@@ -212,10 +213,10 @@
 		/* Interactive mode */
 		if (input->line_no == 0)
-			printf("sbi> ");
+			prompt = "sbi> ";
 		else
-			printf("...  ");
+			prompt = "...  ";
 
 		fflush(stdout);
-		if (os_input_line(&line_p) != EOK)
+		if (os_input_line(prompt, &line_p) != EOK)
 			return EIO;
 
Index: uspace/app/sbi/src/list_t.h
===================================================================
--- uspace/app/sbi/src/list_t.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/sbi/src/list_t.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,4 +30,6 @@
 #define LIST_T_H_
 
+#include "compat.h"
+
 typedef struct list_node {
 	struct list_node *prev, *next;
Index: uspace/app/sbi/src/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/sbi/src/os/helenos.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -210,5 +210,5 @@
  * @param ptr	Place to store pointer to new string.
  */
-int os_input_line(char **ptr)
+int os_input_line(const char *prompt, char **ptr)
 {
 	char *line;
@@ -219,4 +219,6 @@
 		if (tinput == NULL)
 			return EIO;
+
+		tinput_set_prompt(tinput, prompt);
 	}
 
Index: uspace/app/sbi/src/os/os.h
===================================================================
--- uspace/app/sbi/src/os/os.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/sbi/src/os/os.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 char *os_chr_to_astr(wchar_t chr);
 void os_input_disp_help(void);
-int os_input_line(char **ptr);
+int os_input_line(const char *prompt, char **ptr);
 int os_exec(char * const cmd[]);
 
Index: uspace/app/sbi/src/os/posix.c
===================================================================
--- uspace/app/sbi/src/os/posix.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/sbi/src/os/posix.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -193,6 +193,8 @@
  * @param ptr	Place to store pointer to new string.
  */
-int os_input_line(char **ptr)
-{
+int os_input_line(const char *prompt, char **ptr)
+{
+	printf("%s", prompt);
+
 	if (fgets(os_input_buffer, OS_INPUT_BUFFER_SIZE, stdin) == NULL)
 		os_input_buffer[0] = '\0';
Index: uspace/app/sbi/src/run_expr.c
===================================================================
--- uspace/app/sbi/src/run_expr.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/sbi/src/run_expr.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -2529,4 +2529,6 @@
 	if (rc1 == EOK)
 		rc2 = os_str_get_char(string->value, elem_index, &cval);
+	else
+		rc2 = EOK;
 
 	if (rc1 != EOK || rc2 != EOK) {
Index: uspace/app/stats/stats.c
===================================================================
--- uspace/app/stats/stats.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/stats/stats.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -69,13 +69,19 @@
 	size_t i;
 	for (i = 0; i < count; i++) {
-		uint64_t resmem, virtmem, ucycles, kcycles;
-		char resmem_suffix, virtmem_suffix, usuffix, ksuffix;
-		
-		order_suffix(stats_tasks[i].resmem, &resmem, &resmem_suffix);
-		order_suffix(stats_tasks[i].virtmem, &virtmem, &virtmem_suffix);
+		uint64_t resmem;
+		uint64_t virtmem;
+		uint64_t ucycles;
+		uint64_t kcycles;
+		const char *resmem_suffix;
+		const char *virtmem_suffix;
+		char usuffix;
+		char ksuffix;
+		
+		bin_order_suffix(stats_tasks[i].resmem, &resmem, &resmem_suffix, true);
+		bin_order_suffix(stats_tasks[i].virtmem, &virtmem, &virtmem_suffix, true);
 		order_suffix(stats_tasks[i].ucycles, &ucycles, &usuffix);
 		order_suffix(stats_tasks[i].kcycles, &kcycles, &ksuffix);
 		
-		printf("%-8" PRIu64 " %7zu %9" PRIu64 "%c %8" PRIu64 "%c"
+		printf("%-8" PRIu64 " %7zu %7" PRIu64 "%s %6" PRIu64 "%s"
 		    " %8" PRIu64 "%c %8" PRIu64 "%c %s\n",
 		    stats_tasks[i].task_id, stats_tasks[i].threads,
Index: uspace/app/taskdump/elf_core.c
===================================================================
--- uspace/app/taskdump/elf_core.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/taskdump/elf_core.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -38,12 +38,16 @@
  * Looking at core files produced by Linux, these don't have section headers,
  * only program headers, although objdump shows them as having sections.
- * Basically at the beginning there should be a note segment (which we
- * do not write) and one loadable segment per memory area (which we do write).
- *
- * The note segment probably contains register state, etc. -- we don't
- * deal with these yet. Nevertheless you can use these core files with
- * objdump or gdb.
- */
-
+ * Basically at the beginning there should be a note segment followed
+ * by one loadable segment per memory area.
+ *
+ * The note segment contains a series of records with register state,
+ * process info etc. We only write one record NT_PRSTATUS which contains
+ * process/register state (anything which is not register state we fill
+ * with zeroes).
+ */
+
+#include <align.h>
+#include <elf/elf.h>
+#include <elf/elf_linux.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -58,11 +62,11 @@
 #include <udebug.h>
 #include <macros.h>
-
-#include <elf.h>
-#include "include/elf_core.h"
-
-static off64_t align_foff_up(off64_t foff, uintptr_t vaddr, size_t page_size);
-static int write_all(int fd, void *data, size_t len);
-static int write_mem_area(int fd, as_area_info_t *area, int phoneid);
+#include <libarch/istate.h>
+
+#include "elf_core.h"
+
+static off64_t align_foff_up(off64_t, uintptr_t, size_t);
+static int align_pos(int, size_t);
+static int write_mem_area(int, as_area_info_t *, async_sess_t *);
 
 #define BUFFER_SIZE 0x1000
@@ -71,13 +75,17 @@
 /** Save ELF core file.
  *
- * @param file_name	Name of file to save to.
- * @param ainfo		Array of @a n memory area info structures.
- * @param n		Number of memory areas.
- * @param phoneid	Debugging phone.
- *
- * @return		EOK on sucess, ENOENT if file cannot be created,
- *			ENOMEM on out of memory, EIO on write error.
- */
-int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n, int phoneid)
+ * @param file_name Name of file to save to.
+ * @param ainfo     Array of @a n memory area info structures.
+ * @param n         Number of memory areas.
+ * @param sess      Debugging session.
+ *
+ * @return EOK on sucess.
+ * @return ENOENT if file cannot be created.
+ * @return ENOMEM on out of memory.
+ * @return EIO on write error.
+ *
+ */
+int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n,
+    async_sess_t *sess, istate_t *istate)
 {
 	elf_header_t elf_hdr;
@@ -86,12 +94,29 @@
 	elf_word flags;
 	elf_segment_header_t *p_hdr;
+	elf_prstatus_t pr_status;
+	elf_note_t note;
+	size_t word_size;
 
 	int fd;
-	int rc;
+	ssize_t rc;
 	unsigned int i;
 
-	n_ph = n;
-
-	p_hdr = malloc(sizeof(elf_segment_header_t) * n);
+#ifdef __32_BITS__
+	word_size = 4;
+#endif
+#ifdef __64_BITS__
+	/*
+	 * This should be 8 per the 64-bit ELF spec, but the Linux kernel
+	 * screws up and uses 4 anyway (and screws up elf_note_t as well)
+	 * and we are trying to be compatible with Linux GDB target. Sigh.
+	 */
+	word_size = 4;
+#endif
+	memset(&pr_status, 0, sizeof(pr_status));
+	istate_to_elf_regs(istate, &pr_status.regs);
+
+	n_ph = n + 1;
+
+	p_hdr = malloc(sizeof(elf_segment_header_t) * n_ph);
 	if (p_hdr == NULL) {
 		printf("Failed allocating memory.\n");
@@ -111,7 +136,8 @@
 	 * 	ELF header
 	 *	program headers
+	 *	note segment
 	 * repeat:
 	 *	(pad for alignment)
-	 *	segment data
+	 *	core segment
 	 * end repeat
 	 */
@@ -143,30 +169,44 @@
 	foff = elf_hdr.e_phoff + n_ph * sizeof(elf_segment_header_t);
 
-	for (i = 1; i <= n; ++i) {
-		foff = align_foff_up(foff, ainfo[i - 1].start_addr, PAGE_SIZE);
+	memset(&p_hdr[0], 0, sizeof(p_hdr[0]));
+	p_hdr[0].p_type = PT_NOTE;
+	p_hdr[0].p_offset = foff;
+	p_hdr[0].p_vaddr = 0;
+	p_hdr[0].p_paddr = 0;
+	p_hdr[0].p_filesz = sizeof(elf_note_t)
+	    + ALIGN_UP((str_size("CORE") + 1), word_size)
+	    + ALIGN_UP(sizeof(elf_prstatus_t), word_size);
+	p_hdr[0].p_memsz = 0;
+	p_hdr[0].p_flags = 0;
+	p_hdr[0].p_align = 1;
+
+	foff += p_hdr[0].p_filesz;
+
+	for (i = 0; i < n; ++i) {
+		foff = align_foff_up(foff, ainfo[i].start_addr, PAGE_SIZE);
 
 		flags = 0;
-		if (ainfo[i - 1].flags & AS_AREA_READ)
+		if (ainfo[i].flags & AS_AREA_READ)
 			flags |= PF_R;
-		if (ainfo[i - 1].flags & AS_AREA_WRITE)
+		if (ainfo[i].flags & AS_AREA_WRITE)
 			flags |= PF_W;
-		if (ainfo[i - 1].flags & AS_AREA_EXEC)
+		if (ainfo[i].flags & AS_AREA_EXEC)
 			flags |= PF_X;
 
-		memset(&p_hdr[i - 1], 0, sizeof(p_hdr[i - 1]));
-		p_hdr[i - 1].p_type = PT_LOAD;
-		p_hdr[i - 1].p_offset = foff;
-		p_hdr[i - 1].p_vaddr = ainfo[i - 1].start_addr;
-		p_hdr[i - 1].p_paddr = 0;
-		p_hdr[i - 1].p_filesz = ainfo[i - 1].size;
-		p_hdr[i - 1].p_memsz = ainfo[i - 1].size;
-		p_hdr[i - 1].p_flags = flags;
-		p_hdr[i - 1].p_align = PAGE_SIZE;
-
-		foff += ainfo[i - 1].size;
+		memset(&p_hdr[i + 1], 0, sizeof(p_hdr[i + 1]));
+		p_hdr[i + 1].p_type = PT_LOAD;
+		p_hdr[i + 1].p_offset = foff;
+		p_hdr[i + 1].p_vaddr = ainfo[i].start_addr;
+		p_hdr[i + 1].p_paddr = 0;
+		p_hdr[i + 1].p_filesz = ainfo[i].size;
+		p_hdr[i + 1].p_memsz = ainfo[i].size;
+		p_hdr[i + 1].p_flags = flags;
+		p_hdr[i + 1].p_align = PAGE_SIZE;
+
+		foff += ainfo[i].size;
 	}
 
 	rc = write_all(fd, &elf_hdr, sizeof(elf_hdr));
-	if (rc != EOK) {
+	if (rc != sizeof(elf_hdr)) {
 		printf("Failed writing ELF header.\n");
 		free(p_hdr);
@@ -176,5 +216,5 @@
 	for (i = 0; i < n_ph; ++i) {
 		rc = write_all(fd, &p_hdr[i], sizeof(p_hdr[i]));
-		if (rc != EOK) {
+		if (rc != sizeof(p_hdr[i])) {
 			printf("Failed writing program header.\n");
 			free(p_hdr);
@@ -183,5 +223,46 @@
 	}
 
-	for (i = 0; i < n_ph; ++i) {
+	if (lseek(fd, p_hdr[0].p_offset, SEEK_SET) == (off64_t) -1) {
+		printf("Failed writing memory data.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	/*
+	 * Write note header
+	 */
+	note.namesz = str_size("CORE") + 1;
+	note.descsz = sizeof(elf_prstatus_t);
+	note.type = NT_PRSTATUS;
+
+	rc = write_all(fd, &note, sizeof(elf_note_t));
+	if (rc != sizeof(elf_note_t)) {
+		printf("Failed writing note header.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	rc = write_all(fd, "CORE", note.namesz);
+	if (rc != (ssize_t) note.namesz) {
+		printf("Failed writing note header.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	rc = align_pos(fd, word_size);
+	if (rc != EOK) {
+		printf("Failed writing note header.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	rc = write_all(fd, &pr_status, sizeof(elf_prstatus_t));
+	if (rc != sizeof(elf_prstatus_t)) {
+		printf("Failed writing register data.\n");
+		free(p_hdr);
+		return EIO;
+	}
+
+	for (i = 1; i < n_ph; ++i) {
 		if (lseek(fd, p_hdr[i].p_offset, SEEK_SET) == (off64_t) -1) {
 			printf("Failed writing memory data.\n");
@@ -189,5 +270,5 @@
 			return EIO;
 		}
-		if (write_mem_area(fd, &ainfo[i], phoneid) != EOK) {
+		if (write_mem_area(fd, &ainfo[i - 1], sess) != EOK) {
 			printf("Failed writing memory data.\n");
 			free(p_hdr);
@@ -206,8 +287,8 @@
 	off64_t rva = vaddr % page_size;
 	off64_t rfo = foff % page_size;
-	
+
 	if (rva >= rfo)
 		return (foff + (rva - rfo));
-	
+
 	return (foff + (page_size + (rva - rfo)));
 }
@@ -215,16 +296,17 @@
 /** Write memory area from application to core file.
  *
- * @param fd		File to write to.
- * @param area		Memory area info structure.
- * @param phoneid	Debugging phone.
- *
- * @return		EOK on success, EIO on failure.
- */
-static int write_mem_area(int fd, as_area_info_t *area, int phoneid)
+ * @param fd   File to write to.
+ * @param area Memory area info structure.
+ * @param sess Debugging session.
+ *
+ * @return EOK on success, EIO on failure.
+ *
+ */
+static int write_mem_area(int fd, as_area_info_t *area, async_sess_t *sess)
 {
 	size_t to_copy;
 	size_t total;
 	uintptr_t addr;
-	int rc;
+	ssize_t rc;
 
 	addr = area->start_addr;
@@ -233,5 +315,5 @@
 	while (total < area->size) {
 		to_copy = min(area->size - total, BUFFER_SIZE);
-		rc = udebug_mem_read(phoneid, buffer, addr, to_copy);
+		rc = udebug_mem_read(sess, buffer, addr, to_copy);
 		if (rc < 0) {
 			printf("Failed reading task memory.\n");
@@ -240,5 +322,5 @@
 
 		rc = write_all(fd, buffer, to_copy);
-		if (rc != EOK) {
+		if (rc != (ssize_t) to_copy) {
 			printf("Failed writing memory contents.\n");
 			return EIO;
@@ -252,35 +334,23 @@
 }
 
-/** Write until the buffer is written in its entirety.
- *
- * This function fails if it cannot write exactly @a len bytes to the file.
- *
- * @param fd		The file to write to.
- * @param buf		Data, @a len bytes long.
- * @param len		Number of bytes to write.
- *
- * @return		EOK on error, return value from write() if writing
- *			failed.
- */
-static int write_all(int fd, void *data, size_t len)
+static int align_pos(int fd, size_t align)
 {
-	int cnt = 0;
-
-	do {
-		data += cnt;
-		len -= cnt;
-		cnt = write(fd, data, len);
-	} while (cnt > 0 && (len - cnt) > 0);
-
-	if (cnt < 0)
-		return cnt;
-
-	if (len - cnt > 0)
-		return EIO;
+	off64_t cur_pos;
+	size_t rem, adv;
+
+	cur_pos = lseek(fd, 0, SEEK_CUR);
+	if (cur_pos < 0)
+		return -1;
+
+	rem = cur_pos % align;
+	adv = align - rem;
+
+	cur_pos = lseek(fd, adv, SEEK_CUR);
+	if (cur_pos < 0)
+		return -1;
 
 	return EOK;
 }
 
-
 /** @}
  */
Index: pace/app/taskdump/include/elf.h
===================================================================
--- uspace/app/taskdump/include/elf.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,349 +1,0 @@
-/*
- * Copyright (c) 2006 Sergey Bondari
- * 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 ELF_H_
-#define ELF_H_
-
-#include <arch/elf.h>
-#include <sys/types.h>
-
-/**
- * current ELF version
- */
-#define	EV_CURRENT	1
-
-/** 
- * ELF types 
- */
-#define ET_NONE		0	/* No type */
-#define ET_REL		1	/* Relocatable file */
-#define ET_EXEC		2	/* Executable */
-#define ET_DYN		3	/* Shared object */
-#define ET_CORE		4	/* Core */
-#define ET_LOPROC	0xff00	/* Processor specific */
-#define ET_HIPROC	0xffff	/* Processor specific */
-
-/** 
- * ELF machine types
- */
-#define EM_NO		0	/* No machine */
-#define EM_SPARC	2	/* SPARC */
-#define EM_386		3	/* i386 */
-#define EM_MIPS		8	/* MIPS RS3000 */
-#define EM_MIPS_RS3_LE	10	/* MIPS RS3000 LE */
-#define EM_PPC		20	/* PPC32 */
-#define EM_PPC64	21	/* PPC64 */
-#define EM_ARM		40	/* ARM */
-#define EM_SPARCV9	43	/* SPARC64 */
-#define EM_IA_64	50	/* IA-64 */
-#define EM_X86_64	62	/* AMD64/EMT64 */
-
-/**
- * ELF identification indexes
- */
-#define EI_MAG0		0
-#define EI_MAG1		1
-#define EI_MAG2		2
-#define EI_MAG3		3
-#define EI_CLASS	4		/* File class */
-#define EI_DATA		5		/* Data encoding */
-#define EI_VERSION	6		/* File version */
-#define EI_OSABI	7
-#define EI_ABIVERSION	8
-#define EI_PAD		9		/* Start of padding bytes */
-#define EI_NIDENT	16		/* ELF identification table size */
-
-/**
- * ELF magic number
- */
-#define ELFMAG0		0x7f
-#define ELFMAG1		'E'
-#define ELFMAG2		'L'
-#define ELFMAG3		'F'
-
-/**
- * ELF file classes
- */
-#define ELFCLASSNONE	0
-#define ELFCLASS32	1
-#define ELFCLASS64	2
-
-/**
- * ELF data encoding types
- */
-#define ELFDATANONE	0
-#define ELFDATA2LSB	1		/* Least significant byte first (little endian) */
-#define ELFDATA2MSB	2		/* Most signigicant byte first (big endian) */
-
-/**
- * ELF error return codes
- */
-#define EE_OK			0	/* No error */
-#define EE_INVALID		1	/* Invalid ELF image */
-#define	EE_MEMORY		2	/* Cannot allocate address space */
-#define EE_INCOMPATIBLE		3	/* ELF image is not compatible with current architecture */
-#define EE_UNSUPPORTED		4	/* Non-supported ELF (e.g. dynamic ELFs) */
-#define EE_IRRECOVERABLE	5
-
-/**
- * ELF section types
- */
-#define SHT_NULL		0
-#define SHT_PROGBITS		1
-#define SHT_SYMTAB		2
-#define SHT_STRTAB		3
-#define SHT_RELA		4
-#define SHT_HASH		5
-#define SHT_DYNAMIC		6
-#define SHT_NOTE		7
-#define SHT_NOBITS		8
-#define SHT_REL			9
-#define SHT_SHLIB		10
-#define SHT_DYNSYM		11
-#define SHT_LOOS		0x60000000
-#define SHT_HIOS		0x6fffffff
-#define SHT_LOPROC		0x70000000
-#define SHT_HIPROC		0x7fffffff
-#define SHT_LOUSER		0x80000000
-#define SHT_HIUSER		0xffffffff
-
-/**
- * ELF section flags
- */
-#define SHF_WRITE		0x1 
-#define SHF_ALLOC		0x2
-#define SHF_EXECINSTR		0x4
-#define SHF_TLS			0x400
-#define SHF_MASKPROC		0xf0000000
-
-/** Macros for decomposing elf_symbol.st_info into binging and type */
-#define ELF_ST_BIND(i)		((i) >> 4)
-#define ELF_ST_TYPE(i)		((i) & 0x0f)
-#define ELF_ST_INFO(b, t)	(((b) << 4) + ((t) & 0x0f))
-
-/**
- * Symbol binding
- */
-#define STB_LOCAL		0
-#define STB_GLOBAL		1
-#define STB_WEAK		2
-#define STB_LOPROC		13
-#define STB_HIPROC		15
-
-/**
- * Symbol types
- */
-#define STT_NOTYPE		0
-#define STT_OBJECT		1
-#define STT_FUNC		2
-#define STT_SECTION		3
-#define STT_FILE		4
-#define STT_LOPROC		13
-#define STT_HIPROC		15
-
-/**
- * Program segment types
- */
-#define PT_NULL			0
-#define PT_LOAD			1
-#define PT_DYNAMIC		2
-#define PT_INTERP		3
-#define PT_NOTE			4
-#define PT_SHLIB		5
-#define PT_PHDR			6
-#define PT_LOPROC		0x70000000
-#define PT_HIPROC		0x7fffffff
-
-/**
- * Program segment attributes.
- */
-#define PF_X	1
-#define PF_W	2
-#define PF_R	4
-
-/**
- * ELF data types
- *
- * These types are found to be identical in both 32-bit and 64-bit
- * ELF object file specifications. They are the only types used
- * in ELF header.
- */
-typedef uint64_t elf_xword;
-typedef int64_t elf_sxword;
-typedef uint32_t elf_word;
-typedef int32_t elf_sword;
-typedef uint16_t elf_half;
-
-/**
- * 32-bit ELF data types.
- *
- * These types are specific for 32-bit format.
- */
-typedef uint32_t elf32_addr;
-typedef uint32_t elf32_off;
-
-/**
- * 64-bit ELF data types.
- *
- * These types are specific for 64-bit format.
- */
-typedef uint64_t elf64_addr;
-typedef uint64_t elf64_off;
-
-/** ELF header */
-struct elf32_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf32_addr e_entry;
-	elf32_off e_phoff;
-	elf32_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-struct elf64_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf64_addr e_entry;
-	elf64_off e_phoff;
-	elf64_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-
-/*
- * ELF segment header.
- * Segments headers are also known as program headers.
- */
-struct elf32_segment_header {
-	elf_word p_type;
-	elf32_off p_offset;
-	elf32_addr p_vaddr;
-	elf32_addr p_paddr;
-	elf_word p_filesz;
-	elf_word p_memsz;
-	elf_word p_flags;
-	elf_word p_align;
-};
-struct elf64_segment_header {
-	elf_word p_type;
-	elf_word p_flags;
-	elf64_off p_offset;
-	elf64_addr p_vaddr;
-	elf64_addr p_paddr;
-	elf_xword p_filesz;
-	elf_xword p_memsz;
-	elf_xword p_align;
-};
-
-/*
- * ELF section header
- */
-struct elf32_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_word sh_flags;
-	elf32_addr sh_addr;
-	elf32_off sh_offset;
-	elf_word sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_word sh_addralign;
-	elf_word sh_entsize;
-};
-struct elf64_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_xword sh_flags;
-	elf64_addr sh_addr;
-	elf64_off sh_offset;
-	elf_xword sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_xword sh_addralign;
-	elf_xword sh_entsize;
-};
-
-/*
- * ELF symbol table entry
- */
-struct elf32_symbol {
-	elf_word st_name;
-	elf32_addr st_value;
-	elf_word st_size;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-};
-struct elf64_symbol {
-	elf_word st_name;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-	elf64_addr st_value;
-	elf_xword st_size;
-};
-
-#ifdef __32_BITS__ 
-typedef struct elf32_header elf_header_t;
-typedef struct elf32_segment_header elf_segment_header_t;
-typedef struct elf32_section_header elf_section_header_t;
-typedef struct elf32_symbol elf_symbol_t;
-#endif
-#ifdef __64_BITS__
-typedef struct elf64_header elf_header_t;
-typedef struct elf64_segment_header elf_segment_header_t;
-typedef struct elf64_section_header elf_section_header_t;
-typedef struct elf64_symbol elf_symbol_t;
-#endif
-
-extern char *elf_error(unsigned int rc);
-
-#endif
-
-/** @}
- */
Index: uspace/app/taskdump/include/elf_core.h
===================================================================
--- uspace/app/taskdump/include/elf_core.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/taskdump/include/elf_core.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,5 +36,10 @@
 #define ELF_CORE_H_
 
-int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n, int phoneid);
+#include <async.h>
+#include <elf/elf_linux.h>
+#include <libarch/istate.h>
+
+extern int elf_core_save(const char *, as_area_info_t *, unsigned int,
+    async_sess_t *, istate_t *);
 
 #endif
Index: uspace/app/taskdump/include/symtab.h
===================================================================
--- uspace/app/taskdump/include/symtab.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/taskdump/include/symtab.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,6 @@
 #define SYMTAB_H_
 
+#include <elf/elf.h>
 #include <sys/types.h>
-#include <elf.h>
 
 typedef struct {
Index: uspace/app/taskdump/symtab.c
===================================================================
--- uspace/app/taskdump/symtab.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/taskdump/symtab.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,4 +36,5 @@
  */
 
+#include <elf/elf.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,5 +44,4 @@
 #include <fcntl.h>
 
-#include <elf.h>
 #include "include/symtab.h"
 
@@ -50,5 +50,4 @@
     elf_section_header_t *shdr);
 static int chunk_load(int fd, off64_t start, size_t size, void **ptr);
-static int read_all(int fd, void *buf, size_t len);
 
 /** Load symbol table from an ELF file.
@@ -90,5 +89,5 @@
 
 	rc = read_all(fd, &elf_hdr, sizeof(elf_header_t));
-	if (rc != EOK) {
+	if (rc != sizeof(elf_header_t)) {
 		printf("failed reading elf header\n");
 		free(stab);
@@ -312,5 +311,5 @@
 
 	rc = read_all(fd, sec_hdr, sizeof(elf_section_header_t));
-	if (rc != EOK)
+	if (rc != sizeof(elf_section_header_t))
 		return EIO;
 
@@ -331,8 +330,9 @@
 static int chunk_load(int fd, off64_t start, size_t size, void **ptr)
 {
-	int rc;
-
-	rc = lseek(fd, start, SEEK_SET);
-	if (rc == (off64_t) -1) {
+	ssize_t rc;
+	off64_t offs;
+
+	offs = lseek(fd, start, SEEK_SET);
+	if (offs == (off64_t) -1) {
 		printf("failed seeking chunk\n");
 		*ptr = NULL;
@@ -347,5 +347,5 @@
 
 	rc = read_all(fd, *ptr, size);
-	if (rc != EOK) {
+	if (rc != (ssize_t) size) {
 		printf("failed reading chunk\n");
 		free(*ptr);
@@ -357,34 +357,4 @@
 }
 
-/** Read until the buffer is read in its entirety.
- *
- * This function fails if it cannot read exactly @a len bytes from the file.
- *
- * @param fd		The file to read from.
- * @param buf		Buffer for storing data, @a len bytes long.
- * @param len		Number of bytes to read.
- *
- * @return		EOK on error, EIO if file is short or return value
- *			from read() if reading failed.
- */
-static int read_all(int fd, void *buf, size_t len)
-{
-	int cnt = 0;
-
-	do {
-		buf += cnt;
-		len -= cnt;
-		cnt = read(fd, buf, len);
-	} while (cnt > 0 && (len - cnt) > 0);
-
-	if (cnt < 0)
-		return cnt;
-
-	if (len - cnt > 0)
-		return EIO;
-
-	return EOK;
-}
-
 /** @}
  */
Index: uspace/app/taskdump/taskdump.c
===================================================================
--- uspace/app/taskdump/taskdump.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/taskdump/taskdump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,4 +34,5 @@
 
 #include <async.h>
+#include <elf/elf_linux.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -54,5 +55,5 @@
 #define LINE_BYTES 16
 
-static int phoneid;
+static async_sess_t *sess;
 static task_id_t task_id;
 static bool write_core_file;
@@ -73,4 +74,6 @@
 static char *fmt_sym_address(uintptr_t addr);
 
+static istate_t reg_state;
+
 int main(int argc, char *argv[])
 {
@@ -104,6 +107,6 @@
 		printf("Failed dumping address space areas.\n");
 
-	udebug_end(phoneid);
-	async_hangup(phoneid);
+	udebug_end(sess);
+	async_hangup(sess);
 
 	return 0;
@@ -112,30 +115,27 @@
 static int connect_task(task_id_t task_id)
 {
-	int rc;
-
-	rc = async_connect_kbox(task_id);
-
-	if (rc == ENOTSUP) {
-		printf("You do not have userspace debugging support "
-		    "compiled in the kernel.\n");
-		printf("Compile kernel with 'Support for userspace debuggers' "
-		    "(CONFIG_UDEBUG) enabled.\n");
-		return rc;
-	}
-
-	if (rc < 0) {
+	async_sess_t *ksess = async_connect_kbox(task_id);
+	
+	if (!ksess) {
+		if (errno == ENOTSUP) {
+			printf("You do not have userspace debugging support "
+			    "compiled in the kernel.\n");
+			printf("Compile kernel with 'Support for userspace debuggers' "
+			    "(CONFIG_UDEBUG) enabled.\n");
+			return errno;
+		}
+		
 		printf("Error connecting\n");
-		printf("async_connect_kbox(%" PRIu64 ") -> %d ", task_id, rc);
-		return rc;
-	}
-
-	phoneid = rc;
-
-	rc = udebug_begin(phoneid);
+		printf("async_connect_kbox(%" PRIu64 ") -> %d ", task_id, errno);
+		return errno;
+	}
+	
+	int rc = udebug_begin(ksess);
 	if (rc < 0) {
 		printf("udebug_begin() -> %d\n", rc);
 		return rc;
 	}
-
+	
+	sess = ksess;
 	return 0;
 }
@@ -213,5 +213,5 @@
 
 	/* TODO: See why NULL does not work. */
-	rc = udebug_thread_read(phoneid, &dummy_buf, 0, &copied, &needed);
+	rc = udebug_thread_read(sess, &dummy_buf, 0, &copied, &needed);
 	if (rc < 0) {
 		printf("udebug_thread_read() -> %d\n", rc);
@@ -227,5 +227,5 @@
 	thash_buf = malloc(buf_size);
 
-	rc = udebug_thread_read(phoneid, thash_buf, buf_size, &copied, &needed);
+	rc = udebug_thread_read(sess, thash_buf, buf_size, &copied, &needed);
 	if (rc < 0) {
 		printf("udebug_thread_read() -> %d\n", rc);
@@ -262,5 +262,5 @@
 	int rc;
 
-	rc = udebug_areas_read(phoneid, &dummy_buf, 0, &copied, &needed);
+	rc = udebug_areas_read(sess, &dummy_buf, 0, &copied, &needed);
 	if (rc < 0) {
 		printf("udebug_areas_read() -> %d\n", rc);
@@ -271,5 +271,5 @@
 	ainfo_buf = malloc(buf_size);
 
-	rc = udebug_areas_read(phoneid, ainfo_buf, buf_size, &copied, &needed);
+	rc = udebug_areas_read(sess, ainfo_buf, buf_size, &copied, &needed);
 	if (rc < 0) {
 		printf("udebug_areas_read() -> %d\n", rc);
@@ -296,5 +296,8 @@
 	if (write_core_file) {
 		printf("Writing core file '%s'\n", core_file_name);
-		rc = elf_core_save(core_file_name, ainfo_buf, n_areas, phoneid);
+
+		rc = elf_core_save(core_file_name, ainfo_buf, n_areas, sess,
+		    &reg_state);
+
 		if (rc != EOK) {
 			printf("Failed writing core file.\n");
@@ -316,5 +319,5 @@
 	int rc;
 
-	rc = udebug_regs_read(phoneid, thash, &istate);
+	rc = udebug_regs_read(sess, thash, &istate);
 	if (rc < 0) {
 		printf("Failed reading registers (%d).\n", rc);
@@ -324,4 +327,7 @@
 	pc = istate_get_pc(&istate);
 	fp = istate_get_fp(&istate);
+
+	/* Save register state for dumping to core file later. */
+	reg_state = istate;
 
 	sym_pc = fmt_sym_address(pc);
@@ -359,5 +365,5 @@
 	(void) arg;
 
-	rc = udebug_mem_read(phoneid, &data, addr, sizeof(data));
+	rc = udebug_mem_read(sess, &data, addr, sizeof(data));
 	if (rc < 0) {
 		printf("Warning: udebug_mem_read() failed.\n");
@@ -430,5 +436,5 @@
 	int rc;
 
-	rc = udebug_name_read(phoneid, &dummy_buf, 0, &copied, &needed);
+	rc = udebug_name_read(sess, &dummy_buf, 0, &copied, &needed);
 	if (rc < 0)
 		return NULL;
@@ -436,5 +442,5 @@
 	name_size = needed;
 	name = malloc(name_size + 1);
-	rc = udebug_name_read(phoneid, name, name_size, &copied, &needed);
+	rc = udebug_name_read(sess, name, name_size, &copied, &needed);
 	if (rc < 0) {
 		free(name);
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,8 +29,11 @@
 
 USPACE_PREFIX = ../..
+LIBS = $(LIBEXT2_PREFIX)/libext2.a $(LIBBLOCK_PREFIX)/libblock.a
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX) -I$(LIBEXT2_PREFIX)
 BINARY = tester
 
 SOURCES = \
 	tester.c \
+	util.c \
 	thread/thread1.c \
 	print/print1.c \
@@ -48,7 +51,12 @@
 	ipc/ping_pong.c \
 	loop/loop1.c \
+	mm/common.c \
 	mm/malloc1.c \
+	mm/malloc2.c \
+	mm/malloc3.c \
+	mm/mapping1.c \
 	hw/misc/virtchar1.c \
-	hw/serial/serial1.c
+	hw/serial/serial1.c \
+	libext2/libext2_1.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/tester/console/console1.c
===================================================================
--- uspace/app/tester/console/console1.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/console/console1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -50,19 +50,21 @@
 {
 	if (!test_quiet) {
+		console_ctrl_t *console = console_init(stdin, stdout);
+		
 		printf("Style test: ");
-		fflush(stdout);
-		console_set_style(fphone(stdout), STYLE_NORMAL);
+		console_flush(console);
+		console_set_style(console, STYLE_NORMAL);
 		printf(" normal ");
-		fflush(stdout);
-		console_set_style(fphone(stdout), STYLE_EMPHASIS);
+		console_flush(console);
+		console_set_style(console, STYLE_EMPHASIS);
 		printf(" emphasized ");
-		fflush(stdout);
-		console_set_style(fphone(stdout), STYLE_INVERTED);
+		console_flush(console);
+		console_set_style(console, STYLE_INVERTED);
 		printf(" inverted ");
-		fflush(stdout);
-		console_set_style(fphone(stdout), STYLE_SELECTED);
+		console_flush(console);
+		console_set_style(console, STYLE_SELECTED);
 		printf(" selected ");
-		fflush(stdout);
-		console_set_style(fphone(stdout), STYLE_NORMAL);
+		console_flush(console);
+		console_set_style(console, STYLE_NORMAL);
 		printf("\n");
 		
@@ -73,11 +75,11 @@
 		for (j = 0; j < 2; j++) {
 			for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
-				fflush(stdout);
-				console_set_color(fphone(stdout), i, COLOR_WHITE,
+				console_flush(console);
+				console_set_color(console, i, COLOR_WHITE,
 				    j ? CATTR_BRIGHT : 0);
 				printf(" %s ", color_name[i]);
 			}
-			fflush(stdout);
-			console_set_style(fphone(stdout), STYLE_NORMAL);
+			console_flush(console);
+			console_set_style(console, STYLE_NORMAL);
 			putchar('\n');
 		}
@@ -86,11 +88,11 @@
 		for (j = 0; j < 2; j++) {
 			for (i = COLOR_BLACK; i <= COLOR_WHITE; i++) {
-				fflush(stdout);
-				console_set_color(fphone(stdout), COLOR_WHITE, i,
+				console_flush(console);
+				console_set_color(console, COLOR_WHITE, i,
 				    j ? CATTR_BRIGHT : 0);
 				printf(" %s ", color_name[i]);
 			}
-			fflush(stdout);
-			console_set_style(fphone(stdout), STYLE_NORMAL);
+			console_flush(console);
+			console_set_style(console, STYLE_NORMAL);
 			putchar('\n');
 		}
@@ -99,28 +101,28 @@
 		
 		for (i = 0; i < 255; i += 16) {
-			fflush(stdout);
-			console_set_rgb_color(fphone(stdout), (255 - i) << 16, i << 16);
+			console_flush(console);
+			console_set_rgb_color(console, (255 - i) << 16, i << 16);
 			putchar('X');
 		}
-		fflush(stdout);
-		console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
+		console_flush(console);
+		console_set_color(console, COLOR_BLACK, COLOR_WHITE, 0);
 		putchar('\n');
 		
 		for (i = 0; i < 255; i += 16) {
-			fflush(stdout);
-			console_set_rgb_color(fphone(stdout), (255 - i) << 8, i << 8);
+			console_flush(console);
+			console_set_rgb_color(console, (255 - i) << 8, i << 8);
 			putchar('X');
 		}
-		fflush(stdout);
-		console_set_color(fphone(stdout), COLOR_BLACK, COLOR_WHITE, 0);
+		console_flush(console);
+		console_set_color(console, COLOR_BLACK, COLOR_WHITE, 0);
 		putchar('\n');
 		
 		for (i = 0; i < 255; i += 16) {
-			fflush(stdout);
-			console_set_rgb_color(fphone(stdout), 255 - i, i);
+			console_flush(console);
+			console_set_rgb_color(console, 255 - i, i);
 			putchar('X');
 		}
-		fflush(stdout);
-		console_set_style(fphone(stdout), STYLE_NORMAL);
+		console_flush(console);
+		console_set_style(console, STYLE_NORMAL);
 		putchar('\n');
 	}
Index: uspace/app/tester/fault/fault2.c
===================================================================
--- uspace/app/tester/fault/fault2.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/fault/fault2.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,4 +29,5 @@
 
 #include "../tester.h"
+#include <stdio.h>
 
 typedef int __attribute__((may_alias)) aliasing_int;
@@ -38,4 +39,5 @@
 	
 	var1 = *((aliasing_int *) (((char *) (&var)) + 1));
+	printf("Read %d\n", var1);
 	
 	return "Survived unaligned read";
Index: uspace/app/tester/hw/misc/virtchar1.c
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/hw/misc/virtchar1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,10 +43,10 @@
 #include <str.h>
 #include <vfs/vfs.h>
+#include <vfs/vfs_sess.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include "../../tester.h"
 
-#define DEVICE_PATH_NORMAL "/dev/devices/\\virt\\null\\a"
-#define DEVICE_PATH_CLASSES "/dev/class/virt-null\\1"
+#define DEVICE_PATH_NORMAL "/loc/devices/\\virt\\null\\a"
 #define BUFFER_SIZE 64
 
@@ -66,17 +66,17 @@
 	TPRINTF("   ...file handle %d\n", fd);
 
-	TPRINTF(" Asking for phone...\n");
-	int phone = fd_phone(fd);
-	if (phone < 0) {
+	TPRINTF(" Asking for session...\n");
+	async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd);
+	if (!sess) {
 		close(fd);
-		TPRINTF("   ...error: %s\n", str_error(phone));
-		return "Failed to get phone to device";
+		TPRINTF("   ...error: %s\n", str_error(errno));
+		return "Failed to get session to device";
 	}
-	TPRINTF("   ...phone is %d\n", phone);
+	TPRINTF("   ...session is %p\n", sess);
 	
 	TPRINTF(" Will try to read...\n");
 	size_t i;
 	char buffer[BUFFER_SIZE];
-	char_dev_read(phone, 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++) {
@@ -88,6 +88,6 @@
 	
 	/* Clean-up. */
-	TPRINTF(" Closing phones and file descriptors\n");
-	async_hangup(phone);
+	TPRINTF(" Closing session and file descriptor\n");
+	async_hangup(sess);
 	close(fd);
 	
@@ -104,9 +104,4 @@
 	}
 
-	res = test_virtchar1_internal(DEVICE_PATH_CLASSES);
-	if (res != NULL) {
-		return res;
-	}
-
 	return NULL;
 }
Index: uspace/app/tester/hw/serial/serial1.c
===================================================================
--- uspace/app/tester/hw/serial/serial1.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/hw/serial/serial1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -71,22 +71,18 @@
 		}
 	
-	int res = devman_get_phone(DEVMAN_CLIENT, IPC_FLAG_BLOCKING);
-	
 	devman_handle_t handle;
-	res = devman_device_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
+	int res = devman_fun_get_handle("/hw/pci0/00:01.0/com1/a", &handle,
 	    IPC_FLAG_BLOCKING);
 	if (res != EOK)
 		return "Could not get serial device handle";
 	
-	int phone = devman_device_connect(handle, IPC_FLAG_BLOCKING);
-	if (phone < 0) {
-		devman_hangup_phone(DEVMAN_CLIENT);
+	async_sess_t *sess = devman_device_connect(EXCHANGE_SERIALIZE, handle,
+	    IPC_FLAG_BLOCKING);
+	if (!sess)
 		return "Unable to connect to serial device";
-	}
 	
 	char *buf = (char *) malloc(cnt + 1);
 	if (buf == NULL) {
-		async_hangup(phone);
-		devman_hangup_phone(DEVMAN_CLIENT);
+		async_hangup(sess);
 		return "Failed to allocate input buffer";
 	}
@@ -97,19 +93,23 @@
 	sysarg_t old_word_size;
 	
-	res = async_req_0_4(phone, SERIAL_GET_COM_PROPS, &old_baud,
+	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);
+	
 	if (res != EOK) {
 		free(buf);
-		async_hangup(phone);
-		devman_hangup_phone(DEVMAN_CLIENT);
+		async_hangup(sess);
 		return "Failed to get old serial communication parameters";
 	}
 	
-	res = async_req_4_0(phone, SERIAL_SET_COM_PROPS, 1200,
+	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);
+	
 	if (EOK != res) {
 		free(buf);
-		async_hangup(phone);
-		devman_hangup_phone(DEVMAN_CLIENT);
+		async_hangup(sess);
 		return "Failed to set serial communication parameters";
 	}
@@ -120,21 +120,25 @@
 	size_t total = 0;
 	while (total < cnt) {
-		ssize_t read = char_dev_read(phone, buf, cnt - total);
+		ssize_t read = char_dev_read(sess, buf, cnt - total);
 		
 		if (read < 0) {
-			async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+			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(phone);
-			devman_hangup_phone(DEVMAN_CLIENT);
+			async_hangup(sess);
 			return "Failed read from serial device";
 		}
 		
 		if ((size_t) read > cnt - total) {
-			async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+			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(phone);
-			devman_hangup_phone(DEVMAN_CLIENT);
+			async_hangup(sess);
 			return "Read more data than expected";
 		}
@@ -151,21 +155,25 @@
 			 * direction of data transfer.
 			 */
-			ssize_t written = char_dev_write(phone, buf, read);
+			ssize_t written = char_dev_write(sess, buf, read);
 			
 			if (written < 0) {
-				async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+				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(phone);
-				devman_hangup_phone(DEVMAN_CLIENT);
+				async_hangup(sess);
 				return "Failed write to serial device";
 			}
 			
 			if (written != read) {
-				async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+				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(phone);
-				devman_hangup_phone(DEVMAN_CLIENT);
+				async_hangup(sess);
 				return "Written less data than read from serial device";
 			}
@@ -180,11 +188,13 @@
 	
 	size_t eot_size = str_size(EOT);
-	ssize_t written = char_dev_write(phone, (void *) EOT, eot_size);
-	
-	async_req_4_0(phone, SERIAL_SET_COM_PROPS, old_baud,
+	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);
+	
 	free(buf);
-	async_hangup(phone);
-	devman_hangup_phone(DEVMAN_CLIENT);
+	async_hangup(sess);
 	
 	if (written < 0)
Index: uspace/app/tester/ipc/ping_pong.c
===================================================================
--- uspace/app/tester/ipc/ping_pong.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/ipc/ping_pong.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,5 +30,5 @@
 #include <stdlib.h>
 #include <sys/time.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <errno.h>
@@ -61,5 +61,5 @@
 		size_t i;
 		for (i = 0; i < COUNT_GRANULARITY; i++) {
-			int retval = async_req_0_0(PHONE_NS, NS_PING);
+			int retval = ns_ping();
 			
 			if (retval != EOK) {
Index: uspace/app/tester/libext2/libext2_1.c
===================================================================
--- uspace/app/tester/libext2/libext2_1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/libext2/libext2_1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include "../tester.h"
+#include "../util.h"
+#include <libext2.h>
+#include <malloc.h>
+
+static ext2_superblock_t *fake_superblock1()
+{
+	uint8_t *buf;
+	int i;
+	
+	buf = malloc(EXT2_SUPERBLOCK_SIZE);
+	if (buf == NULL) {
+		return NULL;
+	}
+	
+	for (i = 0; i < EXT2_SUPERBLOCK_SIZE; i++) {
+		buf[i] = i % 256;
+	}
+	
+	return (ext2_superblock_t *) buf;
+}
+
+const char *test_libext2_1(void)
+{
+	ext2_superblock_t *fake1;
+	
+	TPRINTF("Testing libext2 superblock getters...\n");
+	TPRINTF("Simple test for correct position and byte order\n");
+	
+	fake1 = fake_superblock1();
+	if (fake1 == NULL) {
+		return "Failed allocating memory for test superblock 1";
+	}
+	
+	ASSERT_EQ_32(0x03020100, ext2_superblock_get_total_inode_count(fake1),
+	    "Failed getting total inode count");
+	ASSERT_EQ_32(0x07060504, ext2_superblock_get_total_block_count(fake1),
+	    "Failed getting total block count");
+	ASSERT_EQ_32(0x0B0A0908, ext2_superblock_get_reserved_block_count(fake1),
+	    "Failed getting reserved block count");
+	ASSERT_EQ_32(0x0F0E0D0C, ext2_superblock_get_free_block_count(fake1),
+	    "Failed getting free block count");
+	ASSERT_EQ_32(0x13121110, ext2_superblock_get_free_inode_count(fake1),
+	    "Failed getting free inode count");
+	ASSERT_EQ_32(0x17161514, ext2_superblock_get_first_block(fake1),
+	    "Failed getting first block number");
+	ASSERT_EQ_32(0x1B1A1918, ext2_superblock_get_block_size_log2(fake1),
+	    "Failed getting log block size");
+	ASSERT_EQ_32(0x1F1E1D1C, ext2_superblock_get_fragment_size_log2(fake1),
+	    "Failed getting log fragment size");
+	ASSERT_EQ_32(0x23222120, ext2_superblock_get_blocks_per_group(fake1),
+	    "Failed getting blocks per group");
+	ASSERT_EQ_32(0x27262524, ext2_superblock_get_fragments_per_group(fake1),
+	    "Failed getting fragments per group");
+	ASSERT_EQ_32(0x2B2A2928, ext2_superblock_get_inodes_per_group(fake1),
+	    "Failed getting inodes per group");
+	ASSERT_EQ_16(0x3938, ext2_superblock_get_magic(fake1),
+	    "Failed getting magic number");
+	ASSERT_EQ_16(0x3B3A, ext2_superblock_get_state(fake1),
+	    "Failed getting state");
+	ASSERT_EQ_16(0x3F3E, ext2_superblock_get_rev_minor(fake1),
+	    "Failed getting minor revision number");
+	ASSERT_EQ_32(0x4B4A4948, ext2_superblock_get_os(fake1),
+	    "Failed getting OS");
+	ASSERT_EQ_32(0x4F4E4D4C, ext2_superblock_get_rev_major(fake1),
+	    "Failed getting major revision number");
+	ASSERT_EQ_32(0x57565554, ext2_superblock_get_first_inode(fake1),
+	    "Failed getting first inode number");
+	ASSERT_EQ_16(0x5958, ext2_superblock_get_inode_size(fake1),
+	    "Failed getting size");
+	ASSERT_EQ_8(0x68, fake1->uuid[0], "UUID position is incorrect");
+	ASSERT_EQ_8(0x78, fake1->volume_name[0],
+	    "Volume name position is incorrect");
+	
+	return NULL;
+}
Index: uspace/app/tester/libext2/libext2_1.def
===================================================================
--- uspace/app/tester/libext2/libext2_1.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/libext2/libext2_1.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,6 @@
+{
+	"libext2_1",
+	"Superblock getters test",
+	&test_libext2_1,
+	true
+},
Index: uspace/app/tester/mm/common.c
===================================================================
--- uspace/app/tester/mm/common.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/mm/common.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2009 Martin Decky
+ * Copyright (c) 2009 Tomas Bures
+ * Copyright (c) 2009 Lubomir Bulej
+ * 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 <malloc.h>
+#include <as.h>
+#include <adt/list.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "../tester.h"
+#include "common.h"
+
+/*
+ * Global error flag. The flag is set if an error
+ * is encountered (overlapping blocks, inconsistent
+ * block data, etc.)
+ */
+bool error_flag = false;
+
+/*
+ * Memory accounting: the amount of allocated memory and the
+ * number and list of allocated blocks.
+ */
+size_t mem_allocated;
+size_t mem_blocks_count;
+
+static LIST_INITIALIZE(mem_blocks);
+static LIST_INITIALIZE(mem_areas);
+
+/** Initializes the memory accounting structures.
+ *
+ */
+void init_mem(void)
+{
+	mem_allocated = 0;
+	mem_blocks_count = 0;
+}
+
+/** Cleanup all allocated memory blocks and mapped areas.
+ *
+ * Set the global error_flag if an error occurs.
+ *
+ */
+void done_mem(void)
+{
+	link_t *link;
+	
+	while ((link = list_first(&mem_blocks)) != NULL) {
+		mem_block_t *block = list_get_instance(link, mem_block_t, link);
+		free_block(block);
+	}
+	
+	while ((link = list_first(&mem_areas)) != NULL) {
+		mem_area_t *area = list_get_instance(link, mem_area_t, link);
+		unmap_area(area);
+	}
+}
+
+static bool overlap_match(link_t *link, void *addr, size_t size)
+{
+	mem_block_t *block = list_get_instance(link, mem_block_t, link);
+	
+	/* Entry block control structure <mbeg, mend) */
+	uint8_t *mbeg = (uint8_t *) block;
+	uint8_t *mend = (uint8_t *) block + sizeof(mem_block_t);
+	
+	/* Entry block memory <bbeg, bend) */
+	uint8_t *bbeg = (uint8_t *) block->addr;
+	uint8_t *bend = (uint8_t *) block->addr + block->size;
+	
+	/* Data block <dbeg, dend) */
+	uint8_t *dbeg = (uint8_t *) addr;
+	uint8_t *dend = (uint8_t *) addr + size;
+	
+	/* Check for overlaps */
+	if (((mbeg >= dbeg) && (mbeg < dend)) ||
+	    ((mend > dbeg) && (mend <= dend)) ||
+	    ((bbeg >= dbeg) && (bbeg < dend)) ||
+	    ((bend > dbeg) && (bend <= dend)))
+		return true;
+	
+	return false;
+}
+
+/** Test overlap
+ *
+ * Test whether a block starting at @addr overlaps with another,
+ * previously allocated memory block or its control structure.
+ *
+ * @param addr Initial address of the block
+ * @param size Size of the block
+ *
+ * @return False if the block does not overlap.
+ *
+ */
+static int test_overlap(void *addr, size_t size)
+{
+	bool fnd = false;
+	
+	list_foreach(mem_blocks, link) {
+		if (overlap_match(link, addr, size)) {
+			fnd = true;
+			break;
+		}
+	}
+	
+	return fnd;
+}
+
+static void check_consistency(const char *loc)
+{
+	/* Check heap consistency */
+	void *prob = heap_check();
+	if (prob != NULL) {
+		TPRINTF("\nError: Heap inconsistency at %p in %s.\n",
+		    prob, loc);
+		TSTACKTRACE();
+		error_flag = true;
+	}
+}
+
+/** Checked malloc
+ *
+ * Allocate @size bytes of memory and check whether the chunk comes
+ * from the non-mapped memory region and whether the chunk overlaps
+ * with other, previously allocated, chunks.
+ *
+ * @param size Amount of memory to allocate
+ *
+ * @return NULL if the allocation failed. Sets the global error_flag to
+ *         true if the allocation succeeded but is illegal.
+ *
+ */
+static void *checked_malloc(size_t size)
+{
+	void *data;
+	
+	/* Allocate the chunk of memory */
+	data = malloc(size);
+	check_consistency("checked_malloc");
+	if (data == NULL)
+		return NULL;
+	
+	/* Check for overlaps with other chunks */
+	if (test_overlap(data, size)) {
+		TPRINTF("\nError: Allocated block overlaps with another "
+		    "previously allocated block.\n");
+		TSTACKTRACE();
+		error_flag = true;
+	}
+	
+	return data;
+}
+
+
+/* Allocate block
+ *
+ * Allocate a block of memory of @size bytes and add record about it into
+ * the mem_blocks list. Return a pointer to the block holder structure or
+ * NULL if the allocation failed.
+ *
+ * If the allocation is illegal (e.g. the memory does not come from the
+ * right region or some of the allocated blocks overlap with others),
+ * set the global error_flag.
+ *
+ * @param size Size of the memory block
+ *
+ */
+mem_block_t *alloc_block(size_t size)
+{
+	/* Check for allocation limit */
+	if (mem_allocated >= MAX_ALLOC)
+		return NULL;
+	
+	/* Allocate the block holder */
+	mem_block_t *block =
+	    (mem_block_t *) checked_malloc(sizeof(mem_block_t));
+	if (block == NULL)
+		return NULL;
+	
+	link_initialize(&block->link);
+	
+	/* Allocate the block memory */
+	block->addr = checked_malloc(size);
+	if (block->addr == NULL) {
+		free(block);
+		check_consistency("alloc_block");
+		return NULL;
+	}
+	
+	block->size = size;
+	
+	/* Register the allocated block */
+	list_append(&block->link, &mem_blocks);
+	mem_allocated += size + sizeof(mem_block_t);
+	mem_blocks_count++;
+	
+	return block;
+}
+
+/** Free block
+ *
+ * Free the block of memory and the block control structure allocated by
+ * alloc_block. Set the global error_flag if an error occurs.
+ *
+ * @param block Block control structure
+ *
+ */
+void free_block(mem_block_t *block)
+{
+	/* Unregister the block */
+	list_remove(&block->link);
+	mem_allocated -= block->size + sizeof(mem_block_t);
+	mem_blocks_count--;
+	
+	/* Free the memory */
+	free(block->addr);
+	check_consistency("free_block (a)");
+	free(block);
+	check_consistency("free_block (b)");
+}
+
+/** Calculate expected value
+ *
+ * Compute the expected value of a byte located at @pos in memory
+ * block described by @block.
+ *
+ * @param block Memory block control structure
+ * @param pos   Position in the memory block data area
+ *
+ */
+static inline uint8_t block_expected_value(mem_block_t *block, uint8_t *pos)
+{
+	return ((uintptr_t) block ^ (uintptr_t) pos) & 0xff;
+}
+
+/** Fill block
+ *
+ * Fill the memory block controlled by @block with data.
+ *
+ * @param block Memory block control structure
+ *
+ */
+void fill_block(mem_block_t *block)
+{
+	for (uint8_t *pos = block->addr, *end = pos + block->size;
+	    pos < end; pos++)
+		*pos = block_expected_value(block, pos);
+	
+	check_consistency("fill_block");
+}
+
+/** Check block
+ *
+ * Check whether the block @block contains the data it was filled with.
+ * Set global error_flag if an error occurs.
+ *
+ * @param block Memory block control structure
+ *
+ */
+void check_block(mem_block_t *block)
+{
+	for (uint8_t *pos = block->addr, *end = pos + block->size;
+	    pos < end; pos++) {
+		if (*pos != block_expected_value(block, pos)) {
+			TPRINTF("\nError: Corrupted content of a data block.\n");
+			TSTACKTRACE();
+			error_flag = true;
+			return;
+		}
+	}
+}
+
+/** Get random block
+ *
+ * Select a random memory block from the list of allocated blocks.
+ *
+ * @return Block control structure or NULL if the list is empty.
+ *
+ */
+mem_block_t *get_random_block(void)
+{
+	if (mem_blocks_count == 0)
+		return NULL;
+	
+	unsigned int idx = rand() % mem_blocks_count;
+	link_t *entry = list_nth(&mem_blocks, idx);
+	
+	if (entry == NULL) {
+		TPRINTF("\nError: Corrupted list of allocated memory blocks.\n");
+		TSTACKTRACE();
+		error_flag = true;
+	}
+	
+	return list_get_instance(entry, mem_block_t, link);
+}
+
+/* Map memory area
+ *
+ * Map a memory area of @size bytes and add record about it into
+ * the mem_areas list. Return a pointer to the area holder structure or
+ * NULL if the mapping failed.
+ *
+ * @param size Size of the memory area
+ *
+ */
+mem_area_t *map_area(size_t size)
+{
+	/* Allocate the area holder */
+	mem_area_t *area =
+	    (mem_area_t *) checked_malloc(sizeof(mem_area_t));
+	if (area == NULL)
+		return NULL;
+	
+	link_initialize(&area->link);
+	
+	/* Map the memory area */
+	void *addr = as_get_mappable_page(size);
+	if (addr == NULL) {
+		free(area);
+		check_consistency("map_area (a)");
+		return NULL;
+	}
+	
+	area->addr = as_area_create(addr, size, AS_AREA_WRITE | AS_AREA_READ);
+	if (area->addr == (void *) -1) {
+		free(area);
+		check_consistency("map_area (b)");
+		return NULL;
+	}
+	
+	area->size = size;
+	
+	/* Register the allocated area */
+	list_append(&area->link, &mem_areas);
+	
+	return area;
+}
+
+/** Unmap area
+ *
+ * Unmap the memory area and free the block control structure.
+ * Set the global error_flag if an error occurs.
+ *
+ * @param area Memory area control structure
+ *
+ */
+void unmap_area(mem_area_t *area)
+{
+	/* Unregister the area */
+	list_remove(&area->link);
+	
+	/* Free the memory */
+	int ret = as_area_destroy(area->addr);
+	if (ret != EOK)
+		error_flag = true;
+	
+	free(area);
+	check_consistency("unmap_area");
+}
+
+/** Calculate expected value
+ *
+ * Compute the expected value of a byte located at @pos in memory
+ * area described by @area.
+ *
+ * @param area Memory area control structure
+ * @param pos  Position in the memory area data area
+ *
+ */
+static inline uint8_t area_expected_value(mem_area_t *area, uint8_t *pos)
+{
+	return ((uintptr_t) area ^ (uintptr_t) pos) & 0xaa;
+}
+
+/** Fill area
+ *
+ * Fill the memory area controlled by @area with data.
+ *
+ * @param area Memory area control structure
+ *
+ */
+void fill_area(mem_area_t *area)
+{
+	for (uint8_t *pos = area->addr, *end = pos + area->size;
+	    pos < end; pos++)
+		*pos = area_expected_value(area, pos);
+	
+	check_consistency("fill_area");
+}
Index: uspace/app/tester/mm/common.h
===================================================================
--- uspace/app/tester/mm/common.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/mm/common.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup tester
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MM_COMMON_H_
+#define MM_COMMON_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include <adt/list.h>
+
+#define MAX_ALLOC  (16 * 1024 * 1024)
+
+#define AREA_GRANULARITY  16
+#define AREA_SIZE         (4 * PAGE_SIZE)
+
+typedef struct {
+	/* Address of the start of the block */
+	void *addr;
+	
+	/* Size of the memory block */
+	size_t size;
+	
+	/* Link to other blocks */
+	link_t link;
+} mem_block_t;
+
+typedef struct {
+	/* Address of the start of the area */
+	void *addr;
+	
+	/* Size of the memory area */
+	size_t size;
+	/* Link to other areas */
+	link_t link;
+} mem_area_t;
+
+/*
+ * Subphase control structures: subphase termination conditions,
+ * probabilities of individual actions, subphase control structure.
+ */
+
+typedef struct {
+	unsigned int max_cycles;
+	unsigned int no_memory;
+	unsigned int no_allocated;
+} sp_term_cond_t;
+
+typedef struct {
+	unsigned int alloc;
+	unsigned int free;
+} sp_action_prob_t;
+
+typedef struct {
+	const char *name;
+	sp_term_cond_t cond;
+	sp_action_prob_t prob;
+} subphase_t;
+
+/*
+ * Phase control structures: The minimum and maximum block size that
+ * can be allocated during the phase execution, phase control structure.
+ */
+
+typedef struct {
+	size_t min_block_size;
+	size_t max_block_size;
+} ph_alloc_size_t;
+
+typedef struct {
+	const char *name;
+	ph_alloc_size_t alloc;
+	subphase_t *subphases;
+} phase_t;
+
+extern bool error_flag;
+extern size_t mem_allocated;
+extern size_t mem_blocks_count;
+
+#define RETURN_IF_ERROR \
+	do { \
+		if (error_flag) \
+			return; \
+	} while (0)
+
+extern void init_mem(void);
+extern void done_mem(void);
+
+extern mem_block_t *alloc_block(size_t);
+extern void free_block(mem_block_t *);
+extern void fill_block(mem_block_t *);
+extern void check_block(mem_block_t *);
+extern mem_block_t *get_random_block(void);
+
+extern mem_area_t *map_area(size_t);
+extern void fill_area(mem_area_t *);
+extern void unmap_area(mem_area_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/app/tester/mm/malloc1.c
===================================================================
--- uspace/app/tester/mm/malloc1.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/mm/malloc1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,7 +30,6 @@
 
 #include <stdio.h>
-#include <unistd.h>
 #include <stdlib.h>
-#include <malloc.h>
+#include "common.h"
 #include "../tester.h"
 
@@ -45,55 +44,4 @@
  */
 
-/**
- * sizeof_array
- * @array array to determine the size of
- *
- * Returns the size of @array in array elements.
- */
-#define sizeof_array(array) \
-	(sizeof(array) / sizeof((array)[0]))
-
-#define MAX_ALLOC (16 * 1024 * 1024)
-
-/*
- * Subphase control structures: subphase termination conditions,
- * probabilities of individual actions, subphase control structure.
- */
-
-typedef struct {
-	unsigned int max_cycles;
-	unsigned int no_memory;
-	unsigned int no_allocated;
-} sp_term_cond_s;
-
-typedef struct {
-	unsigned int alloc;
-	unsigned int free;
-} sp_action_prob_s;
-
-typedef struct {
-	const char *name;
-	sp_term_cond_s cond;
-	sp_action_prob_s prob;
-} subphase_s;
-
-
-/*
- * Phase control structures: The minimum and maximum block size that
- * can be allocated during the phase execution, phase control structure.
- */
-
-typedef struct {
-	size_t min_block_size;
-	size_t max_block_size;
-} ph_alloc_size_s;
-
-typedef struct {
-	const char *name;
-	ph_alloc_size_s alloc;
-	subphase_s *subphases;
-} phase_s;
-
-
 /*
  * Subphases are defined separately here. This is for two reasons:
@@ -101,5 +49,5 @@
  * how many subphases a phase contains.
  */
-static subphase_s subphases_32B[] = {
+static subphase_t subphases_32B[] = {
 	{
 		.name = "Allocation",
@@ -140,5 +88,5 @@
 };
 
-static subphase_s subphases_128K[] = {
+static subphase_t subphases_128K[] = {
 	{
 		.name = "Allocation",
@@ -179,5 +127,5 @@
 };
 
-static subphase_s subphases_default[] = {
+static subphase_t subphases_default[] = {
 	{
 		.name = "Allocation",
@@ -217,10 +165,9 @@
 	}
 };
-
 
 /*
  * Phase definitions.
  */
-static phase_s phases[] = {
+static phase_t phases[] = {
 	{
 		.name = "32 B memory blocks",
@@ -257,307 +204,10 @@
 };
 
-
-/*
- * Global error flag. The flag is set if an error
- * is encountered (overlapping blocks, inconsistent
- * block data, etc.)
- */
-static bool error_flag = false;
-
-/*
- * Memory accounting: the amount of allocated memory and the
- * number and list of allocated blocks.
- */
-static size_t mem_allocated;
-static size_t mem_blocks_count;
-
-static LIST_INITIALIZE(mem_blocks);
-
-typedef struct {
-	/* Address of the start of the block */
-	void *addr;
-	
-	/* Size of the memory block */
-	size_t size;
-	
-	/* link to other blocks */
-	link_t link;
-} mem_block_s;
-
-typedef mem_block_s *mem_block_t;
-
-
-/** init_mem
- *
- * Initializes the memory accounting structures.
- *
- */
-static void init_mem(void)
+static void do_subphase(phase_t *phase, subphase_t *subphase)
 {
-	mem_allocated = 0;
-	mem_blocks_count = 0;
-}
-
-
-static bool overlap_match(link_t *entry, void *addr, size_t size)
-{
-	mem_block_t mblk = list_get_instance(entry, mem_block_s, link);
-	
-	/* Entry block control structure <mbeg, mend) */
-	uint8_t *mbeg = (uint8_t *) mblk;
-	uint8_t *mend = (uint8_t *) mblk + sizeof(mem_block_s);
-	
-	/* Entry block memory <bbeg, bend) */
-	uint8_t *bbeg = (uint8_t *) mblk->addr;
-	uint8_t *bend = (uint8_t *) mblk->addr + mblk->size;
-	
-	/* Data block <dbeg, dend) */
-	uint8_t *dbeg = (uint8_t *) addr;
-	uint8_t *dend = (uint8_t *) addr + size;
-	
-	/* Check for overlaps */
-	if (((mbeg >= dbeg) && (mbeg < dend)) ||
-		((mend > dbeg) && (mend <= dend)) ||
-		((bbeg >= dbeg) && (bbeg < dend)) ||
-		((bend > dbeg) && (bend <= dend)))
-		return true;
-	
-	return false;
-}
-
-
-/** test_overlap
- *
- * Test whether a block starting at @addr overlaps with another, previously
- * allocated memory block or its control structure.
- *
- * @param addr Initial address of the block
- * @param size Size of the block
- *
- * @return false if the block does not overlap.
- *
- */
-static int test_overlap(void *addr, size_t size)
-{
-	link_t *entry;
-	bool fnd = false;
-	
-	for (entry = mem_blocks.next; entry != &mem_blocks; entry = entry->next) {
-		if (overlap_match(entry, addr, size)) {
-			fnd = true;
-			break;
-		}
-	}
-	
-	return fnd;
-}
-
-
-/** checked_malloc
- *
- * Allocate @size bytes of memory and check whether the chunk comes
- * from the non-mapped memory region and whether the chunk overlaps
- * with other, previously allocated, chunks.
- *
- * @param size Amount of memory to allocate
- *
- * @return NULL if the allocation failed. Sets the global error_flag to
- *         true if the allocation succeeded but is illegal.
- *
- */
-static void *checked_malloc(size_t size)
-{
-	void *data;
-	
-	/* Allocate the chunk of memory */
-	data = malloc(size);
-	if (data == NULL)
-		return NULL;
-	
-	/* Check for overlaps with other chunks */
-	if (test_overlap(data, size)) {
-		TPRINTF("\nError: Allocated block overlaps with another "
-			"previously allocated block.\n");
-		error_flag = true;
-	}
-	
-	return data;
-}
-
-
-/** alloc_block
- *
- * Allocate a block of memory of @size bytes and add record about it into
- * the mem_blocks list. Return a pointer to the block holder structure or
- * NULL if the allocation failed.
- *
- * If the allocation is illegal (e.g. the memory does not come from the
- * right region or some of the allocated blocks overlap with others),
- * set the global error_flag.
- *
- * @param size Size of the memory block
- *
- */
-static mem_block_t alloc_block(size_t size)
-{
-	/* Check for allocation limit */
-	if (mem_allocated >= MAX_ALLOC)
-		return NULL;
-	
-	/* Allocate the block holder */
-	mem_block_t block = (mem_block_t) checked_malloc(sizeof(mem_block_s));
-	if (block == NULL)
-		return NULL;
-	
-	link_initialize(&block->link);
-	
-	/* Allocate the block memory */
-	block->addr = checked_malloc(size);
-	if (block->addr == NULL) {
-		free(block);
-		return NULL;
-	}
-	
-	block->size = size;
-	
-	/* Register the allocated block */
-	list_append(&block->link, &mem_blocks);
-	mem_allocated += size + sizeof(mem_block_s);
-	mem_blocks_count++;
-	
-	return block;
-}
-
-
-/** free_block
- *
- * Free the block of memory and the block control structure allocated by
- * alloc_block. Set the global error_flag if an error occurs.
- *
- * @param block Block control structure
- *
- */
-static void free_block(mem_block_t block)
-{
-	/* Unregister the block */
-	list_remove(&block->link);
-	mem_allocated -= block->size + sizeof(mem_block_s);
-	mem_blocks_count--;
-	
-	/* Free the memory */
-	free(block->addr);
-	free(block);
-}
-
-
-/** expected_value
- *
- * Compute the expected value of a byte located at @pos in memory
- * block described by @blk.
- *
- * @param blk Memory block control structure
- * @param pos Position in the memory block data area
- *
- */
-static inline uint8_t expected_value(mem_block_t blk, uint8_t *pos)
-{
-	return ((unsigned long) blk ^ (unsigned long) pos) & 0xff;
-}
-
-
-/** fill_block
- *
- * Fill the memory block controlled by @blk with data.
- *
- * @param blk Memory block control structure
- *
- */
-static void fill_block(mem_block_t blk)
-{
-	uint8_t *pos;
-	uint8_t *end;
-	
-	for (pos = blk->addr, end = pos + blk->size; pos < end; pos++)
-		*pos = expected_value(blk, pos);
-}
-
-
-/** check_block
- *
- * Check whether the block @blk contains the data it was filled with.
- * Set global error_flag if an error occurs.
- *
- * @param blk Memory block control structure
- *
- */
-static void check_block(mem_block_t blk)
-{
-	uint8_t *pos;
-	uint8_t *end;
-	
-	for (pos = blk->addr, end = pos + blk->size; pos < end; pos++) {
-		if (*pos != expected_value (blk, pos)) {
-			TPRINTF("\nError: Corrupted content of a data block.\n");
-			error_flag = true;
-			return;
-		}
-	}
-}
-
-
-static link_t *list_get_nth(link_t *list, unsigned int i)
-{
-	unsigned int cnt = 0;
-	link_t *entry;
-	
-	for (entry = list->next; entry != list; entry = entry->next) {
-		if (cnt == i)
-			return entry;
-		
-		cnt++;
-	}
-	
-	return NULL;
-}
-
-
-/** get_random_block
- *
- * Select a random memory block from the list of allocated blocks.
- *
- * @return Block control structure or NULL if the list is empty.
- *
- */
-static mem_block_t get_random_block(void)
-{
-	if (mem_blocks_count == 0)
-		return NULL;
-	
-	unsigned int blkidx = rand() % mem_blocks_count;
-	link_t *entry = list_get_nth(&mem_blocks, blkidx);
-	
-	if (entry == NULL) {
-		TPRINTF("\nError: Corrupted list of allocated memory blocks.\n");
-		error_flag = true;
-	}
-	
-	return list_get_instance(entry, mem_block_s, link);
-}
-
-
-#define RETURN_IF_ERROR \
-{ \
-	if (error_flag) \
-		return; \
-}
-
-
-static void do_subphase(phase_s *phase, subphase_s *subphase)
-{
-	unsigned int cycles;
-	for (cycles = 0; /* always */; cycles++) {
-		
-		if (subphase->cond.max_cycles &&
-			cycles >= subphase->cond.max_cycles) {
+	for (unsigned int cycles = 0; /* always */; cycles++) {
+		
+		if ((subphase->cond.max_cycles) &&
+		    (cycles >= subphase->cond.max_cycles)) {
 			/*
 			 * We have performed the required number of
@@ -572,9 +222,12 @@
 		unsigned int rnd = rand() % 100;
 		if (rnd < subphase->prob.alloc) {
-			/* Compute a random number lying in interval <min_block_size, max_block_size> */
+			/*
+			 * Compute a random number lying in interval
+			 * <min_block_size, max_block_size>
+			 */
 			int alloc = phase->alloc.min_block_size +
 			    (rand() % (phase->alloc.max_block_size - phase->alloc.min_block_size + 1));
 			
-			mem_block_t blk = alloc_block(alloc);
+			mem_block_t *blk = alloc_block(alloc);
 			RETURN_IF_ERROR;
 			
@@ -585,12 +238,12 @@
 					break;
 				}
-				
 			} else {
 				TPRINTF("A");
 				fill_block(blk);
+				RETURN_IF_ERROR;
 			}
 			
 		} else if (rnd < subphase->prob.free) {
-			mem_block_t blk = get_random_block();
+			mem_block_t *blk = get_random_block();
 			if (blk == NULL) {
 				TPRINTF("F(R)");
@@ -599,5 +252,4 @@
 					break;
 				}
-				
 			} else {
 				TPRINTF("R");
@@ -614,11 +266,8 @@
 }
 
-
-static void do_phase(phase_s *phase)
+static void do_phase(phase_t *phase)
 {
-	unsigned int subno;
-	
-	for (subno = 0; subno < 3; subno++) {
-		subphase_s *subphase = & phase->subphases [subno];
+	for (unsigned int subno = 0; subno < 3; subno++) {
+		subphase_t *subphase = &phase->subphases[subno];
 		
 		TPRINTF(".. Sub-phase %u (%s)\n", subno + 1, subphase->name);
@@ -632,7 +281,7 @@
 	init_mem();
 	
-	unsigned int phaseno;
-	for (phaseno = 0; phaseno < sizeof_array(phases); phaseno++) {
-		phase_s *phase = &phases[phaseno];
+	for (unsigned int phaseno = 0; phaseno < sizeof_array(phases);
+	    phaseno++) {
+		phase_t *phase = &phases[phaseno];
 		
 		TPRINTF("Entering phase %u (%s)\n", phaseno + 1, phase->name);
@@ -645,4 +294,6 @@
 	}
 	
+	TPRINTF("Cleaning up.\n");
+	done_mem();
 	if (error_flag)
 		return "Test failed";
Index: uspace/app/tester/mm/malloc2.c
===================================================================
--- uspace/app/tester/mm/malloc2.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/mm/malloc2.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include "../tester.h"
+
+const char *test_malloc2(void)
+{
+	int cnt = 0;
+	char *p;
+
+	TPRINTF("Provoking the kernel into overcommitting memory to us...\n");
+	while ((p = malloc(1024 * 1024))) {
+		TPRINTF("%dM ", ++cnt);
+		*p = 'A';
+	}
+	TPRINTF("\nWas refused more memory as expected.\n");
+
+	return NULL;
+}
Index: uspace/app/tester/mm/malloc2.def
===================================================================
--- uspace/app/tester/mm/malloc2.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/mm/malloc2.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,6 @@
+{
+	"malloc2",
+	"Memory reservation feature test",
+	&test_malloc2,
+	false	
+},
Index: uspace/app/tester/mm/malloc3.c
===================================================================
--- uspace/app/tester/mm/malloc3.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/mm/malloc3.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2009 Martin Decky
+ * Copyright (c) 2009 Tomas Bures
+ * Copyright (c) 2009 Lubomir Bulej
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "common.h"
+#include "../tester.h"
+
+/*
+ * The test is a slight adaptation of malloc1 test. The major difference
+ * is that the test forces the heap allocator to create multiple
+ * heap areas by creating disturbing address space areas.
+ */
+
+static subphase_t subphases_32B[] = {
+	{
+		.name = "Allocation",
+		.cond = {
+			.max_cycles = 200,
+			.no_memory = 1,
+			.no_allocated = 0,
+		},
+		.prob = {
+			.alloc = 90,
+			.free = 100
+		}
+	},
+	{
+		.name = "Alloc/Dealloc",
+		.cond = {
+			.max_cycles = 200,
+			.no_memory = 0,
+			.no_allocated = 0,
+		},
+		.prob = {
+			.alloc = 50,
+			.free = 100
+		}
+	},
+	{
+		.name = "Deallocation",
+		.cond = {
+			.max_cycles = 0,
+			.no_memory = 0,
+			.no_allocated = 1,
+		},
+		.prob = {
+			.alloc = 10,
+			.free = 100
+		}
+	}
+};
+
+static subphase_t subphases_128K[] = {
+	{
+		.name = "Allocation",
+		.cond = {
+			.max_cycles = 0,
+			.no_memory = 1,
+			.no_allocated = 0,
+		},
+		.prob = {
+			.alloc = 70,
+			.free = 100
+		}
+	},
+	{
+		.name = "Alloc/Dealloc",
+		.cond = {
+			.max_cycles = 30,
+			.no_memory = 0,
+			.no_allocated = 0,
+		},
+		.prob = {
+			.alloc = 50,
+			.free = 100
+		}
+	},
+	{
+		.name = "Deallocation",
+		.cond = {
+			.max_cycles = 0,
+			.no_memory = 0,
+			.no_allocated = 1,
+		},
+		.prob = {
+			.alloc = 30,
+			.free = 100
+		}
+	}
+};
+
+static subphase_t subphases_default[] = {
+	{
+		.name = "Allocation",
+		.cond = {
+			.max_cycles = 0,
+			.no_memory = 1,
+			.no_allocated = 0,
+		},
+		.prob = {
+			.alloc = 90,
+			.free = 100
+		}
+	},
+	{
+		.name = "Alloc/Dealloc",
+		.cond = {
+			.max_cycles = 200,
+			.no_memory = 0,
+			.no_allocated = 0,
+		},
+		.prob = {
+			.alloc = 50,
+			.free = 100
+		}
+	},
+	{
+		.name = "Deallocation",
+		.cond = {
+			.max_cycles = 0,
+			.no_memory = 0,
+			.no_allocated = 1,
+		},
+		.prob = {
+			.alloc = 10,
+			.free = 100
+		}
+	}
+};
+
+/*
+ * Phase definitions.
+ */
+static phase_t phases[] = {
+	{
+		.name = "32 B memory blocks",
+		.alloc = {
+			.min_block_size = 32,
+			.max_block_size = 32
+		},
+		.subphases = subphases_32B
+	},
+	{
+		.name = "128 KB memory blocks",
+		.alloc = {
+			.min_block_size = 128 * 1024,
+			.max_block_size = 128 * 1024
+		},
+		.subphases = subphases_128K
+	},
+	{
+		.name = "2500 B memory blocks",
+		.alloc = {
+			.min_block_size = 2500,
+			.max_block_size = 2500
+		},
+		.subphases = subphases_default
+	},
+	{
+		.name = "1 B .. 250000 B memory blocks",
+		.alloc = {
+			.min_block_size = 1,
+			.max_block_size = 250000
+		},
+		.subphases = subphases_default
+	}
+};
+
+static void do_subphase(phase_t *phase, subphase_t *subphase)
+{
+	for (unsigned int cycles = 0; /* always */; cycles++) {
+		
+		if ((subphase->cond.max_cycles) &&
+		    (cycles >= subphase->cond.max_cycles)) {
+			/*
+			 * We have performed the required number of
+			 * cycles. End the current subphase.
+			 */
+			break;
+		}
+		
+		/*
+		 * Decide whether we alloc or free memory in this step.
+		 */
+		unsigned int rnd = rand() % 100;
+		if (rnd < subphase->prob.alloc) {
+			/*
+			 * Compute a random number lying in interval
+			 * <min_block_size, max_block_size>
+			 */
+			int alloc = phase->alloc.min_block_size +
+			    (rand() % (phase->alloc.max_block_size - phase->alloc.min_block_size + 1));
+			
+			mem_block_t *blk = alloc_block(alloc);
+			RETURN_IF_ERROR;
+			
+			if (blk == NULL) {
+				TPRINTF("F(A)");
+				if (subphase->cond.no_memory) {
+					/* We filled the memory. Proceed to next subphase */
+					break;
+				}
+			} else {
+				TPRINTF("A");
+				fill_block(blk);
+				RETURN_IF_ERROR;
+				
+				if ((mem_blocks_count % AREA_GRANULARITY) == 0) {
+					mem_area_t *area = map_area(AREA_SIZE);
+					RETURN_IF_ERROR;
+					
+					if (area != NULL) {
+						TPRINTF("*");
+						fill_area(area);
+						RETURN_IF_ERROR;
+					} else
+						TPRINTF("F(*)");
+				}
+			}
+			
+		} else if (rnd < subphase->prob.free) {
+			mem_block_t *blk = get_random_block();
+			if (blk == NULL) {
+				TPRINTF("F(R)");
+				if (subphase->cond.no_allocated) {
+					/* We free all the memory. Proceed to next subphase. */
+					break;
+				}
+			} else {
+				TPRINTF("R");
+				check_block(blk);
+				RETURN_IF_ERROR;
+				
+				free_block(blk);
+				RETURN_IF_ERROR;
+			}
+		}
+	}
+	
+	TPRINTF("\n..  finished.\n");
+}
+
+static void do_phase(phase_t *phase)
+{
+	for (unsigned int subno = 0; subno < 3; subno++) {
+		subphase_t *subphase = &phase->subphases[subno];
+		
+		TPRINTF(".. Sub-phase %u (%s)\n", subno + 1, subphase->name);
+		do_subphase(phase, subphase);
+		RETURN_IF_ERROR;
+	}
+}
+
+const char *test_malloc3(void)
+{
+	init_mem();
+	
+	for (unsigned int phaseno = 0; phaseno < sizeof_array(phases);
+	    phaseno++) {
+		phase_t *phase = &phases[phaseno];
+		
+		TPRINTF("Entering phase %u (%s)\n", phaseno + 1, phase->name);
+		
+		do_phase(phase);
+		if (error_flag)
+			break;
+		
+		TPRINTF("Phase finished.\n");
+	}
+	
+	TPRINTF("Cleaning up.\n");
+	done_mem();
+	if (error_flag)
+		return "Test failed";
+	
+	return NULL;
+}
Index: uspace/app/tester/mm/malloc3.def
===================================================================
--- uspace/app/tester/mm/malloc3.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/mm/malloc3.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,6 @@
+{
+	"malloc3",
+	"Multi-heap memory allocator test",
+	&test_malloc3,
+	true
+},
Index: uspace/app/tester/mm/mapping1.c
===================================================================
--- uspace/app/tester/mm/mapping1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/mm/mapping1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <as.h>
+#include <errno.h>
+#include "../tester.h"
+
+#define BUFFER1_PAGES 4
+#define BUFFER2_PAGES 2
+
+static void *create_as_area(size_t size)
+{
+	void *result = as_get_mappable_page(size);
+	TPRINTF("Creating AS area...\n");
+	if (as_area_create(result, size,
+	    AS_AREA_READ | AS_AREA_WRITE) != result) {
+		return NULL;
+	}
+	return result;
+}
+
+static void touch_area(void *area, size_t size)
+{
+	TPRINTF("Touching (faulting-in) AS area...\n");
+	
+	char *ptr = (char *)area;
+	
+	while (size > 0) {
+		*ptr = 0;
+		size--;
+		ptr++;
+	}
+}
+
+#define VERIFY_MAPPING(area, page_count, expected_rc) \
+    verify_mapping((area), (page_count), (expected_rc), #expected_rc)
+
+static bool verify_mapping(void *area, int page_count, int expected_rc,
+    const char *expected_rc_str)
+{
+	TPRINTF("Verifying mapping (expected: %s).\n", expected_rc_str);
+	int i;
+	for (i = 0; i < page_count; i++) {
+		void *page_start = ((char *)area) + PAGE_SIZE * i;
+		int rc = as_get_physical_mapping(page_start, NULL);
+		if (rc != expected_rc) {
+			TPRINTF("as_get_physical_mapping() = %d != %d\n",
+			    rc, expected_rc);
+			return false;
+		}
+	}
+	return true;
+}
+
+const char *test_mapping1(void)
+{
+	int rc;
+	
+	size_t buffer1_len = BUFFER1_PAGES * PAGE_SIZE;
+	size_t buffer2_len = BUFFER2_PAGES * PAGE_SIZE;
+	void *buffer1 = create_as_area(buffer1_len);
+	void *buffer2 = create_as_area(buffer2_len);
+	if (!buffer1 || !buffer2) {
+		return "Cannot allocate memory";
+	}
+	
+	touch_area(buffer1, buffer1_len);
+	touch_area(buffer2, buffer2_len);
+	
+	/* Now verify that mapping to physical frames exist. */
+	if (!VERIFY_MAPPING(buffer1, BUFFER1_PAGES, EOK)) {
+		return "Failed to find mapping (buffer1)";
+	}
+	if (!VERIFY_MAPPING(buffer2, BUFFER2_PAGES, EOK)) {
+		return "Failed to find mapping (buffer2)";
+	}
+	
+	/* Let's destroy the buffer1 area and access it again. */
+	rc = as_area_destroy(buffer1);
+	if (rc != EOK) {
+		return "Failed to destroy AS area";
+	}
+	if (!VERIFY_MAPPING(buffer1, BUFFER1_PAGES, ENOENT)) {
+		return "Mapping of destroyed area still exists";
+	}
+	
+	/* clean-up */
+	rc = as_area_destroy(buffer2);
+	if (rc != EOK) {
+		return "Failed to destroy AS area";
+	}
+	
+	return NULL;
+}
Index: uspace/app/tester/mm/mapping1.def
===================================================================
--- uspace/app/tester/mm/mapping1.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/mm/mapping1.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,6 @@
+{
+	"mapping1",
+	"Page mapping test",
+	&test_mapping1,
+	true
+},
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/tester.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -62,6 +62,10 @@
 #include "loop/loop1.def"
 #include "mm/malloc1.def"
+#include "mm/malloc2.def"
+#include "mm/malloc3.def"
+#include "mm/mapping1.def"
 #include "hw/serial/serial1.def"
 #include "hw/misc/virtchar1.def"
+#include "libext2/libext2_1.def"
 	{NULL, NULL, NULL, false}
 };
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/tester.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #include <sys/types.h>
 #include <bool.h>
+#include <stacktrace.h>
 
 #define IPC_TEST_SERVICE  10240
@@ -46,10 +47,26 @@
 extern char **test_argv;
 
+/**
+ * sizeof_array
+ * @array array to determine the size of
+ *
+ * Returns the size of @array in array elements.
+ */
+#define sizeof_array(array) \
+	(sizeof(array) / sizeof((array)[0]))
+
 #define TPRINTF(format, ...) \
-	{ \
+	do { \
 		if (!test_quiet) { \
-			fprintf(stderr, format, ##__VA_ARGS__); \
+			fprintf(stderr, (format), ##__VA_ARGS__); \
 		} \
-	}
+	} while (0)
+
+#define TSTACKTRACE() \
+	do { \
+		if (!test_quiet) { \
+			stacktrace_print(); \
+		} \
+	} while (0)
 
 typedef const char *(*test_entry_t)(void);
@@ -78,6 +95,12 @@
 extern const char *test_loop1(void);
 extern const char *test_malloc1(void);
+extern const char *test_malloc2(void);
+extern const char *test_malloc3(void);
+extern const char *test_mapping1(void);
 extern const char *test_serial1(void);
 extern const char *test_virtchar1(void);
+extern const char *test_libext2_1(void);
+extern const char *test_devman1(void);
+extern const char *test_devman2(void);
 
 extern test_t tests[];
Index: uspace/app/tester/util.c
===================================================================
--- uspace/app/tester/util.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/util.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "util.h"
+#undef ASSERT_EQ_FN_DEF
+#define ASSERT_EQ_FN_DEF(type, fmt, fmtx) \
+bool assert_eq_fn_##type(type exp, type act, const char *act_desc) \
+{ \
+	if (exp != act) { \
+		fprintf(stderr, "Expected %s to be %" fmt " (0x%" fmtx "),"\
+		    " but was %" fmt " (0x%" fmtx ") \n", \
+		    act_desc, exp, exp, act, act); \
+	} \
+	return exp != act; \
+}
+
+#include "util_functions.def"
+
+
+/** @}
+ */
Index: uspace/app/tester/util.h
===================================================================
--- uspace/app/tester/util.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/util.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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
+ * @{
+ */
+/** @file
+ */
+
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#include <stdio.h>
+#include "tester.h"
+
+#define ASSERT_EQ_FN_DEF(type, fmt, fmtx) \
+extern bool assert_eq_fn_##type(type, type, const char *);
+
+#include "util_functions.def"
+
+#define ASSERT_EQ_64(exp, act, msg) \
+{if (assert_eq_fn_uint64_t(exp, act, #act)) {return msg;}}
+
+#define ASSERT_EQ_32(exp, act, msg) \
+{if (assert_eq_fn_uint32_t(exp, act, #act)) {return msg;}}
+
+#define ASSERT_EQ_16(exp, act, msg) \
+{if (assert_eq_fn_uint16_t(exp, act, #act)) {return msg;}}
+
+#define ASSERT_EQ_8(exp, act, msg) \
+{if (assert_eq_fn_uint8_t(exp, act, #act)) {return msg;}}
+
+#endif
+
+/** @}
+ */
Index: uspace/app/tester/util_functions.def
===================================================================
--- uspace/app/tester/util_functions.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/tester/util_functions.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,4 @@
+ASSERT_EQ_FN_DEF(uint8_t, "hhu", "hhx")
+ASSERT_EQ_FN_DEF(uint16_t, "hu", "hx")
+ASSERT_EQ_FN_DEF(uint32_t, "u", "x")
+ASSERT_EQ_FN_DEF(uint64_t, PRIu64, PRIx64)
Index: uspace/app/tester/vfs/vfs1.c
===================================================================
--- uspace/app/tester/vfs/vfs1.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tester/vfs/vfs1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,5 @@
 #include <fcntl.h>
 #include <dirent.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <sys/stat.h>
Index: uspace/app/testread/Makefile
===================================================================
--- uspace/app/testread/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/testread/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2011 Martin Sucha
+# 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 = testread
+
+SOURCES = \
+	testread.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/testread/testread.c
===================================================================
--- uspace/app/testread/testread.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/testread/testread.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 test
+ * @{
+ */
+
+/**
+ * @file	testread.c
+ * This program checks if the file contains a pattern of increasing
+ * 64 bit unsigned integers (that may overflow at some point)
+ * stored in little endian byte order.
+ * This is to verify that the filesystem reads
+ * the files correctly.
+ * If the file does not contain specified pattern, it stops
+ * at the point where the file does not match and prints
+ * the byte offset at which the error occured.
+ * While checking the file, the program displays how many megabytes
+ * it has already read, how long it took to read the last megabyte
+ * and current and average read speed.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mem.h>
+#include <loc.h>
+#include <byteorder.h>
+#include <sys/types.h>
+#include <sys/typefmt.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <time.h>
+
+#define NAME	"testread"
+#define BUFELEMS 1024
+#define MBYTE (1024*1024)
+
+static void syntax_print(void);
+
+int main(int argc, char **argv)
+{
+
+	FILE *file;
+	char *file_name;
+	uint64_t *buf;
+	uint64_t expected;
+	aoff64_t offset;
+	aoff64_t next_mark;
+	aoff64_t last_mark;
+	unsigned int i;
+	bool check_enabled = true;
+	bool progress = true;
+	
+	if (argc < 2) {
+		printf(NAME ": Error, argument missing.\n");
+		syntax_print();
+		return 1;
+	}
+	
+	/* Skip program name */
+	--argc; ++argv;
+	
+	if (argc > 0 && str_cmp(*argv, "--no-check") == 0) {
+		check_enabled = false;
+		--argc; ++argv;
+	}
+	
+	if (argc > 0 && str_cmp(*argv, "--no-progress") == 0) {
+		progress = false;
+		--argc; ++argv;
+	}
+	
+	if (argc != 1) {
+		printf(NAME ": Error, unexpected argument.\n");
+		syntax_print();
+		return 1;
+	}
+	
+	file_name = *argv;
+	
+	buf = calloc(BUFELEMS, sizeof(uint64_t));
+	if (buf == NULL) {
+		printf("Failed allocating buffer\n");
+		return 1;
+	}
+	
+	file = fopen(file_name, "r");
+	if (file == NULL) {
+		printf("Failed opening file\n");
+		return 1;
+	}
+	
+	expected = 0;
+	offset = 0;
+	next_mark = 0;
+	last_mark = 0;
+	struct timeval prev_time;
+	struct timeval start_time;
+	int rc;
+	rc = gettimeofday(&start_time, NULL);
+	if (rc != EOK) {
+		printf("gettimeofday failed\n");
+		fclose(file);
+		free(buf);
+		return 1;
+	}
+	prev_time = start_time;
+	
+	while (!feof(file)) {
+		size_t elems = fread(buf, sizeof(uint64_t), BUFELEMS, file);
+		if (ferror(file)) {
+			printf("Failed reading file\n");
+			fclose(file);
+			free(buf);
+			return 1;
+		}
+		
+		for (i = 0; i < elems; i++) {
+			if (check_enabled && uint64_t_le2host(buf[i]) != expected) {
+				printf("Unexpected value at offset %" PRIuOFF64 "\n", offset);
+				fclose(file);
+				free(buf);
+				return 2;
+			}
+			expected++;
+			offset += sizeof(uint64_t);
+		}
+		
+		if (progress && offset >= next_mark) {
+			struct timeval cur_time;
+			rc = gettimeofday(&cur_time, NULL);
+			if (rc != EOK) {
+				printf("gettimeofday failed\n");
+				fclose(file);
+				free(buf);
+				return 1;
+			}
+			uint32_t last_run = cur_time.tv_sec - prev_time.tv_sec;
+			uint32_t total_time = cur_time.tv_sec - start_time.tv_sec;
+			if (last_run > 0 && total_time > 0) {
+				printf("%" PRIuOFF64 "M - time: %u s, "
+				    "cur: %"PRIuOFF64 " B/s, avg: %" PRIuOFF64 " B/s\n",
+				    offset / MBYTE, last_run,
+				    (offset-last_mark)/last_run,
+				    offset/total_time);
+				prev_time = cur_time;
+				last_mark = offset;
+			}
+			next_mark += MBYTE;
+		}
+	}
+	
+	struct timeval final_time;
+	rc = gettimeofday(&final_time, NULL);
+	if (rc != EOK) {
+		printf("gettimeofday failed\n");
+		fclose(file);
+		free(buf);
+		return 1;
+	}
+	
+	uint32_t total_run_time = final_time.tv_sec - start_time.tv_sec;
+	if (total_run_time > 0) {
+		printf("total bytes: %" PRIuOFF64 
+		    ", total time: %u s, avg speed: %" PRIuOFF64 " B/s\n",
+		    offset,
+		    total_run_time,
+		    offset/total_run_time);
+	}
+	
+	fclose(file);
+	free(buf);
+
+	return 0;
+}
+
+
+static void syntax_print(void)
+{
+	printf("syntax: testread <filename>\n");
+}
+
+/**
+ * @}
+ */
Index: uspace/app/tetris/Makefile
===================================================================
--- uspace/app/tetris/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tetris/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,5 +34,4 @@
 	shapes.c \
 	scores.c \
-	input.c \
 	tetris.c \
 	screen.c
Index: pace/app/tetris/input.c
===================================================================
--- uspace/app/tetris/input.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,197 +1,0 @@
-/*	$OpenBSD: input.c,v 1.12 2005/04/13 02:33:08 deraadt Exp $	*/
-/*    $NetBSD: input.c,v 1.3 1996/02/06 22:47:33 jtc Exp $    */
-
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek and Darren F. Provine.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)input.c	8.1 (Berkeley) 5/31/93
- */
-
-/** @addtogroup tetris
- * @{
- */
-/** @file
- */
-
-/*
- * Tetris input.
- */
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <stdio.h>
-
-#include <errno.h>
-#include <unistd.h>
-#include <str.h>
-
-#include "input.h"
-#include "tetris.h"
-
-#include <async.h>
-#include <vfs/vfs.h>
-#include <io/console.h>
-#include <ipc/console.h>
-
-/* return true iff the given timeval is positive */
-#define	TV_POS(tv) \
-	((tv)->tv_sec > 0 || ((tv)->tv_sec == 0 && (tv)->tv_usec > 0))
-
-/* subtract timeval `sub' from `res' */
-#define	TV_SUB(res, sub) \
-	(res)->tv_sec -= (sub)->tv_sec; \
-	(res)->tv_usec -= (sub)->tv_usec; \
-	if ((res)->tv_usec < 0) { \
-		(res)->tv_usec += 1000000; \
-		(res)->tv_sec--; \
-	}
-
-/* We will use a hack here - if lastchar is non-zero, it is
- * the last character read. We will somehow simulate the select
- * semantics.
- */
-static aid_t getchar_inprog = 0;
-static char lastchar = '\0';
-
-/*
- * Do a `read wait': select for reading from stdin, with timeout *tvp.
- * On return, modify *tvp to reflect the amount of time spent waiting.
- * It will be positive only if input appeared before the time ran out;
- * otherwise it will be zero or perhaps negative.
- *
- * If tvp is nil, wait forever, but return if select is interrupted.
- *
- * Return 0 => no input, 1 => can read() from stdin
- *
- */
-int rwait(struct timeval *tvp)
-{
-	struct timeval starttv, endtv, *s;
-	static ipc_call_t charcall;
-	sysarg_t rc;
-	
-	/*
-	 * Someday, select() will do this for us.
-	 * Just in case that day is now, and no one has
-	 * changed this, we use a temporary.
-	 */
-	if (tvp) {
-		(void) gettimeofday(&starttv, NULL);
-		endtv = *tvp;
-		s = &endtv;
-	} else
-		s = NULL;
-	
-	if (!lastchar) {
-again:
-		if (!getchar_inprog) {
-			getchar_inprog = async_send_0(fphone(stdin),
-			    CONSOLE_GET_EVENT, &charcall);
-		}
-		
-		if (!s)
-			async_wait_for(getchar_inprog, &rc);
-		else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) {
-			tvp->tv_sec = 0;
-			tvp->tv_usec = 0;
-			return (0);
-		}
-		
-		getchar_inprog = 0;
-		if (rc)
-			stop("end of file, help");
-		
-		if (IPC_GET_ARG1(charcall) == KEY_RELEASE)
-			goto again;
-		
-		lastchar = IPC_GET_ARG4(charcall);
-	}
-	
-	if (tvp) {
-		/* since there is input, we may not have timed out */
-		(void) gettimeofday(&endtv, NULL);
-		TV_SUB(&endtv, &starttv);
-		TV_SUB(tvp, &endtv);  /* adjust *tvp by elapsed time */
-	}
-	
-	return 1;
-}
-
-/*
- * `sleep' for the current turn time (using select).
- * Eat any input that might be available.
- */
-void tsleep(void)
-{
-	struct timeval tv;
-	
-	tv.tv_sec = 0;
-	tv.tv_usec = fallrate;
-	while (TV_POS(&tv))
-		if (rwait(&tv)) {
-			lastchar = '\0';
-		} else
-			break;
-}
-
-/*
- * getchar with timeout.
- */
-int tgetchar(void)
-{
-	static struct timeval timeleft;
-	char c;
-	
-	/*
-	 * Reset timeleft to fallrate whenever it is not positive.
-	 * In any case, wait to see if there is any input.  If so,
-	 * take it, and update timeleft so that the next call to
-	 * tgetchar() will not wait as long.  If there is no input,
-	 * make timeleft zero or negative, and return -1.
-	 *
-	 * Most of the hard work is done by rwait().
-	 */
-	if (!TV_POS(&timeleft)) {
-		faster();  /* go faster */
-		timeleft.tv_sec = 0;
-		timeleft.tv_usec = fallrate;
-	}
-	
-	if (!rwait(&timeleft))
-		return -1;
-	
-	c = lastchar;
-	lastchar = '\0';
-	return ((int) (unsigned char) c);
-}
-
-/** @}
- */
Index: pace/app/tetris/input.h
===================================================================
--- uspace/app/tetris/input.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,49 +1,0 @@
-/*	$OpenBSD: input.h,v 1.5 2003/06/03 03:01:41 millert Exp $	*/
-/*	$NetBSD: input.h,v 1.2 1995/04/22 07:42:36 cgd Exp $	*/
-
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek and Darren F. Provine.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)input.h	8.1 (Berkeley) 5/31/93
- */
-
-/** @addtogroup tetris
- * @{
- */
-/** @file
- */
-
-extern int rwait(struct timeval *);
-extern int tgetchar(void);
-extern void tsleep(void);
-
-/** @}
- */
Index: uspace/app/tetris/scores.c
===================================================================
--- uspace/app/tetris/scores.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tetris/scores.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,37 +1,45 @@
-/*	$OpenBSD: scores.c,v 1.11 2006/04/20 03:25:36 ray Exp $	*/
-/*	$NetBSD: scores.c,v 1.2 1995/04/22 07:42:38 cgd Exp $	*/
-
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek and Darren F. Provine.
+/*
+ * Copyright (c) 2011 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)scores.c	8.1 (Berkeley) 5/31/93
+ *
+ * - 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.
+ */
+
+/** Attributations
+ *
+ * scores.c 8.1 (Berkeley) 5/31/93
+ * NetBSD: scores.c,v 1.2 1995/04/22 07:42:38 cgd
+ * OpenBSD: scores.c,v 1.11 2006/04/20 03:25:36 ray
+ *
+ * Based upon BSD Tetris
+ *
+ * Copyright (c) 1992, 1993
+ *      The Regents of the University of California.
+ *      Distributed under BSD license.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek and Darren F. Provine.
+ *
  */
 
@@ -60,5 +68,4 @@
 #include <err.h>
 #include <time.h>
-
 #include "screen.h"
 #include "tetris.h"
@@ -118,5 +125,5 @@
 	int j;
 	size_t off;
-	console_event_t ev;
+	kbd_event_t ev;
 	
 	clear_screen();
@@ -133,6 +140,6 @@
 	
 	while (1) {
-		fflush(stdout);
-		if (!console_get_event(fphone(stdin), &ev))
+		console_flush(console);
+		if (!console_get_kbd_event(console, &ev))
 			exit(1);
 		
Index: uspace/app/tetris/scores.h
===================================================================
--- uspace/app/tetris/scores.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tetris/scores.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,37 +1,45 @@
-/*	$OpenBSD: scores.h,v 1.5 2003/06/03 03:01:41 millert Exp $	*/
-/*	$NetBSD: scores.h,v 1.2 1995/04/22 07:42:40 cgd Exp $	*/
+/*
+ * Copyright (c) 2011 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.
+ */
 
-/*-
+/** Attributations
+ *
+ * scores.h 8.1 (Berkeley) 5/31/93
+ * NetBSD: scores.h,v 1.2 1995/04/22 07:42:40 cgd
+ * OpenBSD: scores.h,v 1.5 2003/06/03 03:01:41 millert
+ *
+ * Based upon BSD Tetris
+ *
  * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.
+ *      Distributed under BSD license.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek and Darren F. Provine.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)scores.h	8.1 (Berkeley) 5/31/93
  */
 
@@ -41,5 +49,4 @@
 /** @file
  */
-
 
 /*
Index: uspace/app/tetris/screen.c
===================================================================
--- uspace/app/tetris/screen.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tetris/screen.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,37 +1,45 @@
-/*	$OpenBSD: screen.c,v 1.13 2006/04/20 03:25:36 ray Exp $	*/
-/*	$NetBSD: screen.c,v 1.4 1995/04/29 01:11:36 mycroft Exp $	*/
-
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek and Darren F. Provine.
+/*
+ * Copyright (c) 2011 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)screen.c	8.1 (Berkeley) 5/31/93
+ *
+ * - 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.
+ */
+
+/** Attributations
+ *
+ * screen.c 8.1 (Berkeley) 5/31/93
+ * NetBSD: screen.c,v 1.4 1995/04/29 01:11:36 mycroft
+ * OpenBSD: screen.c,v 1.13 2006/04/20 03:25:36 ray
+ *
+ * Based upon BSD Tetris
+ *
+ * Copyright (c) 1992, 1993
+ *      The Regents of the University of California.
+ *      Distributed under BSD license.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek and Darren F. Provine.
+ *
  */
 
@@ -69,4 +77,8 @@
 static const struct shape *lastshape;
 
+static suseconds_t timeleft = 0;
+
+console_ctrl_t *console;
+
 
 /*
@@ -82,6 +94,6 @@
 static void start_standout(uint32_t color)
 {
-	fflush(stdout);
-	console_set_rgb_color(fphone(stdout), 0xffffff,
+	console_flush(console);
+	console_set_rgb_color(console, 0xffffff,
 	    use_color ? color : 0x000000);
 }
@@ -89,11 +101,11 @@
 static void resume_normal(void)
 {
-	fflush(stdout);
-	console_set_style(fphone(stdout), STYLE_NORMAL);
+	console_flush(console);
+	console_set_style(console, STYLE_NORMAL);
 }
 
 void clear_screen(void)
 {
-	console_clear(fphone(stdout));
+	console_clear(console);
 	moveto(0, 0);
 }
@@ -105,5 +117,5 @@
 {
 	resume_normal();
-	console_clear(fphone(stdout));
+	console_clear(console);
 	curscore = -1;
 	memset(curscreen, 0, sizeof(curscreen));
@@ -115,5 +127,5 @@
 void scr_init(void)
 {
-	console_cursor_visibility(fphone(stdout), 0);
+	console_cursor_visibility(console, 0);
 	resume_normal();
 	scr_clear();
@@ -122,6 +134,6 @@
 void moveto(sysarg_t r, sysarg_t c)
 {
-	fflush(stdout);
-	console_set_pos(fphone(stdout), c, r);
+	console_flush(console);
+	console_set_pos(console, c, r);
 }
 
@@ -130,5 +142,5 @@
 static int get_display_size(winsize_t *ws)
 {
-	return console_get_size(fphone(stdout), &ws->ws_col, &ws->ws_row);
+	return console_get_size(console, &ws->ws_col, &ws->ws_row);
 }
 
@@ -136,5 +148,5 @@
 {
 	sysarg_t ccap;
-	int rc = console_get_color_cap(fphone(stdout), &ccap);
+	int rc = console_get_color_cap(console, &ccap);
 	
 	if (rc != 0)
@@ -179,5 +191,5 @@
 void scr_end(void)
 {
-	console_cursor_visibility(fphone(stdout), 1);
+	console_cursor_visibility(console, 1);
 }
 
@@ -302,5 +314,5 @@
 		resume_normal();
 	
-	fflush(stdout);
+	console_flush(console);
 }
 
@@ -322,4 +334,80 @@
 }
 
+/** Sleep for the current turn time
+ *
+ * Eat any input that might be available.
+ *
+ */
+void tsleep(void)
+{
+	suseconds_t timeout = fallrate;
+	
+	while (timeout > 0) {
+		kbd_event_t event;
+		
+		if (!console_get_kbd_event_timeout(console, &event, &timeout))
+			break;
+	}
+}
+
+/** Get char with timeout
+ *
+ */
+int tgetchar(void)
+{
+	/*
+	 * Reset timeleft to fallrate whenever it is not positive
+	 * and increase speed.
+	 */
+	
+	if (timeleft <= 0) {
+		faster();
+		timeleft = fallrate;
+	}
+	
+	/*
+	 * Wait to see if there is any input. If so, take it and
+	 * update timeleft so that the next call to tgetchar()
+	 * will not wait as long. If there is no input,
+	 * make timeleft zero and return -1.
+	 */
+	
+	wchar_t c = 0;
+	
+	while (c == 0) {
+		kbd_event_t event;
+		
+		if (!console_get_kbd_event_timeout(console, &event, &timeleft)) {
+			timeleft = 0;
+			return -1;
+		}
+		
+		if (event.type == KEY_PRESS)
+			c = event.c;
+	}
+	
+	return (int) c;
+}
+
+/** Get char without timeout
+ *
+ */
+int twait(void)
+{
+	wchar_t c = 0;
+	
+	while (c == 0) {
+		kbd_event_t event;
+		
+		if (!console_get_kbd_event(console, &event))
+			return -1;
+		
+		if (event.type == KEY_PRESS)
+			c = event.c;
+	}
+	
+	return (int) c;
+}
+
 /** @}
  */
Index: uspace/app/tetris/screen.h
===================================================================
--- uspace/app/tetris/screen.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tetris/screen.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,37 +1,45 @@
-/*	$OpenBSD: screen.h,v 1.5 2003/06/03 03:01:41 millert Exp $	*/
-/*	$NetBSD: screen.h,v 1.2 1995/04/22 07:42:42 cgd Exp $	*/
+/*
+ * Copyright (c) 2011 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.
+ */
 
-/*-
+/** Attributations
+ *
+ * screen.h 8.1 (Berkeley) 5/31/93
+ * NetBSD: screen.h,v 1.2 1995/04/22 07:42:42 cgd
+ * OpenBSD: screen.h,v 1.5 2003/06/03 03:01:41 millert
+ *
+ * Based upon BSD Tetris
+ *
  * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.
+ *      Distributed under BSD license.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek and Darren F. Provine.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)screen.h	8.1 (Berkeley) 5/31/93
  */
 
@@ -48,4 +56,5 @@
 
 #include <sys/types.h>
+#include <io/console.h>
 #include <async.h>
 #include <bool.h>
@@ -56,4 +65,5 @@
 } winsize_t;
 
+extern console_ctrl_t *console;
 extern winsize_t winsize;
 
@@ -61,5 +71,4 @@
 extern void clear_screen(void);
 
-/* just calls putchar; for tputs */
 extern int put(int);
 extern void scr_clear(void);
@@ -70,4 +79,8 @@
 extern void scr_update(void);
 
+extern void tsleep(void);
+extern int tgetchar(void);
+extern int twait(void);
+
 /** @}
  */
Index: uspace/app/tetris/shapes.c
===================================================================
--- uspace/app/tetris/shapes.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tetris/shapes.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,37 +1,45 @@
-/*	$OpenBSD: shapes.c,v 1.8 2004/07/10 07:26:24 deraadt Exp $	*/
-/*	$NetBSD: shapes.c,v 1.2 1995/04/22 07:42:44 cgd Exp $	*/
+/*
+ * Copyright (c) 2011 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.
+ */
 
-/*-
+/** Attributations
+ *
+ * shapes.c 8.1 (Berkeley) 5/31/93
+ * NetBSD: shapes.c,v 1.2 1995/04/22 07:42:44 cgd
+ * OpenBSD: shapes.c,v 1.8 2004/07/10 07:26:24 deraadt
+ *
+ * Based upon BSD Tetris
+ *
  * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.
+ *      Distributed under BSD license.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek and Darren F. Provine.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)shapes.c	8.1 (Berkeley) 5/31/93
  */
 
Index: uspace/app/tetris/tetris.c
===================================================================
--- uspace/app/tetris/tetris.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tetris/tetris.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,37 +1,45 @@
-/*	$OpenBSD: tetris.c,v 1.21 2006/04/20 03:24:12 ray Exp $	*/
-/*	$NetBSD: tetris.c,v 1.2 1995/04/22 07:42:47 cgd Exp $	*/
-
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek and Darren F. Provine.
+/*
+ * Copyright (c) 2011 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)tetris.c	8.1 (Berkeley) 5/31/93
+ *
+ * - 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.
+ */
+
+/** Attributations
+ *
+ * tetris.c 8.1 (Berkeley) 5/31/93
+ * NetBSD: tetris.c,v 1.2 1995/04/22 07:42:47 cgd
+ * OpenBSD: tetris.c,v 1.21 2006/04/20 03:24:12 ray
+ *
+ * Based upon BSD Tetris
+ *
+ * Copyright (c) 1992, 1993
+ *      The Regents of the University of California.
+ *      Distributed under BSD license.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek and Darren F. Provine.
+ *
  */
 
@@ -56,6 +64,4 @@
 #include <unistd.h>
 #include <getopt.h>
-
-#include "input.h"
 #include "scores.h"
 #include "screen.h"
@@ -245,8 +251,10 @@
 	int ch;
 	
+	console = console_init(stdin, stdout);
+	
 	keys = "jkl pq";
 	
 	classic = 0;
-	showpreview = 1; 
+	showpreview = 1;
 	
 	while ((ch = getopt(argc, argv, "ck:ps")) != -1)
@@ -371,6 +379,6 @@
 					scr_msg(key_msg, 0);
 					scr_msg(msg, 1);
-					(void) fflush(stdout);
-				} while (rwait((struct timeval *) NULL) == -1);
+					console_flush(console);
+				} while (!twait());
 				
 				scr_msg(msg, 0);
Index: uspace/app/tetris/tetris.h
===================================================================
--- uspace/app/tetris/tetris.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/tetris/tetris.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,37 +1,45 @@
-/*	$OpenBSD: tetris.h,v 1.9 2003/06/03 03:01:41 millert Exp $	*/
-/*	$NetBSD: tetris.h,v 1.2 1995/04/22 07:42:48 cgd Exp $	*/
+/*
+ * Copyright (c) 2011 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.
+ */
 
-/*-
+/** Attributations
+ *
+ * tetris.h 8.1 (Berkeley) 5/31/93
+ * NetBSD: tetris.h,v 1.2 1995/04/22 07:42:48 cgd
+ * OpenBSD: tetris.h,v 1.9 2003/06/03 03:01:41 millert
+ *
+ * Based upon BSD Tetris
+ *
  * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.
+ *      Distributed under BSD license.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek and Darren F. Provine.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)tetris.h	8.1 (Berkeley) 5/31/93
  */
 
Index: uspace/app/top/Makefile
===================================================================
--- uspace/app/top/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/top/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,6 +33,5 @@
 SOURCES = \
 	top.c \
-	screen.c \
-	input.c
+	screen.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: pace/app/top/input.c
===================================================================
--- uspace/app/top/input.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,200 +1,0 @@
-/*	$OpenBSD: input.c,v 1.12 2005/04/13 02:33:08 deraadt Exp $	*/
-/*    $NetBSD: input.c,v 1.3 1996/02/06 22:47:33 jtc Exp $    */
-
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek and Darren F. Provine.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)input.c	8.1 (Berkeley) 5/31/93
- */
-
-/** @addtogroup top
- * @{
- */
-/** @file
- */
-
-/*
- * Top input.
- */
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <stdio.h>
-
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <str.h>
-
-#include "input.h"
-
-#include <async.h>
-#include <vfs/vfs.h>
-#include <io/console.h>
-#include <ipc/console.h>
-
-#define USEC_COUNT 1000000
-
-/* return true iff the given timeval is positive */
-#define	TV_POS(tv) \
-	((tv)->tv_sec > 0 || ((tv)->tv_sec == 0 && (tv)->tv_usec > 0))
-
-/* subtract timeval `sub' from `res' */
-#define	TV_SUB(res, sub) \
-	(res)->tv_sec -= (sub)->tv_sec; \
-	(res)->tv_usec -= (sub)->tv_usec; \
-	if ((res)->tv_usec < 0) { \
-		(res)->tv_usec += 1000000; \
-		(res)->tv_sec--; \
-	}
-
-/* We will use a hack here - if lastchar is non-zero, it is
- * the last character read. We will somehow simulate the select
- * semantics.
- */
-static aid_t getchar_inprog = 0;
-static char lastchar = '\0';
-
-/*
- * Do a `read wait': select for reading from stdin, with timeout *tvp.
- * On return, modify *tvp to reflect the amount of time spent waiting.
- * It will be positive only if input appeared before the time ran out;
- * otherwise it will be zero or perhaps negative.
- *
- * If tvp is nil, wait forever, but return if select is interrupted.
- *
- * Return 0 => no input, 1 => can read() from stdin
- *
- */
-int rwait(struct timeval *tvp)
-{
-	struct timeval starttv, endtv, *s;
-	static ipc_call_t charcall;
-	sysarg_t rc;
-	
-	/*
-	 * Someday, select() will do this for us.
-	 * Just in case that day is now, and no one has
-	 * changed this, we use a temporary.
-	 */
-	if (tvp) {
-		(void) gettimeofday(&starttv, NULL);
-		endtv = *tvp;
-		s = &endtv;
-	} else
-		s = NULL;
-	
-	if (!lastchar) {
-again:
-		if (!getchar_inprog) {
-			getchar_inprog = async_send_0(fphone(stdin),
-			    CONSOLE_GET_EVENT, &charcall);
-		}
-		
-		if (!s)
-			async_wait_for(getchar_inprog, &rc);
-		else if (async_wait_timeout(getchar_inprog, &rc, s->tv_usec) == ETIMEOUT) {
-			tvp->tv_sec = 0;
-			tvp->tv_usec = 0;
-			return (0);
-		}
-		
-		getchar_inprog = 0;
-		if (rc) {
-			printf("End of file, bug?\n");
-			exit(1);
-		}
-		
-		if (IPC_GET_ARG1(charcall) == KEY_RELEASE)
-			goto again;
-		
-		lastchar = IPC_GET_ARG4(charcall);
-	}
-	
-	if (tvp) {
-		/* since there is input, we may not have timed out */
-		(void) gettimeofday(&endtv, NULL);
-		TV_SUB(&endtv, &starttv);
-		TV_SUB(tvp, &endtv);  /* adjust *tvp by elapsed time */
-	}
-	
-	return 1;
-}
-
-/*
- * `sleep' for the current turn time (using select).
- * Eat any input that might be available.
- */
-void tsleep(unsigned int sec)
-{
-	struct timeval tv;
-	
-	tv.tv_sec = 0;
-	tv.tv_usec = sec * USEC_COUNT;
-	while (TV_POS(&tv))
-		if (rwait(&tv)) {
-			lastchar = '\0';
-		} else
-			break;
-}
-
-/*
- * getchar with timeout.
- */
-int tgetchar(unsigned int sec)
-{
-	static struct timeval timeleft;
-	char c;
-	
-	/*
-	 * Reset timeleft to USEC_COUNT whenever it is not positive.
-	 * In any case, wait to see if there is any input.  If so,
-	 * take it, and update timeleft so that the next call to
-	 * tgetchar() will not wait as long.  If there is no input,
-	 * make timeleft zero or negative, and return -1.
-	 *
-	 * Most of the hard work is done by rwait().
-	 */
-	if (!TV_POS(&timeleft)) {
-		timeleft.tv_sec = 0;
-		timeleft.tv_usec = sec * USEC_COUNT;
-	}
-	
-	if (!rwait(&timeleft))
-		return -1;
-	
-	c = lastchar;
-	lastchar = '\0';
-	return ((int) (unsigned char) c);
-}
-
-/** @}
- */
Index: pace/app/top/input.h
===================================================================
--- uspace/app/top/input.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*	$OpenBSD: input.h,v 1.5 2003/06/03 03:01:41 millert Exp $	*/
-/*	$NetBSD: input.h,v 1.2 1995/04/22 07:42:36 cgd Exp $	*/
-
-/*-
- * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek and Darren F. Provine.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)input.h	8.1 (Berkeley) 5/31/93
- */
-
-/** @addtogroup top
- * @{
- */
-/** @file
- */
-
-#ifndef TOP_INPUT_
-#define TOP_INPUT_
-
-#include <sys/time.h>
-
-extern int rwait(struct timeval *);
-extern int tgetchar(unsigned int sec);
-extern void tsleep(unsigned int sec);
-
-#endif
-
-/** @}
- */
Index: uspace/app/top/screen.c
===================================================================
--- uspace/app/top/screen.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/top/screen.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -46,35 +46,40 @@
 #include "top.h"
 
+#define USEC_COUNT  1000000
+
 static sysarg_t warn_col = 0;
 static sysarg_t warn_row = 0;
+static suseconds_t timeleft = 0;
+
+console_ctrl_t *console;
 
 static void screen_style_normal(void)
 {
-	fflush(stdout);
-	console_set_style(fphone(stdout), STYLE_NORMAL);
+	console_flush(console);
+	console_set_style(console, STYLE_NORMAL);
 }
 
 static void screen_style_inverted(void)
 {
-	fflush(stdout);
-	console_set_style(fphone(stdout), STYLE_INVERTED);
+	console_flush(console);
+	console_set_style(console, STYLE_INVERTED);
 }
 
 static void screen_moveto(sysarg_t col, sysarg_t row)
 {
-	fflush(stdout);
-	console_set_pos(fphone(stdout), col, row);
+	console_flush(console);
+	console_set_pos(console, col, row);
 }
 
 static void screen_get_pos(sysarg_t *col, sysarg_t *row)
 {
-	fflush(stdout);
-	console_get_pos(fphone(stdout), col, row);
+	console_flush(console);
+	console_get_pos(console, col, row);
 }
 
 static void screen_get_size(sysarg_t *col, sysarg_t *row)
 {
-	fflush(stdout);
-	console_get_size(fphone(stdout), col, row);
+	console_flush(console);
+	console_get_size(console, col, row);
 }
 
@@ -84,6 +89,6 @@
 	
 	if (clear) {
-		fflush(stdout);
-		console_clear(fphone(stdout));
+		console_flush(console);
+		console_clear(console);
 	}
 	
@@ -111,6 +116,8 @@
 void screen_init(void)
 {
-	fflush(stdout);
-	console_cursor_visibility(fphone(stdout), false);
+	console = console_init(stdin, stdout);
+	
+	console_flush(console);
+	console_cursor_visibility(console, false);
 	
 	screen_restart(true);
@@ -121,6 +128,6 @@
 	screen_restart(true);
 	
-	fflush(stdout);
-	console_cursor_visibility(fphone(stdout), true);
+	console_flush(console);
+	console_cursor_visibility(console, true);
 }
 
@@ -254,16 +261,16 @@
 	uint64_t used;
 	uint64_t free;
-	char total_suffix;
-	char unavail_suffix;
-	char used_suffix;
-	char free_suffix;
-	
-	order_suffix(data->physmem->total, &total, &total_suffix);
-	order_suffix(data->physmem->unavail, &unavail, &unavail_suffix);
-	order_suffix(data->physmem->used, &used, &used_suffix);
-	order_suffix(data->physmem->free, &free, &free_suffix);
-	
-	printf("memory: %" PRIu64 "%c total, %" PRIu64 "%c unavail, %"
-	    PRIu64 "%c used, %" PRIu64 "%c free", total, total_suffix,
+	const char *total_suffix;
+	const char *unavail_suffix;
+	const char *used_suffix;
+	const char *free_suffix;
+	
+	bin_order_suffix(data->physmem->total, &total, &total_suffix, false);
+	bin_order_suffix(data->physmem->unavail, &unavail, &unavail_suffix, false);
+	bin_order_suffix(data->physmem->used, &used, &used_suffix, false);
+	bin_order_suffix(data->physmem->free, &free, &free_suffix, false);
+	
+	printf("memory: %" PRIu64 "%s total, %" PRIu64 "%s unavail, %"
+	    PRIu64 "%s used, %" PRIu64 "%s free", total, total_suffix,
 	    unavail, unavail_suffix, used, used_suffix, free, free_suffix);
 	screen_newline();
@@ -295,15 +302,15 @@
 		
 		uint64_t resmem;
-		char resmem_suffix;
-		order_suffix(task->resmem, &resmem, &resmem_suffix);
+		const char *resmem_suffix;
+		bin_order_suffix(task->resmem, &resmem, &resmem_suffix, true);
 		
 		uint64_t virtmem;
-		char virtmem_suffix;
-		order_suffix(task->virtmem, &virtmem, &virtmem_suffix);
-		
-		printf("%-8" PRIu64 " %7zu %9" PRIu64 "%c ",
+		const char *virtmem_suffix;
+		bin_order_suffix(task->virtmem, &virtmem, &virtmem_suffix, true);
+		
+		printf("%-8" PRIu64 " %7zu %7" PRIu64 "%s ",
 		    task->task_id, task->threads, resmem, resmem_suffix);
 		print_percent(perc->resmem, 2);
-		printf(" %8" PRIu64 "%c ", virtmem, virtmem_suffix);
+		printf(" %6" PRIu64 "%s ", virtmem, virtmem_suffix);
 		print_percent(perc->virtmem, 2);
 		puts(" ");
@@ -508,5 +515,5 @@
 	}
 	
-	fflush(stdout);
+	console_flush(console);
 }
 
@@ -521,5 +528,41 @@
 	
 	screen_newline();
-	fflush(stdout);
+	console_flush(console);
+}
+
+/** Get char with timeout
+ *
+ */
+int tgetchar(unsigned int sec)
+{
+	/*
+	 * Reset timeleft whenever it is not positive.
+	 */
+	
+	if (timeleft <= 0)
+		timeleft = sec * USEC_COUNT;
+	
+	/*
+	 * Wait to see if there is any input. If so, take it and
+	 * update timeleft so that the next call to tgetchar()
+	 * will not wait as long. If there is no input,
+	 * make timeleft zero and return -1.
+	 */
+	
+	wchar_t c = 0;
+	
+	while (c == 0) {
+		kbd_event_t event;
+		
+		if (!console_get_kbd_event_timeout(console, &event, &timeleft)) {
+			timeleft = 0;
+			return -1;
+		}
+		
+		if (event.type == KEY_PRESS)
+			c = event.c;
+	}
+	
+	return (int) c;
 }
 
Index: uspace/app/top/screen.h
===================================================================
--- uspace/app/top/screen.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/top/screen.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,8 @@
 #define TOP_SCREEN_H_
 
+#include <io/console.h>
 #include "top.h"
+
+extern console_ctrl_t *console;
 
 extern void screen_init(void);
@@ -42,4 +45,6 @@
 extern void print_warning(const char *, ...);
 
+extern int tgetchar(unsigned int);
+
 #endif
 
Index: uspace/app/top/top.c
===================================================================
--- uspace/app/top/top.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/top/top.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,9 +42,7 @@
 #include <thread.h>
 #include <sys/time.h>
-#include <arch/barrier.h>
 #include <errno.h>
 #include <sort.h>
 #include "screen.h"
-#include "input.h"
 #include "top.h"
 
Index: uspace/app/trace/ipc_desc.c
===================================================================
--- uspace/app/trace/ipc_desc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/trace/ipc_desc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,5 +33,5 @@
  */
 
-#include <ipc/common.h>
+#include <abi/ipc/methods.h>
 #include <stdlib.h>
 #include "ipc_desc.h"
@@ -39,16 +39,14 @@
 ipc_m_desc_t ipc_methods[] = {
 	/* System methods */
-	{ IPC_M_CONNECT_TO_ME,	"CONNECT_TO_ME" },
-	{ IPC_M_CONNECT_ME_TO,	"CONNECT_ME_TO" },
-	{ IPC_M_PHONE_HUNGUP,	"PHONE_HUNGUP" },
-	{ IPC_M_SHARE_OUT,	"SHARE_OUT" },
-	{ IPC_M_SHARE_IN,	"SHARE_IN" },
-	{ IPC_M_DATA_WRITE,	"DATA_WRITE" },
-	{ IPC_M_DATA_READ,	"DATA_READ" },
-	{ IPC_M_DEBUG_ALL,	"DEBUG_ALL" },
-
-	/* Well-known methods */
-	{ IPC_M_PING,		"PING" },
-
+	{ IPC_M_PHONE_HUNGUP,  "PHONE_HUNGUP" },
+	{ IPC_M_CONNECT_ME,    "CONNECT_ME" },
+	{ IPC_M_CONNECT_ME_TO, "CONNECT_ME_TO" },
+	{ IPC_M_CONNECT_TO_ME, "CONNECT_TO_ME" },
+	{ IPC_M_SHARE_OUT,     "SHARE_OUT" },
+	{ IPC_M_SHARE_IN,      "SHARE_IN" },
+	{ IPC_M_DATA_WRITE,    "DATA_WRITE" },
+	{ IPC_M_DATA_READ,     "DATA_READ" },
+	{ IPC_M_DEBUG,         "DEBUG" },
+	
 	/* Terminating entry */
 	{ 0, NULL }
Index: uspace/app/trace/ipcp.c
===================================================================
--- uspace/app/trace/ipcp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/trace/ipcp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 #include <adt/hash_table.h>
 #include <sys/typefmt.h>
-
+#include <abi/ipc/methods.h>
 #include "ipc_desc.h"
 #include "proto.h"
@@ -268,17 +268,15 @@
 	proto_t *proto;
 	int cphone;
-
+	
 	sysarg_t *resp;
 	oper_t *oper;
 	int i;
-
-//	printf("parse_answer\n");
-
+	
 	phone = pcall->phone_hash;
 	method = IPC_GET_IMETHOD(pcall->question);
 	retval = IPC_GET_RETVAL(*answer);
-
+	
 	resp = answer->args;
-
+	
 	if ((display_mask & DM_IPC) != 0) {
 		printf("Response to %p: retval=%" PRIdn ", args = (%" PRIun ", "
@@ -288,11 +286,12 @@
 		    IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
 	}
-
+	
 	if ((display_mask & DM_USER) != 0) {
 		oper = pcall->oper;
-
-		if (oper != NULL && (oper->rv_type != V_VOID || oper->respc > 0)) {
+		
+		if ((oper != NULL) &&
+		    ((oper->rv_type != V_VOID) || (oper->respc > 0))) {
 			printf("->");
-
+			
 			if (oper->rv_type != V_VOID) {
 				putchar(' ');
@@ -304,25 +303,29 @@
 				putchar('(');
 				for (i = 1; i <= oper->respc; ++i) {
-					if (i > 1) printf(", ");
+					if (i > 1)
+						printf(", ");
 					val_print(resp[i], oper->resp_type[i - 1]);
 				}
 				putchar(')');
 			}
-
+			
 			putchar('\n');
 		}
 	}
-
-	if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
+	
+	if ((phone == PHONE_NS) && (method == IPC_M_CONNECT_ME_TO) &&
+	    (retval == 0)) {
 		/* Connected to a service (through NS) */
 		service = IPC_GET_ARG1(pcall->question);
 		proto = proto_get_by_srv(service);
-		if (proto == NULL) proto = proto_unknown;
-
+		if (proto == NULL)
+			proto = proto_unknown;
+		
 		cphone = IPC_GET_ARG5(*answer);
 		if ((display_mask & DM_SYSTEM) != 0) {
 			printf("Registering connection (phone %d, protocol: %s)\n", cphone,
-		    		proto->name);
-		}
+		    proto->name);
+		}
+		
 		ipcp_connection_set(cphone, 0, proto);
 	}
@@ -334,7 +337,5 @@
 	pending_call_t *pcall;
 	unsigned long key[1];
-
-//	printf("ipcp_call_in()\n");
-
+	
 	if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
 		/* Not a response */
@@ -344,11 +345,12 @@
 		return;
 	}
-
+	
 	hash = hash & ~IPC_CALLID_ANSWERED;
 	key[0] = hash;
-
+	
 	item = hash_table_find(&pending_calls, key);
-	if (item == NULL) return; // No matching question found
-
+	if (item == NULL)
+		return; /* No matching question found */
+	
 	/*
 	 * Response matched to question.
@@ -357,5 +359,5 @@
 	pcall = hash_table_get_instance(item, pending_call_t, link);
 	hash_table_remove(&pending_calls, key, 1);
-
+	
 	parse_answer(hash, pcall, call);
 	free(pcall);
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/trace/syscalls.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,5 +33,5 @@
  */
 
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 #include "syscalls.h"
 #include "trace.h"
@@ -40,4 +40,5 @@
     [SYS_KLOG] ={ "klog",				3,	V_INT_ERRNO },
     [SYS_TLS_SET] = { "tls_set",			1,	V_ERRNO },
+
     [SYS_THREAD_CREATE] = { "thread_create",		3,	V_ERRNO },
     [SYS_THREAD_EXIT] = { "thread_exit",		1,	V_ERRNO },
@@ -79,5 +80,5 @@
     [SYS_SYSINFO_GET_DATA] = { "sysinfo_get_data",		5,	V_ERRNO },
 
-    [SYS_DEBUG_ENABLE_CONSOLE] = { "debug_enable_console", 0,	V_ERRNO },
+    [SYS_DEBUG_ACTIVATE_CONSOLE] = { "debug_activate_console", 0,	V_ERRNO },
     [SYS_IPC_CONNECT_KBOX] = { "ipc_connect_kbox",	1,	V_ERRNO }
 };
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/app/trace/trace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -50,8 +50,9 @@
 #include <sys/types.h>
 #include <sys/typefmt.h>
+#include <vfs/vfs.h>
 
 #include <libc.h>
 
-// Temporary: service and method names
+/* Temporary: service and method names */
 #include "proto.h"
 #include <ipc/services.h>
@@ -72,5 +73,5 @@
 ipc_call_t thread_ipc_req[THBUF_SIZE];
 
-int phoneid;
+async_sess_t *sess;
 bool abort_trace;
 
@@ -81,5 +82,5 @@
 
 static bool cev_valid;
-static console_event_t cev;
+static kbd_event_t cev;
 
 void thread_trace_start(uintptr_t thread_hash);
@@ -146,36 +147,33 @@
 static int connect_task(task_id_t task_id)
 {
-	int rc;
-
-	rc = async_connect_kbox(task_id);
-
-	if (rc == ENOTSUP) {
-		printf("You do not have userspace debugging support "
-		    "compiled in the kernel.\n");
-		printf("Compile kernel with 'Support for userspace debuggers' "
-		    "(CONFIG_UDEBUG) enabled.\n");
-		return rc;
-	}
-
-	if (rc < 0) {
+	async_sess_t *ksess = async_connect_kbox(task_id);
+	
+	if (!ksess) {
+		if (errno == ENOTSUP) {
+			printf("You do not have userspace debugging support "
+			    "compiled in the kernel.\n");
+			printf("Compile kernel with 'Support for userspace debuggers' "
+			    "(CONFIG_UDEBUG) enabled.\n");
+			return errno;
+		}
+		
 		printf("Error connecting\n");
-		printf("ipc_connect_task(%" PRIu64 ") -> %d ", task_id, rc);
-		return rc;
-	}
-
-	phoneid = rc;
-
-	rc = udebug_begin(phoneid);
+		printf("ipc_connect_task(%" PRIu64 ") -> %d ", task_id, errno);
+		return errno;
+	}
+	
+	int rc = udebug_begin(ksess);
 	if (rc < 0) {
 		printf("udebug_begin() -> %d\n", rc);
 		return rc;
 	}
-
-	rc = udebug_set_evmask(phoneid, UDEBUG_EM_ALL);
+	
+	rc = udebug_set_evmask(ksess, UDEBUG_EM_ALL);
 	if (rc < 0) {
 		printf("udebug_set_evmask(0x%x) -> %d\n ", UDEBUG_EM_ALL, rc);
 		return rc;
 	}
-
+	
+	sess = ksess;
 	return 0;
 }
@@ -188,5 +186,5 @@
 	int i;
 
-	rc = udebug_thread_read(phoneid, thread_hash_buf,
+	rc = udebug_thread_read(sess, thread_hash_buf,
 		THBUF_SIZE*sizeof(unsigned), &tb_copied, &tb_needed);
 	if (rc < 0) {
@@ -314,5 +312,5 @@
 
 	memset(&call, 0, sizeof(call));
-	rc = udebug_mem_read(phoneid, &call.args, sc_args[1], sizeof(call.args));
+	rc = udebug_mem_read(sess, &call.args, sc_args[1], sizeof(call.args));
 
 	if (rc >= 0) {
@@ -325,8 +323,7 @@
 	ipc_call_t question, reply;
 	int rc;
-	int phoneidx;
-
-//	printf("sc_ipc_call_sync_fast()\n");
-	phoneidx = sc_args[0];
+	int phoneid;
+
+	phoneid = sc_args[0];
 
 	IPC_SET_IMETHOD(question, sc_args[1]);
@@ -337,14 +334,10 @@
 	IPC_SET_ARG5(question, 0);
 
-//	printf("memset\n");
 	memset(&reply, 0, sizeof(reply));
-//	printf("udebug_mem_read(phone=%d, buffer_ptr=%u, src_addr=%d, n=%d\n",
-//		phoneid, &reply.args, sc_args[5], sizeof(reply.args));
-	rc = udebug_mem_read(phoneid, &reply.args, sc_args[5], sizeof(reply.args));
-//	printf("dmr->%d\n", rc);
-	if (rc < 0) return;
-
-//	printf("call ipc_call_sync\n");
-	ipcp_call_sync(phoneidx, &question, &reply);
+	rc = udebug_mem_read(sess, &reply.args, sc_args[5], sizeof(reply.args));
+	if (rc < 0)
+		return;
+	
+	ipcp_call_sync(phoneid, &question, &reply);
 }
 
@@ -355,5 +348,5 @@
 
 	memset(&question, 0, sizeof(question));
-	rc = udebug_mem_read(phoneid, &question.args, sc_args[1],
+	rc = udebug_mem_read(sess, &question.args, sc_args[1],
 	    sizeof(question.args));
 
@@ -372,5 +365,5 @@
 
 	memset(&reply, 0, sizeof(reply));
-	rc = udebug_mem_read(phoneid, &reply.args, sc_args[2],
+	rc = udebug_mem_read(sess, &reply.args, sc_args[2],
 	    sizeof(reply.args));
 
@@ -391,11 +384,8 @@
 
 	memset(&call, 0, sizeof(call));
-	rc = udebug_mem_read(phoneid, &call, sc_args[0], sizeof(call));
-//	printf("udebug_mem_read(phone %d, dest %d, app-mem src %d, size %d -> %d\n",
-//		phoneid, (int)&call, sc_args[0], sizeof(call), rc);
-
-	if (rc >= 0) {
+	rc = udebug_mem_read(sess, &call, sc_args[0], sizeof(call));
+	
+	if (rc >= 0)
 		ipcp_call_in(&call, sc_rc);
-	}
 }
 
@@ -407,13 +397,8 @@
 
 	/* Read syscall arguments */
-	rc = udebug_args_read(phoneid, thread_hash, sc_args);
-
-	async_serialize_start();
-
-//	printf("[%d] ", thread_id);
+	rc = udebug_args_read(sess, thread_hash, sc_args);
 
 	if (rc < 0) {
 		printf("error\n");
-		async_serialize_end();
 		return;
 	}
@@ -432,6 +417,4 @@
 		break;
 	}
-
-	async_serialize_end();
 }
 
@@ -444,7 +427,5 @@
 
 	/* Read syscall arguments */
-	rc = udebug_args_read(phoneid, thread_hash, sc_args);
-
-	async_serialize_start();
+	rc = udebug_args_read(sess, thread_hash, sc_args);
 
 //	printf("[%d] ", thread_id);
@@ -452,5 +433,4 @@
 	if (rc < 0) {
 		printf("error\n");
-		async_serialize_end();
 		return;
 	}
@@ -481,14 +461,9 @@
 		break;
 	}
-
-	async_serialize_end();
 }
 
 static void event_thread_b(uintptr_t hash)
 {
-	async_serialize_start();
 	printf("New thread, hash %p\n", (void *) hash);
-	async_serialize_end();
-
 	thread_trace_start(hash);
 }
@@ -527,5 +502,5 @@
 
 		/* Run thread until an event occurs */
-		rc = udebug_go(phoneid, thread_hash,
+		rc = udebug_go(sess, thread_hash,
 		    &ev_type, &val0, &val1);
 
@@ -612,21 +587,21 @@
 
 	/* Send default files */
-	fdi_node_t *files[4];
-	fdi_node_t stdin_node;
-	fdi_node_t stdout_node;
-	fdi_node_t stderr_node;
-	
-	if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
-		files[0] = &stdin_node;
+	int *files[4];
+	int fd_stdin;
+	int fd_stdout;
+	int fd_stderr;
+	
+	if ((stdin != NULL) && (fhandle(stdin, &fd_stdin) == EOK))
+		files[0] = &fd_stdin;
 	else
 		files[0] = NULL;
 	
-	if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
-		files[1] = &stdout_node;
+	if ((stdout != NULL) && (fhandle(stdout, &fd_stdout) == EOK))
+		files[1] = &fd_stdout;
 	else
 		files[1] = NULL;
 	
-	if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
-		files[2] = &stderr_node;
+	if ((stderr != NULL) && (fhandle(stderr, &fd_stderr) == EOK))
+		files[2] = &fd_stderr;
 	else
 		files[2] = NULL;
@@ -656,5 +631,7 @@
 {
 	(void) arg;
-
+	
+	console_ctrl_t *console = console_init(stdin, stdout);
+	
 	while (true) {
 		fibril_mutex_lock(&state_lock);
@@ -662,12 +639,12 @@
 			fibril_condvar_wait(&state_cv, &state_lock);
 		fibril_mutex_unlock(&state_lock);
-
-		if (!console_get_event(fphone(stdin), &cev))
+		
+		if (!console_get_kbd_event(console, &cev))
 			return -1;
-
+		
 		fibril_mutex_lock(&state_lock);
 		cev_valid = true;
 		fibril_condvar_broadcast(&state_cv);
-		fibril_mutex_unlock(&state_lock);		
+		fibril_mutex_unlock(&state_lock);
 	}
 }
@@ -675,5 +652,5 @@
 static void trace_task(task_id_t task_id)
 {
-	console_event_t ev;
+	kbd_event_t ev;
 	bool done;
 	int i;
@@ -727,5 +704,5 @@
 		case KC_P:
 			printf("Pause...\n");
-			rc = udebug_stop(phoneid, thash);
+			rc = udebug_stop(sess, thash);
 			if (rc != EOK)
 				printf("Error: stop -> %d\n", rc);
@@ -743,6 +720,6 @@
 	printf("\nTerminate debugging session...\n");
 	abort_trace = true;
-	udebug_end(phoneid);
-	async_hangup(phoneid);
+	udebug_end(sess);
+	async_hangup(sess);
 
 	ipcp_cleanup();
@@ -785,6 +762,4 @@
 	o = oper_new("open", 2, arg_def, V_INT_ERRNO, 0, resp_def);
 	proto_add_oper(p, VFS_IN_OPEN, o);
-	o = oper_new("open_node", 4, arg_def, V_INT_ERRNO, 0, resp_def);
-	proto_add_oper(p, VFS_IN_OPEN_NODE, o);
 	o = oper_new("read", 1, arg_def, V_ERRNO, 1, resp_def);
 	proto_add_oper(p, VFS_IN_READ, o);
@@ -816,4 +791,5 @@
 	proto_register(SERVICE_VFS, p);
 
+#if 0
 	p = proto_new("console");
 
@@ -851,4 +827,5 @@
 	proto_console = p;
 	proto_register(SERVICE_CONSOLE, p);
+#endif
 }
 
@@ -872,5 +849,5 @@
 static display_mask_t parse_display_mask(const char *text)
 {
-	display_mask_t dm;
+	display_mask_t dm = 0;
 	const char *c = text;
 	
Index: uspace/app/usbinfo/Makefile
===================================================================
--- uspace/app/usbinfo/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/usbinfo/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+BINARY = usbinfo
+
+LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS = \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+SOURCES = \
+	desctree.c \
+	dev.c \
+	dump.c \
+	hid.c \
+	info.c \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/usbinfo/desctree.c
===================================================================
--- uspace/app/usbinfo/desctree.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/usbinfo/desctree.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,87 @@
+/*
+ * 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 usbinfo
+ * @{
+ */
+/**
+ * @file
+ * Descriptor tree dump.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+
+#include "usbinfo.h"
+#include <usb/dev/dp.h>
+
+static void browse_descriptor_tree_internal(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *root, size_t depth,
+    dump_descriptor_in_tree_t callback, void *arg)
+{
+	if (root == NULL) {
+		return;
+	}
+	callback(root, depth, arg);
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
+	do {
+		browse_descriptor_tree_internal(parser, data, child, depth + 1,
+		    callback, arg);
+		child = usb_dp_get_sibling_descriptor(parser, data,
+		    root, child);
+	} while (child != NULL);
+}
+
+void browse_descriptor_tree(uint8_t *descriptors, size_t descriptors_size,
+    usb_dp_descriptor_nesting_t *descriptor_nesting,
+    dump_descriptor_in_tree_t callback, size_t initial_depth, void *arg)
+{
+	usb_dp_parser_data_t data = {
+		.data = descriptors,
+		.size = descriptors_size,
+		.arg = NULL
+	};
+
+	usb_dp_parser_t parser = {
+		.nesting = descriptor_nesting
+	};
+
+	browse_descriptor_tree_internal(&parser, &data, descriptors,
+	    initial_depth, callback, arg);
+}
+
+/** @}
+ */
Index: uspace/app/usbinfo/dev.c
===================================================================
--- uspace/app/usbinfo/dev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/usbinfo/dev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2011 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 usbinfo
+ * @{
+ */
+/**
+ * @file
+ * Representation of queried device.
+ */
+#include <usb/dev/pipes.h>
+#include <errno.h>
+#include <str_error.h>
+#include <usb/dev/request.h>
+#include "usbinfo.h"
+
+usbinfo_device_t *prepare_device(const char *name,
+    devman_handle_t hc_handle, usb_address_t dev_addr)
+{
+	usbinfo_device_t *dev = malloc(sizeof(usbinfo_device_t));
+	if (dev == NULL) {
+		fprintf(stderr, NAME ": memory allocation failed.\n");
+		return NULL;
+	}
+
+	int rc;
+	bool transfer_started = false;
+
+	rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to create connection to device %s: %s.\n",
+		    name, str_error(rc));
+		goto leave;
+	}
+
+	rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
+	    &dev->wire);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to create default control pipe to %s: %s.\n",
+		    name, str_error(rc));
+		goto leave;
+	}
+
+	rc = usb_pipe_probe_default_control(&dev->ctrl_pipe);
+	if (rc != EOK) {
+		if (rc == ENOENT) {
+			fprintf(stderr, NAME ": " \
+			    "device %s not present or malfunctioning.\n",
+			    name);
+		} else {
+			fprintf(stderr, NAME ": " \
+			    "probing default control pipe of %s failed: %s.\n",
+			    name, str_error(rc));
+		}
+		goto leave;
+	}
+
+	usb_pipe_start_long_transfer(&dev->ctrl_pipe);
+	transfer_started = true;
+
+	rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
+	    &dev->device_descriptor);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to retrieve device descriptor of %s: %s.\n",
+		    name, str_error(rc));
+		goto leave;
+	}
+
+	rc = usb_request_get_full_configuration_descriptor_alloc(
+	    &dev->ctrl_pipe, 0, (void **)&dev->full_configuration_descriptor,
+	    &dev->full_configuration_descriptor_size);
+	if (rc != EOK) {
+		fprintf(stderr, NAME ": " \
+		    "failed to retrieve configuration descriptor of %s: %s.\n",
+		    name, str_error(rc));
+		goto leave;
+	}
+
+	return dev;
+
+
+leave:
+	if (transfer_started) {
+		usb_pipe_end_long_transfer(&dev->ctrl_pipe);
+	}
+
+	free(dev);
+
+	return NULL;
+}
+
+void destroy_device(usbinfo_device_t *dev)
+{
+	usb_pipe_end_long_transfer(&dev->ctrl_pipe);
+	free(dev);
+}
+
+/** @}
+ */
Index: uspace/app/usbinfo/dump.c
===================================================================
--- uspace/app/usbinfo/dump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/usbinfo/dump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,191 @@
+/*
+ * 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 usbinfo
+ * @{
+ */
+/**
+ * @file
+ * USB querying.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+
+#include "usbinfo.h"
+#include <usb/dev/dp.h>
+
+#define INDENT "  "
+#define BYTES_PER_LINE 12
+
+
+const char *get_indent(size_t level)
+{
+	static const char *indents[] = {
+		INDENT,
+		INDENT INDENT,
+		INDENT INDENT INDENT,
+		INDENT INDENT INDENT INDENT,
+		INDENT INDENT INDENT INDENT INDENT
+	};
+	static size_t indents_count = sizeof(indents)/sizeof(indents[0]);
+	if (level >= indents_count) {
+		return indents[indents_count - 1];
+	}
+	return indents[level];
+}
+
+void dump_buffer(const char *msg, size_t indent,
+    const uint8_t *buffer, size_t length)
+{
+	if (msg != NULL) {
+		printf("%s\n", msg);
+	}
+
+	size_t i;
+	if (length > 0) {
+		printf("%s", get_indent(indent));
+	}
+	for (i = 0; i < length; i++) {
+		printf("0x%02X", buffer[i]);
+		if (((i > 0) && (((i+1) % BYTES_PER_LINE) == 0))
+		    || (i + 1 == length)) {
+			printf("\n");
+			if (i + 1 < length) {
+				printf("%s", get_indent(indent));
+			}
+		} else {
+			printf("  ");
+		}
+	}
+}
+
+void dump_usb_descriptor(uint8_t *descriptor, size_t size)
+{
+	printf("Device descriptor:\n");
+	usb_dump_standard_descriptor(stdout, get_indent(0), "\n",
+	    descriptor, size);
+}
+
+void dump_match_ids(match_id_list_t *matches, const char *line_prefix)
+{
+	list_foreach(matches->ids, link) {
+		match_id_t *match = list_get_instance(link, match_id_t, link);
+
+		printf("%s%3d %s\n", line_prefix, match->score, match->id);
+	}
+}
+
+static void dump_tree_descriptor(uint8_t *descriptor, size_t depth)
+{
+	if (descriptor == NULL) {
+		return;
+	}
+	int type = (int) *(descriptor + 1);
+	const char *name = "unknown";
+	switch (type) {
+#define _TYPE(descriptor_type) \
+		case USB_DESCTYPE_##descriptor_type: name = #descriptor_type; break
+		_TYPE(DEVICE);
+		_TYPE(CONFIGURATION);
+		_TYPE(STRING);
+		_TYPE(INTERFACE);
+		_TYPE(ENDPOINT);
+		_TYPE(HID);
+		_TYPE(HID_REPORT);
+		_TYPE(HID_PHYSICAL);
+		_TYPE(HUB);
+#undef _TYPE
+	}
+	printf("%s%s (0x%02X):\n", get_indent(depth), name, type);
+	usb_dump_standard_descriptor(stdout, get_indent(depth), "\n",
+	    descriptor, descriptor[0]);
+}
+
+static void dump_tree_internal(usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
+    uint8_t *root, size_t depth)
+{
+	if (root == NULL) {
+		return;
+	}
+	dump_tree_descriptor(root, depth);
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
+	do {
+		dump_tree_internal(parser, data, child, depth + 1);
+		child = usb_dp_get_sibling_descriptor(parser, data, root, child);
+	} while (child != NULL);
+}
+
+static void dump_tree(usb_dp_parser_t *parser, usb_dp_parser_data_t *data)
+{
+	uint8_t *ptr = data->data;
+	printf("Descriptor tree:\n");
+	dump_tree_internal(parser, data, ptr, 0);
+}
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+static usb_dp_parser_t parser = {
+	.nesting = descriptor_nesting
+};
+
+void dump_descriptor_tree(uint8_t *descriptors, size_t length)
+{
+	usb_dp_parser_data_t data = {
+		.data = descriptors,
+		.size = length,
+		.arg = NULL
+	};
+
+	dump_tree(&parser, &data);
+}
+
+/** @}
+ */
Index: uspace/app/usbinfo/hid.c
===================================================================
--- uspace/app/usbinfo/hid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/usbinfo/hid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2011 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 usbinfo
+ * @{
+ */
+/**
+ * @file
+ * Dumping of HID-related properties.
+ */
+#include <stdio.h>
+#include <str_error.h>
+#include <usb/classes/classes.h>
+#include <usb/dev/request.h>
+#include <usb/hid/hidparser.h>
+#include <errno.h>
+#include "usbinfo.h"
+
+#define BYTES_PER_LINE 20
+
+typedef enum {
+	HID_DUMP_RAW,
+	HID_DUMP_USAGES
+} hid_dump_type_t;
+
+typedef struct {
+	usbinfo_device_t *dev;
+	hid_dump_type_t dump_type;
+	usb_standard_interface_descriptor_t *last_iface;
+} descriptor_walk_context_t;
+
+static bool is_descriptor_kind(uint8_t *d, usb_descriptor_type_t t)
+{
+	if (d == NULL) {
+		return false;
+	}
+	uint8_t size = d[0];
+	if (size <= 1) {
+		return false;
+	}
+	uint8_t type = d[1];
+	return type == t;
+}
+
+/** Dumps HID report in raw format.
+ *
+ * @param iface_no USB interface the report belongs to.
+ * @param report Report descriptor.
+ * @param size Size of the @p report in bytes.
+ */
+static void dump_hid_report_raw(int iface_no, uint8_t *report, size_t size)
+{
+	printf("%sHID report descriptor for interface %d", get_indent(0),
+	    iface_no);
+	for (size_t i = 0; i < size; i++) {
+		size_t line_idx = i % BYTES_PER_LINE;
+		if (line_idx == 0) {
+			printf("\n%s", get_indent(1));
+		}
+		printf("%02X", (int) report[i]);
+		if (line_idx + 1 < BYTES_PER_LINE) {
+			printf(" ");
+		}
+	}
+	printf("\n");
+}
+
+/** Dumps usages in HID report.
+ *
+ * @param iface_no USB interface the report belongs to.
+ * @param report Parsed report descriptor.
+ */
+static void dump_hid_report_usages(int iface_no, usb_hid_report_t *report)
+{
+	printf("%sParsed HID report descriptor for interface %d\n",
+	    get_indent(0), iface_no);
+	list_foreach(report->reports, report_it) {
+		usb_hid_report_description_t *description = list_get_instance(
+		    report_it, usb_hid_report_description_t, reports_link);
+		printf("%sReport %d (type %d)\n", get_indent(1),
+		    (int) description->report_id,
+		    (int) description->type);
+		list_foreach(description->report_items, item_it) {
+			usb_hid_report_field_t *field = list_get_instance(
+			    item_it, usb_hid_report_field_t, ritems_link);
+			printf("%sUsage page = 0x%04x    Usage = 0x%04x\n",
+			    get_indent(2),
+			    (int) field->usage_page, (int) field->usage);
+		}
+	}
+}
+
+/** Retrieves HID report from given USB device and dumps it.
+ *
+ * @param dump_type In which format to dump the report.
+ * @param ctrl_pipe Default control pipe to the device.
+ * @param iface_no Interface number.
+ * @param report_size Size of the report descriptor.
+ */
+static void retrieve_and_dump_hid_report(hid_dump_type_t dump_type,
+    usb_pipe_t *ctrl_pipe, uint8_t iface_no, size_t report_size)
+{
+	assert(report_size > 0);
+
+	uint8_t *raw_report = malloc(report_size);
+	if (raw_report == NULL) {
+		usb_log_warning(
+		    "Failed to allocate %zuB, skipping interface %d.\n",
+		    report_size, (int) iface_no);
+		return;
+	}
+
+	size_t actual_report_size;
+	int rc = usb_request_get_descriptor(ctrl_pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DESCTYPE_HID_REPORT, 0, iface_no,
+	    raw_report, report_size, &actual_report_size);
+	if (rc != EOK) {
+		usb_log_error("Failed to retrieve HID report descriptor: %s.\n",
+		    str_error(rc));
+		free(raw_report);
+		return;
+	}
+
+	usb_hid_report_t report;
+	rc = usb_hid_parse_report_descriptor(&report, raw_report, report_size);
+	if (rc != EOK) {
+		usb_log_error("Failed to part report descriptor: %s.\n",
+		    str_error(rc));
+	}
+
+	switch (dump_type) {
+	case HID_DUMP_RAW:
+		dump_hid_report_raw(iface_no, raw_report, report_size);
+		break;
+	case HID_DUMP_USAGES:
+		dump_hid_report_usages(iface_no, &report);
+		break;
+	default:
+		assert(false && "unreachable code apparently reached");
+	}
+
+	free(raw_report);
+	usb_hid_free_report(&report);
+}
+
+/** Callback for walking descriptor tree.
+ * This callback remembers current interface and dumps HID report after
+ * encountering HID descriptor.
+ * It dumps only the first report and it expects it to be a normal
+ * report, not a physical one.
+ *
+ * @param raw_descriptor Descriptor as a byte array.
+ * @param depth Descriptor tree depth (currently ignored).
+ * @param arg Custom argument, passed as descriptor_walk_context_t.
+ */
+static void descriptor_walk_callback(uint8_t *raw_descriptor,
+    size_t depth, void *arg)
+{
+	descriptor_walk_context_t *context = (descriptor_walk_context_t *) arg;
+
+	if (is_descriptor_kind(raw_descriptor, USB_DESCTYPE_INTERFACE)) {
+		context->last_iface
+		    = (usb_standard_interface_descriptor_t *) raw_descriptor;
+		return;
+	}
+
+	if (!is_descriptor_kind(raw_descriptor, USB_DESCTYPE_HID)) {
+		return;
+	}
+
+	if (context->last_iface == NULL) {
+		return;
+	}
+
+	usb_standard_hid_descriptor_t *hid_descr
+	    = (usb_standard_hid_descriptor_t *) raw_descriptor;
+
+	if (hid_descr->report_desc_info.type != USB_DESCTYPE_HID_REPORT) {
+		return;
+	}
+
+	size_t report_size = hid_descr->report_desc_info.length;
+
+	if (report_size == 0) {
+		return;
+	}
+
+	retrieve_and_dump_hid_report(context->dump_type,
+	    &context->dev->ctrl_pipe, context->last_iface->interface_number,
+	    report_size);
+}
+
+
+void dump_hidreport_raw(usbinfo_device_t *dev)
+{
+	descriptor_walk_context_t context = {
+		.dev = dev,
+		.dump_type = HID_DUMP_RAW,
+		.last_iface = NULL
+	};
+
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    descriptor_walk_callback, &context);
+}
+
+void dump_hidreport_usages(usbinfo_device_t *dev)
+{
+	descriptor_walk_context_t context = {
+		.dev = dev,
+		.dump_type = HID_DUMP_USAGES,
+		.last_iface = NULL
+	};
+
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    descriptor_walk_callback, &context);
+}
+
+/** @}
+ */
Index: uspace/app/usbinfo/info.c
===================================================================
--- uspace/app/usbinfo/info.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/usbinfo/info.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2011 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 usbinfo
+ * @{
+ */
+/**
+ * @file
+ * Dumping of generic device properties.
+ */
+#include <stdio.h>
+#include <str_error.h>
+#include <errno.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/recognise.h>
+#include <usb/dev/request.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/hub.h>
+#include "usbinfo.h"
+
+void dump_short_device_identification(usbinfo_device_t *dev)
+{
+	printf("%sDevice 0x%04x by vendor 0x%04x\n", get_indent(0),
+	    (int) dev->device_descriptor.product_id,
+	    (int) dev->device_descriptor.vendor_id);
+}
+
+static void dump_match_ids_from_interface(uint8_t *descriptor, size_t depth,
+    void *arg)
+{
+	if (depth != 1) {
+		return;
+	}
+	size_t descr_size = descriptor[0];
+	if (descr_size < sizeof(usb_standard_interface_descriptor_t)) {
+		return;
+	}
+	int descr_type = descriptor[1];
+	if (descr_type != USB_DESCTYPE_INTERFACE) {
+		return;
+	}
+
+	usbinfo_device_t *dev = (usbinfo_device_t *) arg;
+
+	usb_standard_interface_descriptor_t *iface
+	    = (usb_standard_interface_descriptor_t *) descriptor;
+
+	printf("%sInterface #%d match ids (%s, 0x%02x, 0x%02x)\n",
+	    get_indent(0),
+	    (int) iface->interface_number,
+	    usb_str_class(iface->interface_class),
+	    (int) iface->interface_subclass,
+	    (int) iface->interface_protocol);
+
+	match_id_list_t matches;
+	init_match_ids(&matches);
+	usb_device_create_match_ids_from_interface(&dev->device_descriptor,
+	    iface, &matches);
+	dump_match_ids(&matches, get_indent(1));
+	clean_match_ids(&matches);
+}
+
+void dump_device_match_ids(usbinfo_device_t *dev)
+{
+	match_id_list_t matches;
+	init_match_ids(&matches);
+	usb_device_create_match_ids_from_device_descriptor(
+	    &dev->device_descriptor, &matches);
+	printf("%sDevice match ids (0x%04x by 0x%04x, %s)\n", get_indent(0),
+	    (int) dev->device_descriptor.product_id,
+	    (int) dev->device_descriptor.vendor_id,
+	    usb_str_class(dev->device_descriptor.device_class));
+	dump_match_ids(&matches, get_indent(1));
+	clean_match_ids(&matches);
+
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    dump_match_ids_from_interface,
+	    dev);
+}
+
+static void dump_descriptor_tree_brief_device(const char *prefix,
+    usb_standard_device_descriptor_t *descriptor)
+{
+	printf("%sDevice (0x%04x by 0x%04x, %s, %zu configurations)\n", prefix,
+	    (int) descriptor->product_id,
+	    (int) descriptor->vendor_id,
+	    usb_str_class(descriptor->device_class),
+	    (size_t) descriptor->configuration_count);
+}
+
+static void dump_descriptor_tree_brief_configuration(const char *prefix,
+    usb_standard_configuration_descriptor_t *descriptor)
+{
+	printf("%sConfiguration #%d (%zu interfaces, total %zuB)\n", prefix,
+	    (int) descriptor->configuration_number,
+	    (size_t) descriptor->interface_count,
+	    (size_t) descriptor->total_length);
+}
+
+static void dump_descriptor_tree_brief_interface(const char *prefix,
+    usb_standard_interface_descriptor_t *descriptor)
+{
+	printf("%sInterface #%d (%s, 0x%02x, 0x%02x), alternate %d\n", prefix,
+	    (int) descriptor->interface_number,
+	    usb_str_class(descriptor->interface_class),
+	    (int) descriptor->interface_subclass,
+	    (int) descriptor->interface_protocol,
+	    (int) descriptor->alternate_setting);
+}
+
+static void dump_descriptor_tree_brief_endpoint(const char *prefix,
+    usb_standard_endpoint_descriptor_t *descriptor)
+{
+	usb_endpoint_t endpoint_no = descriptor->endpoint_address & 0xF;
+	usb_transfer_type_t transfer = descriptor->attributes & 0x3;
+	usb_direction_t direction = descriptor->endpoint_address & 0x80
+	    ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	printf("%sEndpoint #%d (%s %s, %zu)\n", prefix,
+	    endpoint_no, usb_str_transfer_type(transfer),
+	    direction == USB_DIRECTION_IN ? "in" : "out",
+	    (size_t) descriptor->max_packet_size);
+}
+
+static void dump_descriptor_tree_brief_hid(const char *prefix,
+    usb_standard_hid_descriptor_t *descriptor)
+{
+	printf("%sHID (country %d, %d descriptors)\n", prefix,
+	    (int) descriptor->country_code,
+	    (int) descriptor->class_desc_count);
+}
+
+static void dump_descriptor_tree_brief_hub(const char *prefix,
+    usb_hub_descriptor_header_t *descriptor)
+{
+	printf("%shub (%d ports)\n", prefix,
+	    (int) descriptor->port_count);
+}
+
+
+static void dump_descriptor_tree_callback(uint8_t *descriptor,
+    size_t depth, void *arg)
+{
+	const char *indent = get_indent(depth + 1);
+
+	int descr_type = -1;
+	size_t descr_size = descriptor[0];
+	if (descr_size > 0) {
+		descr_type = descriptor[1];
+	}
+
+	switch (descr_type) {
+
+#define _BRANCH(type_enum, descriptor_type, callback) \
+	case type_enum: \
+		if (descr_size >= sizeof(descriptor_type)) { \
+			callback(indent, (descriptor_type *) descriptor); \
+			if (arg != NULL) { \
+				usb_dump_standard_descriptor(stdout, \
+				    get_indent(depth +2), "\n", \
+				    descriptor, descr_size); \
+			} \
+		} else { \
+			descr_type = -1; \
+		} \
+		break;
+
+		_BRANCH(USB_DESCTYPE_DEVICE,
+		    usb_standard_device_descriptor_t,
+		    dump_descriptor_tree_brief_device);
+		_BRANCH(USB_DESCTYPE_CONFIGURATION,
+		    usb_standard_configuration_descriptor_t,
+		    dump_descriptor_tree_brief_configuration);
+		_BRANCH(USB_DESCTYPE_INTERFACE,
+		    usb_standard_interface_descriptor_t,
+		    dump_descriptor_tree_brief_interface);
+		_BRANCH(USB_DESCTYPE_ENDPOINT,
+		    usb_standard_endpoint_descriptor_t,
+		    dump_descriptor_tree_brief_endpoint);
+		_BRANCH(USB_DESCTYPE_HID,
+		    usb_standard_hid_descriptor_t,
+		    dump_descriptor_tree_brief_hid);
+		/*
+		 * Probably useless, hub descriptor shall not be part of
+		 * configuration descriptor.
+		 */
+		_BRANCH(USB_DESCTYPE_HUB,
+		    usb_hub_descriptor_header_t,
+		    dump_descriptor_tree_brief_hub);
+
+		default:
+			break;
+	}
+
+	if (descr_type == -1) {
+		printf("%sInvalid descriptor.\n", indent);
+	}
+}
+
+void dump_descriptor_tree_brief(usbinfo_device_t *dev)
+{
+	dump_descriptor_tree_callback((uint8_t *)&dev->device_descriptor,
+	    (size_t) -1, NULL);
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    dump_descriptor_tree_callback,
+	    NULL);
+}
+
+void dump_descriptor_tree_full(usbinfo_device_t *dev)
+{
+	dump_descriptor_tree_callback((uint8_t *)&dev->device_descriptor,
+	    (size_t) -1, dev);
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    dump_descriptor_tree_callback,
+	    dev);
+}
+
+static void find_string_indexes_callback(uint8_t *descriptor,
+    size_t depth, void *arg)
+{
+	size_t descriptor_length = descriptor[0];
+	if (descriptor_length <= 1) {
+		return;
+	}
+
+	/*printf("Found string in %s->%s: %zu\n",
+	    #descr_struct, #descr_item, __str_index); */
+#define SET_STRING_INDEX(descr, mask, descr_type, descr_struct, descr_item) \
+	do { \
+		if ((descr)[1] == (descr_type)) { \
+			descr_struct *__type_descr = (descr_struct *) (descr); \
+			size_t __str_index = __type_descr->descr_item; \
+			if ((__str_index > 0) && (__str_index < 64)) { \
+				mask = (mask) | (1 << __str_index); \
+			} \
+		} \
+	} while (0)
+
+	uint64_t *mask = arg;
+
+#define SET_STR(descr_type, descr_struct, descr_item) \
+	SET_STRING_INDEX(descriptor, (*mask), descr_type, descr_struct, descr_item)
+
+	SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
+	    str_manufacturer);
+	SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
+	    str_product);
+	SET_STR(USB_DESCTYPE_DEVICE, usb_standard_device_descriptor_t,
+	    str_serial_number);
+	SET_STR(USB_DESCTYPE_CONFIGURATION, usb_standard_configuration_descriptor_t,
+	    str_configuration);
+	SET_STR(USB_DESCTYPE_INTERFACE, usb_standard_interface_descriptor_t,
+	    str_interface);
+}
+
+
+void dump_strings(usbinfo_device_t *dev)
+{
+	/* Get supported languages. */
+	l18_win_locales_t *langs;
+	size_t langs_count;
+	int rc = usb_request_get_supported_languages(&dev->ctrl_pipe,
+	    &langs, &langs_count);
+	if (rc != EOK) {
+		fprintf(stderr,
+		    NAME ": failed to get list of supported languages: %s.\n",
+		    str_error(rc));
+		return;
+	}
+
+	printf("%sString languages (%zu):", get_indent(0), langs_count);
+	size_t i;
+	for (i = 0; i < langs_count; i++) {
+		printf(" 0x%04x", (int) langs[i]);
+	}
+	printf(".\n");
+
+	/* Find used indexes. Device with more than 64 strings are very rare.
+	 */
+	uint64_t str_mask = 0;
+	find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,
+	    &str_mask);
+	usb_dp_walk_simple(dev->full_configuration_descriptor,
+	    dev->full_configuration_descriptor_size,
+	    usb_dp_standard_descriptor_nesting,
+	    find_string_indexes_callback,
+	    &str_mask);
+
+	/* Get all strings and dump them. */
+	for (i = 0; i < langs_count; i++) {
+		l18_win_locales_t lang = langs[i];
+
+		printf("%sStrings in %s:\n", get_indent(0),
+		    str_l18_win_locale(lang));
+
+		size_t idx;
+		for (idx = 1; idx < 64; idx++) {
+			if ((str_mask & ((uint64_t)1 << idx)) == 0) {
+				continue;
+			}
+			char *string = NULL;
+			rc = usb_request_get_string(&dev->ctrl_pipe, idx, lang,
+			    &string);
+			if ((rc != EOK) && (rc != EEMPTY)) {
+				printf("%sWarn: failed to retrieve string #%zu: %s.\n",
+				    get_indent(1), idx, str_error(rc));
+				continue;
+			}
+			printf("%sString #%zu: \"%s\"\n", get_indent(1),
+			    idx, rc == EOK ? string : "");
+			if (string != NULL) {
+				free(string);
+			}
+		}
+	}
+}
+
+
+void dump_status(usbinfo_device_t *dev)
+{
+	int rc;
+	uint16_t device_status = 0;
+	uint16_t ctrl_pipe_status = 0;
+
+	/* Device status first. */
+	rc = usb_request_get_status(&dev->ctrl_pipe,
+	    USB_REQUEST_RECIPIENT_DEVICE, 0,
+	    &device_status);
+	if (rc != EOK) {
+		printf("%sFailed to get device status: %s.\n",
+		    get_indent(0), str_error(rc));
+		goto try_ctrl_pipe_status;
+	}
+
+	printf("%sDevice status 0x%04x: power=%s, remote-wakeup=%s.\n",
+	    get_indent(0),
+	    device_status,
+	    device_status & USB_DEVICE_STATUS_SELF_POWERED ? "self" : "bus",
+	    device_status & USB_DEVICE_STATUS_REMOTE_WAKEUP ? "yes" : "no");
+
+	/* Interface is not interesting, skipping ;-). */
+
+	/* Control endpoint zero. */
+try_ctrl_pipe_status:
+	rc = usb_request_get_status(&dev->ctrl_pipe,
+	    USB_REQUEST_RECIPIENT_ENDPOINT, 0,
+	    &ctrl_pipe_status);
+	if (rc != EOK) {
+		printf("%sFailed to get control endpoint status: %s.\n",
+		    get_indent(0), str_error(rc));
+		goto leave;
+	}
+
+	printf("%sControl endpoint zero status %04X: halted=%s.\n",
+	    get_indent(0),
+	    ctrl_pipe_status,
+	    ctrl_pipe_status & USB_ENDPOINT_STATUS_HALTED ? "yes" : "no");
+
+leave:
+	return;
+}
+
+/** @}
+ */
Index: uspace/app/usbinfo/main.c
===================================================================
--- uspace/app/usbinfo/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/usbinfo/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2010-2011 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 usbinfo
+ * @{
+ */
+/**
+ * @file
+ * USB querying.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+#include <getopt.h>
+#include <devman.h>
+#include <loc.h>
+#include <usb/hc.h>
+#include <usb/dev/pipes.h>
+#include "usbinfo.h"
+
+static void print_usage(char *app_name)
+{
+#define _INDENT "      "
+#define _OPTION(opt, description) \
+	printf(_INDENT opt "\n" _INDENT _INDENT description "\n")
+
+	printf(NAME ": query USB devices for descriptors\n\n");
+	printf("Usage: %s [options] device [device [device [ ... ]]]\n",
+	    app_name);
+	printf(_INDENT "The device can be specified in two ways.\n");
+	printf(_INDENT "  o Using its devman path, e.g. /hw/pci0/.../usb00_a1.\n");
+	printf(_INDENT "  o Or using BUS.ADDR numbers as printed by lsusb.\n");
+
+	_OPTION("-h --help", "Print this help and exit.");
+	_OPTION("-i --identification", "Brief device identification.");
+	_OPTION("-m --match-ids", "Print match ids generated for the device.");
+	_OPTION("-t --descriptor-tree", "Print descriptor tree.");
+	_OPTION("-T --descriptor-tree-full", "Print detailed descriptor tree");
+	_OPTION("-s --strings", "Try to print all string descriptors.");
+	_OPTION("-S --status", "Get status of the device.");
+	_OPTION("-r --hid-report", "Dump HID report descriptor.");
+	_OPTION("-r --hid-report-usages", "Dump usages of HID report.");
+
+	printf("\n");
+	printf("If no option is specified, `-i' is considered default.\n");
+	printf("\n");
+
+#undef _OPTION
+#undef _INDENT
+}
+
+static struct option long_options[] = {
+	{"help", no_argument, NULL, 'h'},
+	{"identification", no_argument, NULL, 'i'},
+	{"match-ids", no_argument, NULL, 'm'},
+	{"descriptor-tree", no_argument, NULL, 't'},
+	{"descriptor-tree-full", no_argument, NULL, 'T'},
+	{"strings", no_argument, NULL, 's'},
+	{"status", no_argument, NULL, 'S'},
+	{"hid-report", no_argument, NULL, 'r'},
+	{"hid-report-usages", no_argument, NULL, 'R'},
+	{0, 0, NULL, 0}
+};
+static const char *short_options = "himtTsSrR";
+
+static usbinfo_action_t actions[] = {
+	{
+		.opt = 'i',
+		.action = dump_short_device_identification,
+		.active = false
+	},
+	{
+		.opt = 'm',
+		.action = dump_device_match_ids,
+		.active = false
+	},
+	{
+		.opt = 't',
+		.action = dump_descriptor_tree_brief,
+		.active = false
+	},
+	{
+		.opt = 'T',
+		.action = dump_descriptor_tree_full,
+		.active = false
+	},
+	{
+		.opt = 's',
+		.action = dump_strings,
+		.active = false
+	},
+	{
+		.opt = 'S',
+		.action = dump_status,
+		.active = false
+	},
+	{
+		.opt = 'r',
+		.action = dump_hidreport_raw,
+		.active = false
+	},
+	{
+		.opt = 'R',
+		.action = dump_hidreport_usages,
+		.active = false
+	},
+	{
+		.opt = 0
+	}
+};
+
+int main(int argc, char *argv[])
+{
+	if (argc <= 1) {
+		print_usage(argv[0]);
+		return -1;
+	}
+
+	/*
+	 * Process command-line options. They determine what shall be
+	 * done with the device.
+	 */
+	int opt;
+	do {
+		opt = getopt_long(argc, argv,
+		    short_options, long_options, NULL);
+		switch (opt) {
+			case -1:
+				break;
+			case '?':
+				print_usage(argv[0]);
+				return 1;
+			case 'h':
+				print_usage(argv[0]);
+				return 0;
+			default: {
+				int idx = 0;
+				while (actions[idx].opt != 0) {
+					if (actions[idx].opt == opt) {
+						actions[idx].active = true;
+						break;
+					}
+					idx++;
+				}
+				break;
+			}
+		}
+	} while (opt > 0);
+
+	/* Set the default action. */
+	int idx = 0;
+	bool something_active = false;
+	while (actions[idx].opt != 0) {
+		if (actions[idx].active) {
+			something_active = true;
+			break;
+		}
+		idx++;
+	}
+	if (!something_active) {
+		actions[0].active = true;
+	}
+
+	/*
+	 * Go through all devices given on the command line and run the
+	 * specified actions.
+	 */
+	int i;
+	for (i = optind; i < argc; i++) {
+		char *devpath = argv[i];
+
+		/* The initialization is here only to make compiler happy. */
+		devman_handle_t hc_handle = 0;
+		usb_address_t dev_addr = 0;
+		int rc = usb_resolve_device_handle(devpath,
+		    &hc_handle, &dev_addr, NULL);
+		if (rc != EOK) {
+			fprintf(stderr, NAME ": device `%s' not found "
+			    "or not of USB kind, skipping.\n",
+			    devpath);
+			continue;
+		}
+
+		usbinfo_device_t *dev = prepare_device(devpath,
+		    hc_handle, dev_addr);
+		if (dev == NULL) {
+			continue;
+		}
+
+		/* Run actions the user specified. */
+		printf("%s\n", devpath);
+
+		int action = 0;
+		while (actions[action].opt != 0) {
+			if (actions[action].active) {
+				actions[action].action(dev);
+			}
+			action++;
+		}
+
+		/* Destroy the control pipe (close the session etc.). */
+		destroy_device(dev);
+	}
+
+	return 0;
+}
+
+
+/** @}
+ */
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/usbinfo/usbinfo.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,94 @@
+/*
+ * 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 usbinfo
+ * @{
+ */
+/** @file
+ * Common header for usbinfo application.
+ */
+#ifndef USBINFO_USBINFO_H_
+#define USBINFO_USBINFO_H_
+
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+#include <usb/dev/pipes.h>
+#include <usb/debug.h>
+#include <usb/dev/dp.h>
+#include <ipc/devman.h>
+
+typedef struct {
+	usb_pipe_t ctrl_pipe;
+	usb_device_connection_t wire;
+	usb_standard_device_descriptor_t device_descriptor;
+	uint8_t *full_configuration_descriptor;
+	size_t full_configuration_descriptor_size;
+} usbinfo_device_t;
+
+typedef struct {
+	int opt;
+	void (*action)(usbinfo_device_t *dev);
+	bool active;
+} usbinfo_action_t;
+
+
+#define NAME "usbinfo"
+
+void dump_buffer(const char *, size_t, const uint8_t *, size_t);
+const char *get_indent(size_t);
+void dump_match_ids(match_id_list_t *, const char *);
+void dump_usb_descriptor(uint8_t *, size_t);
+void dump_descriptor_tree(uint8_t *, size_t);
+
+static inline void internal_error(int err)
+{
+	fprintf(stderr, NAME ": internal error (%s).\n", str_error(err));
+}
+
+usbinfo_device_t *prepare_device(const char *, devman_handle_t, usb_address_t);
+void destroy_device(usbinfo_device_t *);
+
+typedef void (*dump_descriptor_in_tree_t)(uint8_t *, size_t, void *);
+void browse_descriptor_tree(uint8_t *, size_t, usb_dp_descriptor_nesting_t *,
+    dump_descriptor_in_tree_t, size_t, void *);
+
+
+void dump_short_device_identification(usbinfo_device_t *);
+void dump_device_match_ids(usbinfo_device_t *);
+void dump_descriptor_tree_brief(usbinfo_device_t *);
+void dump_descriptor_tree_full(usbinfo_device_t *);
+void dump_strings(usbinfo_device_t *);
+void dump_status(usbinfo_device_t *);
+void dump_hidreport_raw(usbinfo_device_t *);
+void dump_hidreport_usages(usbinfo_device_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/vuhid/Makefile
===================================================================
--- uspace/app/vuhid/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+# acronym for virtual USB human input device
+# (it is really annoying to write long names)
+BINARY = vuh
+
+LIBS = \
+	$(LIBUSBVIRT_PREFIX)/libusbvirt.a \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS = \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
+	-I$(LIBUSBVIRT_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+
+SOURCES_INTERFACES = \
+	hids/bootkbd.c
+
+SOURCES = \
+	main.c \
+	device.c \
+	ifaces.c \
+	stdreq.c \
+	$(SOURCES_INTERFACES)
+	
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/vuhid/device.c
===================================================================
--- uspace/app/vuhid/device.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/device.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2011 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 usbvirthid
+ * @{
+ */
+/**
+ * @file
+ * Virtual USB HID device.
+ */
+#include "virthid.h"
+#include <errno.h>
+#include <stdio.h>
+#include <str.h>
+#include <assert.h>
+#include <usb/classes/classes.h>
+
+static int on_data_from_device(usbvirt_device_t *dev,
+    usb_endpoint_t ep, usb_transfer_type_t tr_type,
+    void *data, size_t data_size, size_t *actual_size)
+{
+	vuhid_data_t *vuhid = dev->device_data;
+	vuhid_interface_t *iface = vuhid->in_endpoints_mapping[ep];
+	if (iface == NULL) {
+		return ESTALL;
+	}
+
+	if (iface->on_data_in == NULL) {
+		return EBADCHECKSUM;
+	}
+
+	return iface->on_data_in(iface, data, data_size, actual_size);
+}
+
+static int on_data_to_device(usbvirt_device_t *dev,
+    usb_endpoint_t ep, usb_transfer_type_t tr_type,
+    void *data, size_t data_size)
+{
+	vuhid_data_t *vuhid = dev->device_data;
+	vuhid_interface_t *iface = vuhid->out_endpoints_mapping[ep];
+	if (iface == NULL) {
+		return ESTALL;
+	}
+
+	if (iface->on_data_out == NULL) {
+		return EBADCHECKSUM;
+	}
+
+	return iface->on_data_out(iface, data, data_size);
+}
+
+static int interface_life_fibril(void *arg)
+{
+	vuhid_interface_t *iface = arg;
+	vuhid_data_t *hid_data = iface->vuhid_data;
+
+	if (iface->live != NULL) {
+		iface->live(iface);
+	}
+
+	fibril_mutex_lock(&hid_data->iface_count_mutex);
+	hid_data->iface_died_count++;
+	fibril_condvar_broadcast(&hid_data->iface_count_cv);
+	fibril_mutex_unlock(&hid_data->iface_count_mutex);
+
+	return EOK;
+}
+
+
+static vuhid_interface_t *find_interface_by_id(vuhid_interface_t **ifaces,
+    const char *id)
+{
+	if ((ifaces == NULL) || (id == NULL)) {
+		return NULL;
+	}
+	while (*ifaces != NULL) {
+		if (str_cmp((*ifaces)->id, id) == 0) {
+			return *ifaces;
+		}
+		ifaces++;
+	}
+
+	return NULL;
+}
+
+int add_interface_by_id(vuhid_interface_t **interfaces, const char *id,
+    usbvirt_device_t *dev)
+{
+	vuhid_interface_t *iface = find_interface_by_id(interfaces, id);
+	if (iface == NULL) {
+		return ENOENT;
+	}
+
+	if ((iface->in_data_size == 0) && (iface->out_data_size == 0)) {
+		return EEMPTY;
+	}
+
+	/* Already used interface. */
+	if (iface->vuhid_data != NULL) {
+		return EEXISTS;
+	}
+
+	vuhid_data_t *hid_data = dev->device_data;
+
+	/* Check that we have not run out of available endpoints. */
+	if ((iface->in_data_size > 0)
+	    && (hid_data->in_endpoint_first_free >= VUHID_ENDPOINT_MAX)) {
+		return ELIMIT;
+	}
+	if ((iface->out_data_size > 0)
+	    && (hid_data->out_endpoint_first_free >= VUHID_ENDPOINT_MAX)) {
+		return ELIMIT;
+	}
+
+	if (dev->descriptors->configuration->descriptor->interface_count >=
+	    VUHID_INTERFACE_MAX) {
+		return ELIMIT;
+	}
+
+	/*
+	 * How may descriptors we would add?
+	 */
+	/* Start with interface descriptor. */
+	size_t new_descriptor_count = 1;
+	/* Having in/out data size positive means we would need endpoint. */
+	if (iface->in_data_size > 0) {
+		new_descriptor_count++;
+	}
+	if (iface->out_data_size > 0) {
+		new_descriptor_count++;
+	}
+	/* Having report descriptor means adding the HID descriptor. */
+	if (iface->report_descriptor != NULL) {
+		new_descriptor_count++;
+	}
+
+	/* From now on, in case of errors, we goto to error_leave */
+	int rc;
+
+	/*
+	 * Prepare new descriptors.
+	 */
+	size_t descr_count = 0;
+	size_t total_descr_size = 0;
+	usb_standard_interface_descriptor_t *descr_iface = NULL;
+	hid_descriptor_t *descr_hid = NULL;
+	usb_standard_endpoint_descriptor_t *descr_ep_in = NULL;
+	usb_standard_endpoint_descriptor_t *descr_ep_out = NULL;
+
+	size_t ep_count = 0;
+	if (iface->in_data_size > 0) {
+		ep_count++;
+	}
+	if (iface->out_data_size > 0) {
+		ep_count++;
+	}
+	assert(ep_count > 0);
+
+	/* Interface would be needed always. */
+	descr_iface = malloc(sizeof(usb_standard_interface_descriptor_t));
+	if (descr_iface == NULL) {
+		rc = ENOMEM;
+		goto error_leave;
+	}
+	descr_count++;
+	total_descr_size += sizeof(usb_standard_interface_descriptor_t);
+	descr_iface->length = sizeof(usb_standard_interface_descriptor_t);
+	descr_iface->descriptor_type = USB_DESCTYPE_INTERFACE;
+	descr_iface->interface_number
+	    = dev->descriptors->configuration->descriptor->interface_count;
+	descr_iface->alternate_setting = 0;
+	descr_iface->endpoint_count = ep_count;
+	descr_iface->interface_class = USB_CLASS_HID;
+	descr_iface->interface_subclass = iface->usb_subclass;
+	descr_iface->interface_protocol = iface->usb_protocol;
+	descr_iface->str_interface = 0;
+
+	/* Create the HID descriptor. */
+	if (iface->report_descriptor != NULL) {
+		descr_hid = malloc(sizeof(hid_descriptor_t));
+		if (descr_hid == NULL) {
+			rc = ENOMEM;
+			goto error_leave;
+		}
+		descr_count++;
+		total_descr_size += sizeof(hid_descriptor_t);
+		descr_hid->length = sizeof(hid_descriptor_t);
+		descr_hid->type = USB_DESCTYPE_HID;
+		descr_hid->hid_spec_release = 0x101;
+		descr_hid->country_code = 0;
+		descr_hid->descriptor_count = 1;
+		descr_hid->descriptor1_type = USB_DESCTYPE_HID_REPORT;
+		descr_hid->descriptor1_length = iface->report_descriptor_size;
+	}
+
+	/* Prepare the endpoint descriptors. */
+	if (iface->in_data_size > 0) {
+		descr_ep_in = malloc(sizeof(usb_standard_endpoint_descriptor_t));
+		if (descr_ep_in == NULL) {
+			rc = ENOMEM;
+			goto error_leave;
+		}
+		descr_count++;
+		total_descr_size += sizeof(usb_standard_endpoint_descriptor_t);
+		descr_ep_in->length = sizeof(usb_standard_endpoint_descriptor_t);
+		descr_ep_in->descriptor_type = USB_DESCTYPE_ENDPOINT;
+		descr_ep_in->endpoint_address
+		    = 0x80 | hid_data->in_endpoint_first_free;
+		descr_ep_in->attributes = 3;
+		descr_ep_in->max_packet_size = iface->in_data_size;
+		descr_ep_in->poll_interval = 10;
+	}
+	if (iface->out_data_size > 0) {
+		descr_ep_out = malloc(sizeof(usb_standard_endpoint_descriptor_t));
+		if (descr_ep_out == NULL) {
+			rc = ENOMEM;
+			goto error_leave;
+		}
+		descr_count++;
+		total_descr_size += sizeof(usb_standard_endpoint_descriptor_t);
+		descr_ep_out->length = sizeof(usb_standard_endpoint_descriptor_t);
+		descr_ep_out->descriptor_type = USB_DESCTYPE_ENDPOINT;
+		descr_ep_out->endpoint_address
+		    = 0x00 | hid_data->out_endpoint_first_free;
+		descr_ep_out->attributes = 3;
+		descr_ep_out->max_packet_size = iface->out_data_size;
+		descr_ep_out->poll_interval = 10;
+	}
+
+	/* Extend existing extra descriptors with these ones. */
+	usbvirt_device_configuration_extras_t *extra_descriptors
+	    = dev->descriptors->configuration->extra;
+	extra_descriptors = realloc(extra_descriptors,
+	    sizeof(usbvirt_device_configuration_extras_t)
+	    * (dev->descriptors->configuration->extra_count + descr_count));
+	if (extra_descriptors == NULL) {
+		rc = ENOMEM;
+		goto error_leave;
+	}
+
+	/* Launch the "life" fibril. */
+	iface->vuhid_data = hid_data;
+	fid_t life_fibril = fibril_create(interface_life_fibril, iface);
+	if (life_fibril == 0) {
+		rc = ENOMEM;
+		goto error_leave;
+	}
+
+	/* Allocation is okay, we can (actually have to now) overwrite the
+	 * original pointer.
+	 */
+	dev->descriptors->configuration->extra = extra_descriptors;
+	extra_descriptors += dev->descriptors->configuration->extra_count;
+
+	/* Initialize them. */
+#define _APPEND_DESCRIPTOR(descriptor) \
+	do { \
+		if ((descriptor) != NULL) { \
+			extra_descriptors->data = (uint8_t *) (descriptor); \
+			extra_descriptors->length = (descriptor)->length; \
+			extra_descriptors++; \
+		} \
+	} while (0)
+
+	_APPEND_DESCRIPTOR(descr_iface);
+	_APPEND_DESCRIPTOR(descr_hid);
+	_APPEND_DESCRIPTOR(descr_ep_in);
+	_APPEND_DESCRIPTOR(descr_ep_out);
+#undef _APPEND_DESCRIPTOR
+	dev->descriptors->configuration->extra_count += descr_count;
+
+	/*
+	 * Final changes.
+	 * Increase the necessary counters, make endpoint mapping.
+	 *
+	 */
+	if (iface->in_data_size > 0) {
+		hid_data->in_endpoints_mapping[hid_data->in_endpoint_first_free]
+		    = iface;
+		dev->ops->data_in[hid_data->in_endpoint_first_free]
+		    = on_data_from_device;
+		hid_data->in_endpoint_first_free++;
+	}
+	if (iface->out_data_size > 0) {
+		hid_data->out_endpoints_mapping[hid_data->out_endpoint_first_free]
+		    = iface;
+		dev->ops->data_out[hid_data->out_endpoint_first_free]
+		    = on_data_to_device;
+		hid_data->out_endpoint_first_free++;
+	}
+
+	hid_data->interface_mapping[
+	    dev->descriptors->configuration->descriptor->interface_count]
+	    = iface;
+
+	dev->descriptors->configuration->descriptor->interface_count++;
+	dev->descriptors->configuration->descriptor->total_length
+	    += total_descr_size;
+
+	hid_data->iface_count++;
+	fibril_add_ready(life_fibril);
+
+	return EOK;
+
+error_leave:
+	if (descr_iface != NULL) {
+		free(descr_iface);
+	}
+	if (descr_hid != NULL) {
+		free(descr_hid);
+	}
+	if (descr_ep_in != NULL) {
+		free(descr_ep_in);
+	}
+	if (descr_ep_out != NULL) {
+		free(descr_ep_out);
+	}
+
+	return rc;
+}
+
+void wait_for_interfaces_death(usbvirt_device_t *dev)
+{
+	vuhid_data_t *hid_data = dev->device_data;
+
+	fibril_mutex_lock(&hid_data->iface_count_mutex);
+	while (hid_data->iface_died_count < hid_data->iface_count) {
+		fibril_condvar_wait(&hid_data->iface_count_cv,
+		    &hid_data->iface_count_mutex);
+	}
+	fibril_mutex_unlock(&hid_data->iface_count_mutex);
+}
+
+/** @}
+ */
Index: uspace/app/vuhid/hids/bootkbd.c
===================================================================
--- uspace/app/vuhid/hids/bootkbd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/hids/bootkbd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2011 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 usbvirthid
+ * @{
+ */
+/** @file
+ *
+ */
+#include "../virthid.h"
+#include <errno.h>
+#include <usb/debug.h>
+#include <usb/hid/hid.h>
+#include <usb/hid/usages/core.h>
+
+#include "../report.h"
+
+uint8_t report_descriptor[] = {
+	STD_USAGE_PAGE(USB_HIDUT_PAGE_GENERIC_DESKTOP),
+	USAGE1(USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD),
+	START_COLLECTION(COLLECTION_APPLICATION),
+		STD_USAGE_PAGE(USB_HIDUT_PAGE_KEYBOARD),
+		USAGE_MINIMUM1(224),
+		USAGE_MAXIMUM1(231),
+		LOGICAL_MINIMUM1(0),
+		LOGICAL_MAXIMUM1(1),
+		REPORT_SIZE1(1),
+		REPORT_COUNT1(8),
+		/* Modifiers */
+		INPUT(IOF_DATA | IOF_VARIABLE | IOF_ABSOLUTE),
+		REPORT_COUNT1(1),
+		REPORT_SIZE1(8),
+		/* Reserved */
+		INPUT(IOF_CONSTANT),
+		REPORT_COUNT1(5),
+		REPORT_SIZE1(1),
+		STD_USAGE_PAGE(USB_HIDUT_PAGE_LED),
+		USAGE_MINIMUM1(1),
+		USAGE_MAXIMUM1(5),
+		/* LED states */
+		OUTPUT(IOF_DATA | IOF_VARIABLE | IOF_ABSOLUTE),
+		REPORT_COUNT1(1),
+		REPORT_SIZE1(3),
+		/* LED states padding */
+		OUTPUT(IOF_CONSTANT),
+		REPORT_COUNT1(6),
+		REPORT_SIZE1(8),
+		LOGICAL_MINIMUM1(0),
+		LOGICAL_MAXIMUM1(101),
+		STD_USAGE_PAGE(USB_HIDUT_PAGE_KEYBOARD),
+		USAGE_MINIMUM1(0),
+		USAGE_MAXIMUM1(101),
+		/* Key array */
+		INPUT(IOF_DATA | IOF_ARRAY),
+	END_COLLECTION()
+};
+
+#define INPUT_SIZE 8
+
+static uint8_t in_data[] = {
+	     0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	     0, 0, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, // Caps Lock
+	     0, 0, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, // Num Lock
+	     0, 0, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, // Caps Lock
+	1 << 2, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	1 << 2, 0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00,
+	1 << 2, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	     0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static size_t in_data_count = sizeof(in_data)/INPUT_SIZE;
+// FIXME - locking
+static size_t in_data_position = 0;
+
+static int on_data_in(vuhid_interface_t *iface,
+    void *buffer, size_t buffer_size, size_t *act_buffer_size)
+{
+	static size_t last_pos = (size_t) -1;
+	size_t pos = in_data_position;
+	if (pos >= in_data_count) {
+		return EBADCHECKSUM;
+	}
+
+	if (last_pos == pos) {
+		return ENAK;
+	}
+
+	if (buffer_size > INPUT_SIZE) {
+		buffer_size = INPUT_SIZE;
+	}
+
+	if (act_buffer_size != NULL) {
+		*act_buffer_size = buffer_size;
+	}
+
+	memcpy(buffer, in_data + pos * INPUT_SIZE, buffer_size);
+	last_pos = pos;
+
+	return EOK;
+}
+
+static int on_data_out(vuhid_interface_t *iface,
+    void *buffer, size_t buffer_size)
+{
+	if (buffer_size == 0) {
+		return EEMPTY;
+	}
+	uint8_t leds = ((uint8_t *) buffer)[0];
+#define _GET_LED(index, signature) \
+	(((leds) & (1 << index)) ? (signature) : '-')
+	usb_log_info("%s: LEDs = %c%c%c%c%c\n",
+	    iface->name,
+	    _GET_LED(0, '0'), _GET_LED(1, 'A'), _GET_LED(2, 's'),
+	    _GET_LED(3, 'c'), _GET_LED(4, 'k'));
+#undef _GET_LED
+	return EOK;
+}
+
+
+static void live(vuhid_interface_t *iface)
+{
+	async_usleep(1000 * 1000 * 5);
+	usb_log_debug("Boot keyboard comes to life...\n");
+	while (in_data_position < in_data_count) {
+		async_usleep(1000 * 500);
+		in_data_position++;
+	}
+	usb_log_debug("Boot keyboard died.\n");
+}
+
+
+vuhid_interface_t vuhid_interface_bootkbd = {
+	.id = "boot",
+	.name = "boot keyboard",
+	.usb_subclass = USB_HID_SUBCLASS_BOOT,
+	.usb_protocol = USB_HID_PROTOCOL_KEYBOARD,
+
+	.report_descriptor = report_descriptor,
+	.report_descriptor_size = sizeof(report_descriptor),
+
+	.in_data_size = INPUT_SIZE,
+	.on_data_in = on_data_in,
+
+	.out_data_size = 1,
+	.on_data_out = on_data_out,
+
+	.live = live,
+
+	.vuhid_data = NULL
+};
+
+/**
+ * @}
+ */
Index: uspace/app/vuhid/ifaces.c
===================================================================
--- uspace/app/vuhid/ifaces.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/ifaces.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 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 usbvirthid
+ * @{
+ */
+/**
+ * @file
+ * List of known interfaces.
+ */
+#include <stdlib.h>
+#include "ifaces.h"
+
+extern vuhid_interface_t vuhid_interface_bootkbd;
+
+vuhid_interface_t *available_hid_interfaces[] = {
+	&vuhid_interface_bootkbd,
+	NULL
+};
+
+
+/** @}
+ */
Index: uspace/app/vuhid/ifaces.h
===================================================================
--- uspace/app/vuhid/ifaces.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/ifaces.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 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 usbvirthid
+ * @{
+ */
+/** @file
+ *
+ */
+#ifndef VUHID_IFACES_H_
+#define VUHID_IFACES_H_
+
+#include "virthid.h"
+
+extern vuhid_interface_t *available_hid_interfaces[];
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/vuhid/items.h
===================================================================
--- uspace/app/vuhid/items.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/items.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,113 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/** @file
+ * @brief HID Item related functions.
+ */
+#ifndef VUK_ITEM_H_
+#define VUK_ITEM_H_
+
+#include <sys/types.h>
+
+typedef uint8_t report_descriptor_data_t[];
+
+/* Item types. */
+#define ITEM_MAIN 0
+#define ITEM_GLOBAL 1
+#define ITEM_LOCAL 2
+
+
+
+/* Item tags. */
+
+/* Main item tags. */
+#define TAG_INPUT 8
+#define TAG_OUTPUT 9
+#define TAG_FEATURE 11
+#define TAG_COLLECTION 10
+#define TAG_END_COLLECTION 12
+
+/* Global item tags. */
+#define TAG_USAGE_PAGE 0
+#define TAG_LOGICAL_MINIMUM 1
+#define TAG_LOGICAL_MAXIMUM 2
+#define TAG_REPORT_SIZE 7
+#define TAG_REPORT_COUNT 9
+
+/* Local item tags. */
+#define TAG_USAGE 0
+#define TAG_USAGE_MINIMUM 1
+#define TAG_USAGE_MAXIMUM 2
+
+
+/* Bits for Input, Output and Feature items. */
+#define _IOF(value, shift) ((value) << (shift))
+#define IOF_DATA _IOF(0, 0)
+#define IOF_CONSTANT _IOF(1, 0)
+#define IOF_ARRAY _IOF(0, 1)
+#define IOF_VARIABLE _IOF(1, 1)
+#define IOF_ABSOLUTE _IOF(0, 2)
+#define IOF_RELATIVE _IOF(1, 2)
+/* ... */
+
+/* Collection types. */
+#define COLLECTION_PHYSICAL 0x00
+#define COLLECTION_APPLICATION 0x01
+
+
+/** Creates item prefix.
+ * @param size Item size.
+ * @param type Item type.
+ * @param tag Item tag.
+ */
+#define BUILD_ITEM_PREFIX(size, type, tag) \
+	((size) | ((type) << 2) | ((tag) << 4))
+
+/** Create no-data item.
+ * @param type Item type.
+ * @param tag Item tag.
+ */
+#define ITEM_CREATE0(type, tag) \
+	BUILD_ITEM_PREFIX(0, type, tag)
+
+/** Create item with 1-byte data.
+ * @param type Item type.
+ * @param tag Item tag.
+ * @param data Item data (single byte).
+ */
+#define ITEM_CREATE1(type, tag, data) \
+	BUILD_ITEM_PREFIX(1, type, tag), data
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/vuhid/main.c
===================================================================
--- uspace/app/vuhid/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2011 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 usbvirthid
+ * @{
+ */
+/**
+ * @file
+ * Virtual USB HID device.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/hid.h>
+#include <usbvirt/device.h>
+
+#include "virthid.h"
+#include "ifaces.h"
+#include "stdreq.h"
+
+static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
+	{
+		.req_direction = USB_DIRECTION_IN,
+		.req_type = USB_REQUEST_TYPE_STANDARD,
+		.req_recipient = USB_REQUEST_RECIPIENT_INTERFACE,
+		.request = USB_DEVREQ_GET_DESCRIPTOR,
+		.name = "Get_Descriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		.req_direction = USB_DIRECTION_OUT,
+		.req_recipient = USB_REQUEST_RECIPIENT_INTERFACE,
+		.req_type = USB_REQUEST_TYPE_CLASS,
+		.request = USB_HIDREQ_SET_PROTOCOL,
+		.name = "Set_Protocol",
+		.callback = req_set_protocol
+	},
+	{
+		.req_direction = USB_DIRECTION_OUT,
+		.req_recipient = USB_REQUEST_RECIPIENT_INTERFACE,
+		.req_type = USB_REQUEST_TYPE_CLASS,
+		.request = USB_HIDREQ_SET_REPORT,
+		.name = "Set_Report",
+		.callback = req_set_report
+	},
+	{
+		.callback = NULL
+	}
+};
+
+/** Keyboard callbacks.
+ * We abuse the fact that static variables are zero-filled.
+ */
+static usbvirt_device_ops_t hid_ops = {
+	.control = endpoint_zero_handlers,
+};
+
+/** Standard configuration descriptor. */
+static usb_standard_configuration_descriptor_t std_configuration_descriptor = {
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
+	/* Will be patched at runtime. */
+	.total_length = sizeof(usb_standard_configuration_descriptor_t),
+	.interface_count = 0,
+	.configuration_number = 1,
+	.str_configuration = 0,
+	.attributes = 128, /* denotes bus-powered device */
+	.max_power = 50
+};
+
+/** Standard device descriptor. */
+static usb_standard_device_descriptor_t std_device_descriptor = {
+	.length = sizeof(usb_standard_device_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_DEVICE,
+	.usb_spec_version = 0x110,
+	.device_class = USB_CLASS_USE_INTERFACE,
+	.device_subclass = 0,
+	.device_protocol = 0,
+	.max_packet_size = 64,
+	.configuration_count = 1
+};
+
+/** HID configuration. */
+usbvirt_device_configuration_t configuration = {
+	.descriptor = &std_configuration_descriptor,
+	.extra = NULL,
+	.extra_count = 0
+};
+
+/** HID standard descriptors. */
+usbvirt_descriptors_t descriptors = {
+	.device = &std_device_descriptor,
+	.configuration = &configuration,
+	.configuration_count = 1,
+};
+
+static vuhid_data_t vuhid_data = {
+	.in_endpoints_mapping = { NULL },
+	.in_endpoint_first_free = 1,
+	.out_endpoints_mapping = { NULL },
+	.out_endpoint_first_free = 1,
+
+	.iface_count = 0,
+	.iface_died_count = 0
+	// mutex and CV must be initialized elsewhere
+};
+
+
+/** Keyboard device.
+ * Rest of the items will be initialized later.
+ */
+static usbvirt_device_t hid_dev = {
+	.ops = &hid_ops,
+	.descriptors = &descriptors,
+	.name = "HID",
+	.device_data = &vuhid_data
+};
+
+
+int main(int argc, char * argv[])
+{
+	int rc;
+
+	usb_log_enable(USB_LOG_LEVEL_DEBUG2, "vusbhid");
+
+	fibril_mutex_initialize(&vuhid_data.iface_count_mutex);
+	fibril_condvar_initialize(&vuhid_data.iface_count_cv);
+
+	/* Determine which interfaces to initialize. */
+	int i;
+	for (i = 1; i < argc; i++) {
+		rc = add_interface_by_id(available_hid_interfaces, argv[i],
+		    &hid_dev);
+		if (rc != EOK) {
+			fprintf(stderr, "Failed to add device `%s': %s.\n",
+			    argv[i], str_error(rc));
+		} else {
+			printf("Added device `%s'.\n", argv[i]);
+		}
+	}
+
+	for (i = 0; i < (int) hid_dev.descriptors->configuration->extra_count; i++) {
+		usb_log_debug("Found extra descriptor: %s.\n",
+		    usb_debug_str_buffer(
+		        hid_dev.descriptors->configuration->extra[i].data,
+		        hid_dev.descriptors->configuration->extra[i].length,
+		        0));
+	}
+
+	rc = usbvirt_device_plug(&hid_dev, "/virt/usbhc/hc");
+	if (rc != EOK) {
+		printf("Unable to start communication with VHCD: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	printf("Connected to VHCD...\n");
+
+	wait_for_interfaces_death(&hid_dev);
+	
+	printf("Terminating...\n");
+	
+	usbvirt_device_unplug(&hid_dev);
+
+	return 0;
+}
+
+
+/** @}
+ */
Index: uspace/app/vuhid/report.h
===================================================================
--- uspace/app/vuhid/report.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/report.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,85 @@
+/*
+ * 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 usbvirtkbd
+ * @{
+ */
+/** @file
+ * @brief HID Report Descriptor.
+ */
+#ifndef VUK_REPORT_H_
+#define VUK_REPORT_H_
+
+#include "items.h"
+
+/** Use standard Usage Page. */
+#define STD_USAGE_PAGE(page) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_USAGE_PAGE, page)
+
+/** Usage with one byte usage ID. */
+#define USAGE1(usage_id) \
+	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE, usage_id)
+
+/** Start a collection. */
+#define START_COLLECTION(collection) \
+	ITEM_CREATE1(ITEM_MAIN, TAG_COLLECTION, collection)
+
+/** End a collection. */
+#define END_COLLECTION() \
+	ITEM_CREATE0(ITEM_MAIN, TAG_END_COLLECTION)
+
+
+#define USAGE_MINIMUM1(value) \
+	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE_MINIMUM, value)
+	
+#define USAGE_MAXIMUM1(value) \
+	ITEM_CREATE1(ITEM_LOCAL, TAG_USAGE_MAXIMUM, value)
+	
+#define LOGICAL_MINIMUM1(value) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_LOGICAL_MINIMUM, value)
+
+#define LOGICAL_MAXIMUM1(value) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_LOGICAL_MAXIMUM, value)
+
+#define REPORT_SIZE1(size) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_REPORT_SIZE, size)
+
+#define REPORT_COUNT1(count) \
+	ITEM_CREATE1(ITEM_GLOBAL, TAG_REPORT_COUNT, count)
+	
+#define INPUT(modifiers) \
+	ITEM_CREATE1(ITEM_MAIN, TAG_INPUT, modifiers)
+
+#define OUTPUT(modifiers) \
+	ITEM_CREATE1(ITEM_MAIN, TAG_OUTPUT, modifiers)
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/vuhid/stdreq.c
===================================================================
--- uspace/app/vuhid/stdreq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/stdreq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2011 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 usbvirthid
+ * @{
+ */
+/**
+ * @file
+ *
+ */
+#include <errno.h>
+#include <usb/debug.h>
+#include <usb/descriptor.h>
+#include "stdreq.h"
+#include "virthid.h"
+
+#define VUHID_DATA(vuhid, device) \
+	vuhid_data_t *vuhid = device->device_data
+
+int req_get_descriptor(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size)
+{
+	VUHID_DATA(vuhid, device);
+
+	if (setup_packet->value_high == USB_DESCTYPE_HID_REPORT) {
+		vuhid_interface_t *iface
+		    = vuhid->interface_mapping[setup_packet->index];
+		if (iface == NULL) {
+			return EFORWARD;
+		}
+		if (iface->report_descriptor != NULL) {
+			usbvirt_control_reply_helper(setup_packet,
+			    data, act_size,
+			    iface->report_descriptor,
+			    iface->report_descriptor_size);
+			return EOK;
+		} else {
+			return ENOENT;
+		}
+	}
+	
+	/* Let the framework handle all the rest. */
+	return EFORWARD;
+}
+
+int req_set_protocol(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size)
+{
+	VUHID_DATA(vuhid, device);
+
+	size_t iface_index = setup_packet->index;
+	int protocol = setup_packet->value;
+
+	// FIXME - check ranges
+	vuhid_interface_t *iface = vuhid->interface_mapping[iface_index];
+	if (iface == NULL) {
+		return ENOENT;
+	}
+	iface->set_protocol = protocol;
+
+	return EOK;
+}
+
+int req_set_report(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size)
+{
+	VUHID_DATA(vuhid, device);
+
+	size_t iface_index = setup_packet->index;
+
+	// FIXME - check ranges
+	vuhid_interface_t *iface = vuhid->interface_mapping[iface_index];
+	if (iface == NULL) {
+		return ENOENT;
+	}
+
+	size_t data_length = setup_packet->length;
+	if (iface->on_data_out == NULL) {
+		return ENOTSUP;
+	}
+
+	/* SET_REPORT is translated to data out */
+	int rc = iface->on_data_out(iface, data, data_length);
+
+	return rc;
+}
+
+
+
+/** @}
+ */
Index: uspace/app/vuhid/stdreq.h
===================================================================
--- uspace/app/vuhid/stdreq.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/stdreq.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 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 usbvirthid
+ * @{
+ */
+/** @file
+ * Device request handlers.
+ */
+#ifndef VUHID_STDREQ_H_
+#define VUHID_STDREQ_H_
+
+#include <usbvirt/device.h>
+
+int req_get_descriptor(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size);
+
+int req_set_protocol(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size);
+
+int req_set_report(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/app/vuhid/virthid.h
===================================================================
--- uspace/app/vuhid/virthid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/app/vuhid/virthid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2011 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 usbvirthid
+ * @{
+ */
+/** @file
+ *
+ */
+#ifndef VUHID_VIRTHID_H_
+#define VUHID_VIRTHID_H_
+
+#include <usb/usb.h>
+#include <usbvirt/device.h>
+#include <fibril_synch.h>
+
+#define VUHID_ENDPOINT_MAX USB11_ENDPOINT_MAX
+#define VUHID_INTERFACE_MAX 8
+
+typedef struct vuhid_interface vuhid_interface_t;
+
+typedef struct {
+	vuhid_interface_t *in_endpoints_mapping[VUHID_ENDPOINT_MAX];
+	size_t in_endpoint_first_free;
+	vuhid_interface_t *out_endpoints_mapping[VUHID_ENDPOINT_MAX];
+	size_t out_endpoint_first_free;
+	vuhid_interface_t *interface_mapping[VUHID_INTERFACE_MAX];
+
+	fibril_mutex_t iface_count_mutex;
+	fibril_condvar_t iface_count_cv;
+	size_t iface_count;
+	size_t iface_died_count;
+} vuhid_data_t;
+
+struct vuhid_interface {
+	const char *name;
+	const char *id;
+	int usb_subclass;
+	int usb_protocol;
+
+	uint8_t *report_descriptor;
+	size_t report_descriptor_size;
+
+	size_t in_data_size;
+	size_t out_data_size;
+
+	int (*on_data_in)(vuhid_interface_t *, void *, size_t, size_t *);
+	int (*on_data_out)(vuhid_interface_t *, void *, size_t);
+	void (*live)(vuhid_interface_t *);
+
+	int set_protocol;
+
+	void *interface_data;
+
+	vuhid_data_t *vuhid_data;
+};
+
+typedef struct {
+	uint8_t length;
+	uint8_t type;
+	uint16_t hid_spec_release;
+	uint8_t country_code;
+	uint8_t descriptor_count;
+	uint8_t descriptor1_type;
+	uint16_t descriptor1_length;
+} __attribute__ ((packed)) hid_descriptor_t;
+
+int add_interface_by_id(vuhid_interface_t **, const char *, usbvirt_device_t *);
+void wait_for_interfaces_death(usbvirt_device_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/doc/doxygroups.h
===================================================================
--- uspace/doc/doxygroups.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/doc/doxygroups.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -165,2 +165,163 @@
 	 * @ingroup emul
 	 */
+
+/**
+ * @defgroup usb USB
+ * @ingroup uspace
+ * @brief USB support for HelenOS.
+ */
+	/**
+	 * @defgroup libusb Base USB library
+	 * @ingroup usb
+	 * @brief Common definitions for any driver or application
+	 * dealing with USB.
+	 */
+
+	/**
+	 * @defgroup libusbdev USB library for device drivers
+	 * @ingroup usb
+	 * @brief Library for writing drivers of endpoint devices (functions).
+	 */
+
+	/**
+	 * @defgroup libusbhost USB library for host controller drivers
+	 * @ingroup usb
+	 * @brief Library for writing host controller drivers.
+	 */
+
+	/**
+	 * @defgroup libusbhid USB library for HID devices
+	 * @ingroup usb
+	 * @brief Library for writing USB HID drivers.
+	 */
+
+	/**
+	 * @defgroup usbvirt USB virtualization
+	 * @ingroup usb
+	 * @brief Support for virtual USB devices.
+	 */
+
+		/**
+		 * @defgroup libusbvirt USB virtualization library
+		 * @ingroup usbvirt
+		 * @brief Library for creating virtual USB devices.
+		 */
+
+		/**
+		 * @defgroup drvusbvhc Virtual USB host controller
+		 * @ingroup usbvirt
+		 * @brief Driver simulating work of USB host controller.
+		 */
+
+		/**
+		 * @defgroup usbvirthub Virtual USB hub
+		 * @ingroup usbvirt
+		 * @brief Extra virtual USB hub for virtual host controller.
+		 * @details
+		 * Some of the sources are shared with virtual host controller,
+		 * see @ref drvusbvhc for the rest of the files.
+		 */
+
+		/**
+		 * @defgroup usbvirtkbd Virtual USB keybaord
+		 * @ingroup usbvirt
+		 * @brief Virtual USB keyboard for virtual host controller.
+		 */
+
+	/**
+	 * @defgroup usbinfo USB info application
+	 * @ingroup usb
+	 * @brief Application for querying USB devices.
+	 * @details
+	 * The intended usage of this application is to query new USB devices
+	 * for their descriptors etc. to simplify driver writing.
+	 */
+
+	/**
+	 * @defgroup lsusb HelenOS version of lsusb command
+	 * @ingroup usb
+	 * @brief Application for listing USB host controllers.
+	 * @details
+	 * List all found host controllers.
+	 */
+
+	/**
+	 * @defgroup drvusbmid USB multi interface device driver
+	 * @ingroup usb
+	 * @brief USB multi interface device driver
+	 * @details
+	 * This driver serves as a mini hub (or bus) driver for devices
+	 * that have the class defined at interface level (those devices
+	 * usually have several interfaces).
+	 *
+	 * The term multi interface device driver (MID) was borrowed
+	 * Solaris operating system.
+	 */
+
+	/**
+	 * @defgroup drvusbhub USB hub driver
+	 * @ingroup usb
+	 * @brief USB hub driver.
+	 */
+
+	/**
+	 * @defgroup drvusbhid USB HID driver
+	 * @ingroup usb
+	 * @brief USB driver for HID devices.
+	 */
+
+	/**
+	 * @defgroup drvusbmouse USB mouse driver
+	 * @ingroup usb
+	 * @brief USB driver for mouse with boot protocol.
+	 */
+
+	/**
+	 * @defgroup drvusbmast USB mass storage driver
+	 * @ingroup usb
+	 * @brief USB driver for mass storage devices (bulk-only protocol).
+	 * This driver is a only a stub and is currently used only for
+	 * testing that bulk transfers work.
+	 */
+
+	/**
+	 * @defgroup drvusbuhci UHCI driver
+	 * @ingroup usb
+	 * @brief Drivers for USB UHCI host controller and root hub.
+	 */
+
+		/**
+		 * @defgroup drvusbuhcirh UHCI root hub driver
+		 * @ingroup drvusbuhci
+		 * @brief Driver for UHCI complaint root hub.
+		 */
+
+		/**
+		 * @defgroup drvusbuhcihc UHCI host controller driver
+		 * @ingroup drvusbuhci
+		 * @brief Driver for UHCI complaint USB host controller.
+		 */
+
+	/**
+	 * @defgroup drvusbohci OHCI driver
+	 * @ingroup usb
+	 * @brief Driver for OHCI host controller.
+	 */
+
+	/**
+	 * @defgroup drvusbehci EHCI driver
+	 * @ingroup usb
+	 * @brief Driver for EHCI host controller.
+	 */
+
+	/**
+	 * @defgroup drvusbfallback USB fallback driver
+	 * @ingroup usb
+	 * @brief Fallback driver for any USB device.
+	 * @details
+	 * The purpose of this driver is to simplify querying of unknown
+	 * devices from within HelenOS (without a driver, no node at all
+	 * may appear under /loc/devices).
+	 */
+
+
Index: uspace/doc/main_usb.h
===================================================================
--- uspace/doc/main_usb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/doc/main_usb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,26 @@
+/**
+ @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/bus/isa/Makefile
===================================================================
--- uspace/drv/bus/isa/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/isa/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = isa
+
+SOURCES = \
+	isa.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/isa/isa.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup isa ISA bus driver.
+ * @brief HelenOS ISA bus driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <str_error.h>
+#include <ctype.h>
+#include <macros.h>
+#include <malloc.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <ops/hw_res.h>
+
+#include <devman.h>
+#include <ipc/devman.h>
+#include <device/hw_res.h>
+
+#define NAME "isa"
+#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
+
+/** Obtain soft-state pointer from function node pointer */
+#define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
+
+#define ISA_MAX_HW_RES 4
+
+typedef struct isa_fun {
+	ddf_fun_t *fnode;
+	hw_resource_list_t hw_resources;
+} isa_fun_t;
+
+static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
+{
+	isa_fun_t *fun = ISA_FUN(fnode);
+	assert(fun != NULL);
+
+	return &fun->hw_resources;
+}
+
+static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
+{
+	/* TODO */
+
+	return false;
+}
+
+static hw_res_ops_t isa_fun_hw_res_ops = {
+	&isa_get_fun_resources,
+	&isa_enable_fun_interrupt
+};
+
+static ddf_dev_ops_t isa_fun_ops;
+
+static int isa_add_device(ddf_dev_t *dev);
+
+/** The isa device driver's standard operations */
+static driver_ops_t isa_ops = {
+	.add_device = &isa_add_device
+};
+
+/** The isa device driver structure. */
+static driver_t isa_driver = {
+	.name = NAME,
+	.driver_ops = &isa_ops
+};
+
+static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
+{
+	isa_fun_t *fun = calloc(1, sizeof(isa_fun_t));
+	if (fun == NULL)
+		return NULL;
+
+	ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL) {
+		free(fun);
+		return NULL;
+	}
+
+	fun->fnode = fnode;
+	fnode->driver_data = fun;
+	return fun;
+}
+
+static char *fun_conf_read(const char *conf_path)
+{
+	bool suc = false;
+	char *buf = NULL;
+	bool opened = false;
+	int fd;
+	size_t len = 0;
+
+	fd = open(conf_path, O_RDONLY);
+	if (fd < 0) {
+		ddf_msg(LVL_ERROR, "Unable to open %s", conf_path);
+		goto cleanup;
+	}
+
+	opened = true;
+
+	len = lseek(fd, 0, SEEK_END);
+	lseek(fd, 0, SEEK_SET);
+	if (len == 0) {
+		ddf_msg(LVL_ERROR, "Configuration file '%s' is empty.",
+		    conf_path);
+		goto cleanup;
+	}
+
+	buf = malloc(len + 1);
+	if (buf == NULL) {
+		ddf_msg(LVL_ERROR, "Memory allocation failed.");
+		goto cleanup;
+	}
+
+	if (0 >= read(fd, buf, len)) {
+		ddf_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
+		goto cleanup;
+	}
+
+	buf[len] = 0;
+
+	suc = true;
+
+cleanup:
+	if (!suc && buf != NULL) {
+		free(buf);
+		buf = NULL;
+	}
+
+	if (opened)
+		close(fd);
+
+	return buf;
+}
+
+static char *str_get_line(char *str, char **next)
+{
+	char *line = str;
+
+	if (str == NULL) {
+		*next = NULL;
+		return NULL;
+	}
+
+	while (*str != '\0' && *str != '\n') {
+		str++;
+	}
+
+	if (*str != '\0') {
+		*next = str + 1;
+	} else {
+		*next = NULL;
+	}
+
+	*str = '\0';
+	return line;
+}
+
+static bool line_empty(const char *line)
+{
+	while (line != NULL && *line != 0) {
+		if (!isspace(*line))
+			return false;
+		line++;
+	}
+
+	return true;
+}
+
+static char *get_device_name(char *line)
+{
+	/* Skip leading spaces. */
+	while (*line != '\0' && isspace(*line)) {
+		line++;
+	}
+
+	/* Get the name part of the rest of the line. */
+	strtok(line, ":");
+
+	/* Allocate output buffer. */
+	size_t size = str_size(line) + 1;
+	char *name = malloc(size);
+
+	if (name != NULL) {
+		/* Copy the result to the output buffer. */
+		str_cpy(name, size, line);
+	}
+
+	return name;
+}
+
+static inline char *skip_spaces(char *line)
+{
+	/* Skip leading spaces. */
+	while (*line != '\0' && isspace(*line))
+		line++;
+
+	return line;
+}
+
+static void isa_fun_set_irq(isa_fun_t *fun, int irq)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
+
+	if (count < ISA_MAX_HW_RES) {
+		resources[count].type = INTERRUPT;
+		resources[count].res.interrupt.irq = irq;
+
+		fun->hw_resources.count++;
+
+		ddf_msg(LVL_NOTE, "Added irq 0x%x to function %s", irq,
+		    fun->fnode->name);
+	}
+}
+
+static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
+{
+	size_t count = fun->hw_resources.count;
+	hw_resource_t *resources = fun->hw_resources.resources;
+
+	if (count < ISA_MAX_HW_RES) {
+		resources[count].type = IO_RANGE;
+		resources[count].res.io_range.address = addr;
+		resources[count].res.io_range.size = len;
+		resources[count].res.io_range.endianness = LITTLE_ENDIAN;
+
+		fun->hw_resources.count++;
+
+		ddf_msg(LVL_NOTE, "Added io range (addr=0x%x, size=0x%x) to "
+		    "function %s", (unsigned int) addr, (unsigned int) len,
+		    fun->fnode->name);
+	}
+}
+
+static void fun_parse_irq(isa_fun_t *fun, char *val)
+{
+	int irq = 0;
+	char *end = NULL;
+
+	val = skip_spaces(val);
+	irq = (int)strtol(val, &end, 0x10);
+
+	if (val != end)
+		isa_fun_set_irq(fun, irq);
+}
+
+static void fun_parse_io_range(isa_fun_t *fun, char *val)
+{
+	size_t addr, len;
+	char *end = NULL;
+
+	val = skip_spaces(val);
+	addr = strtol(val, &end, 0x10);
+
+	if (val == end)
+		return;
+
+	val = skip_spaces(end);
+	len = strtol(val, &end, 0x10);
+
+	if (val == end)
+		return;
+
+	isa_fun_set_io_range(fun, addr, len);
+}
+
+static void get_match_id(char **id, char *val)
+{
+	char *end = val;
+
+	while (!isspace(*end))
+		end++;
+
+	size_t size = end - val + 1;
+	*id = (char *)malloc(size);
+	str_cpy(*id, size, val);
+}
+
+static void fun_parse_match_id(isa_fun_t *fun, char *val)
+{
+	char *id = NULL;
+	int score = 0;
+	char *end = NULL;
+	int rc;
+
+	val = skip_spaces(val);
+
+	score = (int)strtol(val, &end, 10);
+	if (val == end) {
+		ddf_msg(LVL_ERROR, "Cannot read match score for function "
+		    "%s.", fun->fnode->name);
+		return;
+	}
+
+	val = skip_spaces(end);
+	get_match_id(&id, val);
+	if (id == NULL) {
+		ddf_msg(LVL_ERROR, "Cannot read match ID for function %s.",
+		    fun->fnode->name);
+		return;
+	}
+
+	ddf_msg(LVL_DEBUG, "Adding match id '%s' with score %d to "
+	    "function %s", id, score, fun->fnode->name);
+
+	rc = ddf_fun_add_match_id(fun->fnode, id, score);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
+		    str_error(rc));
+	}
+
+	free(id);
+}
+
+static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
+    void (*read_fn)(isa_fun_t *, char *))
+{
+	size_t proplen = str_size(prop);
+
+	if (str_lcmp(line, prop, proplen) == 0) {
+		line += proplen;
+		line = skip_spaces(line);
+		(*read_fn)(fun, line);
+
+		return true;
+	}
+
+	return false;
+}
+
+static void fun_prop_parse(isa_fun_t *fun, char *line)
+{
+	/* Skip leading spaces. */
+	line = skip_spaces(line);
+
+	if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
+	    !prop_parse(fun, line, "irq", &fun_parse_irq) &&
+	    !prop_parse(fun, line, "match", &fun_parse_match_id)) {
+
+		ddf_msg(LVL_ERROR, "Undefined device property at line '%s'",
+		    line);
+	}
+}
+
+static void fun_hw_res_alloc(isa_fun_t *fun)
+{
+	fun->hw_resources.resources = 
+	    (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
+}
+
+static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
+{
+	char *line;
+	char *fun_name = NULL;
+
+	/* Skip empty lines. */
+	while (true) {
+		line = str_get_line(fun_conf, &fun_conf);
+
+		if (line == NULL) {
+			/* no more lines */
+			return NULL;
+		}
+
+		if (!line_empty(line))
+			break;
+	}
+
+	/* Get device name. */
+	fun_name = get_device_name(line);
+	if (fun_name == NULL)
+		return NULL;
+
+	isa_fun_t *fun = isa_fun_create(dev, fun_name);
+	if (fun == NULL) {
+		free(fun_name);
+		return NULL;
+	}
+
+	/* Allocate buffer for the list of hardware resources of the device. */
+	fun_hw_res_alloc(fun);
+
+	/* Get properties of the device (match ids, irq and io range). */
+	while (true) {
+		line = str_get_line(fun_conf, &fun_conf);
+
+		if (line_empty(line)) {
+			/* no more device properties */
+			break;
+		}
+
+		/*
+		 * Get the device's property from the configuration line
+		 * and store it in the device structure.
+		 */
+		fun_prop_parse(fun, line);
+	}
+
+	/* Set device operations to the device. */
+	fun->fnode->ops = &isa_fun_ops;
+
+	ddf_msg(LVL_DEBUG, "Binding function %s.", fun->fnode->name);
+
+	/* XXX Handle error */
+	(void) ddf_fun_bind(fun->fnode);
+
+	return fun_conf;
+}
+
+static void fun_conf_parse(char *conf, ddf_dev_t *dev)
+{
+	while (conf != NULL && *conf != '\0') {
+		conf = isa_fun_read_info(conf, dev);
+	}
+}
+
+static void isa_functions_add(ddf_dev_t *dev)
+{
+	char *fun_conf;
+
+	fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
+	if (fun_conf != NULL) {
+		fun_conf_parse(fun_conf, dev);
+		free(fun_conf);
+	}
+}
+
+static int isa_add_device(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "isa_add_device, device handle = %d",
+	    (int) dev->handle);
+
+	/* Make the bus device more visible. Does not do anything. */
+	ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
+
+	ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
+	if (ctl == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating control function.");
+		return EXDEV;
+	}
+
+	if (ddf_fun_bind(ctl) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding control function.");
+		return EXDEV;
+	}
+
+	/* Add functions as specified in the configuration file. */
+	isa_functions_add(dev);
+	ddf_msg(LVL_NOTE, "Finished enumerating legacy functions");
+
+	return EOK;
+}
+
+static void isa_init() 
+{
+	ddf_log_init(NAME, LVL_ERROR);
+	isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS ISA bus driver\n");
+	isa_init();
+	return ddf_driver_main(&isa_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/isa/isa.dev
===================================================================
--- uspace/drv/bus/isa/isa.dev	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/isa/isa.dev	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,15 @@
+com1:
+	match 100 isa/ns8250
+	irq 4
+	io_range 3f8 8
+
+com2:
+	match 100 isa/ns8250
+	irq 3
+	io_range 2f8 8
+
+keyboard:
+	match 100 isa/keyboard
+	irq 1
+	io_range 060 10
+	
Index: uspace/drv/bus/isa/isa.ma
===================================================================
--- uspace/drv/bus/isa/isa.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/isa/isa.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+9 	pci/ven=8086&dev=7000
Index: uspace/drv/bus/pci/pciintel/Makefile
===================================================================
--- uspace/drv/bus/pci/pciintel/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/pci/pciintel/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = pciintel
+
+SOURCES = \
+	pci.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,761 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup pciintel pci bus driver for intel method 1.
+ * @brief HelenOS root pci bus driver for intel method 1.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+#include <str_error.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <devman.h>
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+#include <ipc/irc.h>
+#include <ns.h>
+#include <ipc/services.h>
+#include <sysinfo.h>
+#include <ops/hw_res.h>
+#include <device/hw_res.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+#define NAME "pciintel"
+
+#define CONF_ADDR(bus, dev, fn, reg) \
+	((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
+
+/** Obtain PCI function soft-state from DDF function node */
+#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
+
+/** Obtain PCI bus soft-state from DDF device node */
+#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
+
+/** Obtain PCI bus soft-state from function soft-state */
+#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
+
+static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
+{
+	pci_fun_t *fun = PCI_FUN(fnode);
+	
+	if (fun == NULL)
+		return NULL;
+	return &fun->hw_resources;
+}
+
+static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
+{
+	/* This is an old ugly way, copied from ne2000 driver */
+	assert(fnode);
+	pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
+	
+	sysarg_t apic;
+	sysarg_t i8259;
+	
+	async_sess_t *irc_sess = NULL;
+	
+	if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
+	    || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))) {
+		irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+		    SERVICE_IRC, 0, 0);
+	}
+	
+	if (!irc_sess)
+		return false;
+	
+	size_t i = 0;
+	hw_resource_list_t *res = &dev_data->hw_resources;
+	for (; i < res->count; i++) {
+		if (res->resources[i].type == INTERRUPT) {
+			const int irq = res->resources[i].res.interrupt.irq;
+			
+			async_exch_t *exch = async_exchange_begin(irc_sess);
+			const int rc =
+			    async_req_1_0(exch, IRC_ENABLE_INTERRUPT, irq);
+			async_exchange_end(exch);
+			
+			if (rc != EOK) {
+				async_hangup(irc_sess);
+				return false;
+			}
+		}
+	}
+	
+	async_hangup(irc_sess);
+	return true;
+}
+
+static int pci_config_space_write_32(ddf_fun_t *fun, uint32_t address,
+    uint32_t data)
+{
+	if (address > 252)
+		return EINVAL;
+	pci_conf_write_32(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_write_16(
+    ddf_fun_t *fun, uint32_t address, uint16_t data)
+{
+	if (address > 254)
+		return EINVAL;
+	pci_conf_write_16(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_write_8(
+    ddf_fun_t *fun, uint32_t address, uint8_t data)
+{
+	if (address > 255)
+		return EINVAL;
+	pci_conf_write_8(PCI_FUN(fun), address, data);
+	return EOK;
+}
+
+static int pci_config_space_read_32(
+    ddf_fun_t *fun, uint32_t address, uint32_t *data)
+{
+	if (address > 252)
+		return EINVAL;
+	*data = pci_conf_read_32(PCI_FUN(fun), address);
+	return EOK;
+}
+
+static int pci_config_space_read_16(
+    ddf_fun_t *fun, uint32_t address, uint16_t *data)
+{
+	if (address > 254)
+		return EINVAL;
+	*data = pci_conf_read_16(PCI_FUN(fun), address);
+	return EOK;
+}
+
+static int pci_config_space_read_8(
+    ddf_fun_t *fun, uint32_t address, uint8_t *data)
+{
+	if (address > 255)
+		return EINVAL;
+	*data = pci_conf_read_8(PCI_FUN(fun), address);
+	return EOK;
+}
+
+static hw_res_ops_t pciintel_hw_res_ops = {
+	&pciintel_get_resources,
+	&pciintel_enable_interrupt
+};
+
+static pci_dev_iface_t pci_dev_ops = {
+	.config_space_read_8 = &pci_config_space_read_8,
+	.config_space_read_16 = &pci_config_space_read_16,
+	.config_space_read_32 = &pci_config_space_read_32,
+	.config_space_write_8 = &pci_config_space_write_8,
+	.config_space_write_16 = &pci_config_space_write_16,
+	.config_space_write_32 = &pci_config_space_write_32
+};
+
+static ddf_dev_ops_t pci_fun_ops = {
+	.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops,
+	.interfaces[PCI_DEV_IFACE] = &pci_dev_ops
+};
+
+static int pci_add_device(ddf_dev_t *);
+
+/** PCI bus driver standard operations */
+static driver_ops_t pci_ops = {
+	.add_device = &pci_add_device
+};
+
+/** PCI bus driver structure */
+static driver_t pci_driver = {
+	.name = NAME,
+	.driver_ops = &pci_ops
+};
+
+static pci_bus_t *pci_bus_new(void)
+{
+	pci_bus_t *bus;
+	
+	bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));
+	if (bus == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&bus->conf_mutex);
+	return bus;
+}
+
+static void pci_bus_delete(pci_bus_t *bus)
+{
+	assert(bus != NULL);
+	free(bus);
+}
+
+static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
+{
+	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	
+	fibril_mutex_lock(&bus->conf_mutex);
+	
+	uint32_t conf_addr;
+	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	void *addr = bus->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus->conf_addr_port, conf_addr);
+	
+	switch (len) {
+	case 1:
+		buf[0] = pio_read_8(addr);
+		break;
+	case 2:
+		((uint16_t *) buf)[0] = pio_read_16(addr);
+		break;
+	case 4:
+		((uint32_t *) buf)[0] = pio_read_32(addr);
+		break;
+	}
+	
+	fibril_mutex_unlock(&bus->conf_mutex);
+}
+
+static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
+{
+	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
+	
+	fibril_mutex_lock(&bus->conf_mutex);
+	
+	uint32_t conf_addr;
+	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
+	void *addr = bus->conf_data_port + (reg & 3);
+	
+	pio_write_32(bus->conf_addr_port, conf_addr);
+	
+	switch (len) {
+	case 1:
+		pio_write_8(addr, buf[0]);
+		break;
+	case 2:
+		pio_write_16(addr, ((uint16_t *) buf)[0]);
+		break;
+	case 4:
+		pio_write_32(addr, ((uint32_t *) buf)[0]);
+		break;
+	}
+	
+	fibril_mutex_unlock(&bus->conf_mutex);
+}
+
+uint8_t pci_conf_read_8(pci_fun_t *fun, int reg)
+{
+	uint8_t res;
+	pci_conf_read(fun, reg, &res, 1);
+	return res;
+}
+
+uint16_t pci_conf_read_16(pci_fun_t *fun, int reg)
+{
+	uint16_t res;
+	pci_conf_read(fun, reg, (uint8_t *) &res, 2);
+	return res;
+}
+
+uint32_t pci_conf_read_32(pci_fun_t *fun, int reg)
+{
+	uint32_t res;
+	pci_conf_read(fun, reg, (uint8_t *) &res, 4);
+	return res;
+}
+
+void pci_conf_write_8(pci_fun_t *fun, int reg, uint8_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 1);
+}
+
+void pci_conf_write_16(pci_fun_t *fun, int reg, uint16_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 2);
+}
+
+void pci_conf_write_32(pci_fun_t *fun, int reg, uint32_t val)
+{
+	pci_conf_write(fun, reg, (uint8_t *) &val, 4);
+}
+
+void pci_fun_create_match_ids(pci_fun_t *fun)
+{
+	char *match_id_str;
+	int rc;
+	
+	asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
+	    fun->vendor_id, fun->device_id);
+
+	if (match_id_str == NULL) {
+		ddf_msg(LVL_ERROR, "Out of memory creating match ID.");
+		return;
+	}
+
+	rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match ID: %s",
+		    str_error(rc));
+	}
+	
+	free(match_id_str);
+	
+	/* TODO add more ids (with subsys ids, using class id etc.) */
+}
+
+void pci_add_range(pci_fun_t *fun, uint64_t range_addr, size_t range_size,
+    bool io)
+{
+	hw_resource_list_t *hw_res_list = &fun->hw_resources;
+	hw_resource_t *hw_resources =  hw_res_list->resources;
+	size_t count = hw_res_list->count;
+	
+	assert(hw_resources != NULL);
+	assert(count < PCI_MAX_HW_RES);
+	
+	if (io) {
+		hw_resources[count].type = IO_RANGE;
+		hw_resources[count].res.io_range.address = range_addr;
+		hw_resources[count].res.io_range.size = range_size;
+		hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
+	} else {
+		hw_resources[count].type = MEM_RANGE;
+		hw_resources[count].res.mem_range.address = range_addr;
+		hw_resources[count].res.mem_range.size = range_size;
+		hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
+	}
+	
+	hw_res_list->count++;
+}
+
+/** Read the base address register (BAR) of the device and if it contains valid
+ * address add it to the devices hw resource list.
+ *
+ * @param fun	PCI function
+ * @param addr	The address of the BAR in the PCI configuration address space of
+ *		the device
+ * @return	The addr the address of the BAR which should be read next
+ */
+int pci_read_bar(pci_fun_t *fun, int addr)
+{
+	/* Value of the BAR */
+	uint32_t val, mask;
+	/* IO space address */
+	bool io;
+	/* 64-bit wide address */
+	bool addrw64;
+	
+	/* Size of the io or memory range specified by the BAR */
+	size_t range_size;
+	/* Beginning of the io or memory range specified by the BAR */
+	uint64_t range_addr;
+	
+	/* Get the value of the BAR. */
+	val = pci_conf_read_32(fun, addr);
+
+#define IO_MASK  (~0x3)
+#define MEM_MASK (~0xf)
+	
+	io = (bool) (val & 1);
+	if (io) {
+		addrw64 = false;
+		mask = IO_MASK;
+	} else {
+		mask = MEM_MASK;
+		switch ((val >> 1) & 3) {
+		case 0:
+			addrw64 = false;
+			break;
+		case 2:
+			addrw64 = true;
+			break;
+		default:
+			/* reserved, go to the next BAR */
+			return addr + 4;
+		}
+	}
+	
+	/* Get the address mask. */
+	pci_conf_write_32(fun, addr, 0xffffffff);
+	mask &= pci_conf_read_32(fun, addr);
+	
+	/* Restore the original value. */
+	pci_conf_write_32(fun, addr, val);
+	val = pci_conf_read_32(fun, addr);
+	
+	range_size = pci_bar_mask_to_size(mask);
+	
+	if (addrw64) {
+		range_addr = ((uint64_t)pci_conf_read_32(fun, addr + 4) << 32) |
+		    (val & 0xfffffff0);
+	} else {
+		range_addr = (val & 0xfffffff0);
+	}
+	
+	if (range_addr != 0) {
+		ddf_msg(LVL_DEBUG, "Function %s : address = %" PRIx64
+		    ", size = %x", fun->fnode->name, range_addr,
+		    (unsigned int) range_size);
+	}
+	
+	pci_add_range(fun, range_addr, range_size, io);
+	
+	if (addrw64)
+		return addr + 8;
+	
+	return addr + 4;
+}
+
+void pci_add_interrupt(pci_fun_t *fun, int irq)
+{
+	hw_resource_list_t *hw_res_list = &fun->hw_resources;
+	hw_resource_t *hw_resources = hw_res_list->resources;
+	size_t count = hw_res_list->count;
+	
+	assert(NULL != hw_resources);
+	assert(count < PCI_MAX_HW_RES);
+	
+	hw_resources[count].type = INTERRUPT;
+	hw_resources[count].res.interrupt.irq = irq;
+	
+	hw_res_list->count++;
+	
+	ddf_msg(LVL_NOTE, "Function %s uses irq %x.", fun->fnode->name, irq);
+}
+
+void pci_read_interrupt(pci_fun_t *fun)
+{
+	uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
+	if (irq != 0xff)
+		pci_add_interrupt(fun, irq);
+}
+
+/** Enumerate (recursively) and register the devices connected to a pci bus.
+ *
+ * @param bus		Host-to-PCI bridge
+ * @param bus_num	Bus number
+ */
+void pci_bus_scan(pci_bus_t *bus, int bus_num) 
+{
+	ddf_fun_t *fnode;
+	pci_fun_t *fun;
+	
+	int child_bus = 0;
+	int dnum, fnum;
+	bool multi;
+	uint8_t header_type;
+	
+	fun = pci_fun_new(bus);
+	
+	for (dnum = 0; dnum < 32; dnum++) {
+		multi = true;
+		for (fnum = 0; multi && fnum < 8; fnum++) {
+			pci_fun_init(fun, bus_num, dnum, fnum);
+			fun->vendor_id = pci_conf_read_16(fun,
+			    PCI_VENDOR_ID);
+			fun->device_id = pci_conf_read_16(fun,
+			    PCI_DEVICE_ID);
+			if (fun->vendor_id == 0xffff) {
+				/*
+				 * The device is not present, go on scanning the
+				 * bus.
+				 */
+				if (fnum == 0)
+					break;
+				else
+					continue;
+			}
+			
+			header_type = pci_conf_read_8(fun, PCI_HEADER_TYPE);
+			if (fnum == 0) {
+				/* Is the device multifunction? */
+				multi = header_type >> 7;
+			}
+			/* Clear the multifunction bit. */
+			header_type = header_type & 0x7F;
+			
+			char *fun_name = pci_fun_create_name(fun);
+			if (fun_name == NULL) {
+				ddf_msg(LVL_ERROR, "Out of memory.");
+				return;
+			}
+			
+			fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
+			if (fnode == NULL) {
+				ddf_msg(LVL_ERROR, "Failed creating function.");
+				return;
+			}
+			
+			free(fun_name);
+			fun->fnode = fnode;
+			
+			pci_alloc_resource_list(fun);
+			pci_read_bars(fun);
+			pci_read_interrupt(fun);
+			
+			fnode->ops = &pci_fun_ops;
+			fnode->driver_data = fun;
+			
+			ddf_msg(LVL_DEBUG, "Adding new function %s.",
+			    fnode->name);
+			
+			pci_fun_create_match_ids(fun);
+			
+			if (ddf_fun_bind(fnode) != EOK) {
+				pci_clean_resource_list(fun);
+				clean_match_ids(&fnode->match_ids);
+				free((char *) fnode->name);
+				fnode->name = NULL;
+				continue;
+			}
+			
+			if (header_type == PCI_HEADER_TYPE_BRIDGE ||
+			    header_type == PCI_HEADER_TYPE_CARDBUS) {
+				child_bus = pci_conf_read_8(fun,
+				    PCI_BRIDGE_SEC_BUS_NUM);
+				ddf_msg(LVL_DEBUG, "Device is pci-to-pci "
+				    "bridge, secondary bus number = %d.",
+				    bus_num);
+				if (child_bus > bus_num)
+					pci_bus_scan(bus, child_bus);
+			}
+			
+			fun = pci_fun_new(bus);
+		}
+	}
+	
+	if (fun->vendor_id == 0xffff) {
+		/* Free the auxiliary function structure. */
+		pci_fun_delete(fun);
+	}
+}
+
+static int pci_add_device(ddf_dev_t *dnode)
+{
+	pci_bus_t *bus = NULL;
+	ddf_fun_t *ctl = NULL;
+	bool got_res = false;
+	int rc;
+	
+	ddf_msg(LVL_DEBUG, "pci_add_device");
+	dnode->parent_sess = NULL;
+	
+	bus = pci_bus_new();
+	if (bus == NULL) {
+		ddf_msg(LVL_ERROR, "pci_add_device allocation failed.");
+		rc = ENOMEM;
+		goto fail;
+	}
+	bus->dnode = dnode;
+	dnode->driver_data = bus;
+	
+	dnode->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    dnode->handle, IPC_FLAG_BLOCKING);
+	if (!dnode->parent_sess) {
+		ddf_msg(LVL_ERROR, "pci_add_device failed to connect to the "
+		    "parent driver.");
+		rc = ENOENT;
+		goto fail;
+	}
+	
+	hw_resource_list_t hw_resources;
+	
+	rc = hw_res_get_resource_list(dnode->parent_sess, &hw_resources);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "pci_add_device failed to get hw resources "
+		    "for the device.");
+		goto fail;
+	}
+	got_res = true;
+	
+	ddf_msg(LVL_DEBUG, "conf_addr = %" PRIx64 ".",
+	    hw_resources.resources[0].res.io_range.address);
+	
+	assert(hw_resources.count > 0);
+	assert(hw_resources.resources[0].type == IO_RANGE);
+	assert(hw_resources.resources[0].res.io_range.size == 8);
+	
+	bus->conf_io_addr =
+	    (uint32_t) hw_resources.resources[0].res.io_range.address;
+	
+	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
+	    &bus->conf_addr_port)) {
+		ddf_msg(LVL_ERROR, "Failed to enable configuration ports.");
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
+	bus->conf_data_port = (char *) bus->conf_addr_port + 4;
+	
+	/* Make the bus device more visible. It has no use yet. */
+	ddf_msg(LVL_DEBUG, "Adding a 'ctl' function");
+	
+	ctl = ddf_fun_create(bus->dnode, fun_exposed, "ctl");
+	if (ctl == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating control function.");
+		rc = ENOMEM;
+		goto fail;
+	}
+	
+	rc = ddf_fun_bind(ctl);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding control function.");
+		goto fail;
+	}
+	
+	/* Enumerate functions. */
+	ddf_msg(LVL_DEBUG, "Scanning the bus");
+	pci_bus_scan(bus, 0);
+	
+	hw_res_clean_resource_list(&hw_resources);
+	
+	return EOK;
+	
+fail:
+	if (bus != NULL)
+		pci_bus_delete(bus);
+	
+	if (dnode->parent_sess)
+		async_hangup(dnode->parent_sess);
+	
+	if (got_res)
+		hw_res_clean_resource_list(&hw_resources);
+	
+	if (ctl != NULL)
+		ddf_fun_destroy(ctl);
+	
+	return rc;
+}
+
+static void pciintel_init(void)
+{
+	ddf_log_init(NAME, LVL_ERROR);
+	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
+	pci_fun_ops.interfaces[PCI_DEV_IFACE] = &pci_dev_ops;
+}
+
+pci_fun_t *pci_fun_new(pci_bus_t *bus)
+{
+	pci_fun_t *fun;
+	
+	fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
+	if (fun == NULL)
+		return NULL;
+
+	fun->busptr = bus;
+	return fun;
+}
+
+void pci_fun_init(pci_fun_t *fun, int bus, int dev, int fn)
+{
+	fun->bus = bus;
+	fun->dev = dev;
+	fun->fn = fn;
+}
+
+void pci_fun_delete(pci_fun_t *fun)
+{
+	assert(fun != NULL);
+	hw_res_clean_resource_list(&fun->hw_resources);
+	free(fun);
+}
+
+char *pci_fun_create_name(pci_fun_t *fun)
+{
+	char *name = NULL;
+	
+	asprintf(&name, "%02x:%02x.%01x", fun->bus, fun->dev,
+	    fun->fn);
+	return name;
+}
+
+bool pci_alloc_resource_list(pci_fun_t *fun)
+{
+	fun->hw_resources.resources =
+	    (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
+	return fun->hw_resources.resources != NULL;
+}
+
+void pci_clean_resource_list(pci_fun_t *fun)
+{
+	if (fun->hw_resources.resources != NULL) {
+		free(fun->hw_resources.resources);
+		fun->hw_resources.resources = NULL;
+	}
+}
+
+/** Read the base address registers (BARs) of the function and add the addresses
+ * to its HW resource list.
+ *
+ * @param fun	PCI function
+ */
+void pci_read_bars(pci_fun_t *fun)
+{
+	/*
+	 * Position of the BAR in the PCI configuration address space of the
+	 * device.
+	 */
+	int addr = PCI_BASE_ADDR_0;
+	
+	while (addr <= PCI_BASE_ADDR_5)
+		addr = pci_read_bar(fun, addr);
+}
+
+size_t pci_bar_mask_to_size(uint32_t mask)
+{
+	size_t size = mask & ~(mask - 1);
+	return size;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS PCI bus driver (Intel method 1).\n");
+	pciintel_init();
+	return ddf_driver_main(&pci_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/pci/pciintel/pci.h
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/pci/pciintel/pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup pciintel
+ * @{
+ */
+/** @file
+ */
+
+#ifndef PCI_H_
+#define PCI_H_
+
+#include <ddf/driver.h>
+#include "pci_regs.h"
+
+#define PCI_MAX_HW_RES 8
+
+typedef struct pciintel_bus {
+	/** DDF device node */
+	ddf_dev_t *dnode;
+	uint32_t conf_io_addr;
+	void *conf_data_port;
+	void *conf_addr_port;
+	fibril_mutex_t conf_mutex;
+} pci_bus_t;
+
+typedef struct pci_fun_data {
+	pci_bus_t *busptr;
+	ddf_fun_t *fnode;
+
+	int bus;
+	int dev;
+	int fn;
+	int vendor_id;
+	int device_id;
+	hw_resource_list_t hw_resources;
+} pci_fun_t;
+
+extern void pci_fun_create_match_ids(pci_fun_t *);
+
+extern uint8_t pci_conf_read_8(pci_fun_t *, int);
+extern uint16_t pci_conf_read_16(pci_fun_t *, int);
+extern uint32_t pci_conf_read_32(pci_fun_t *, int);
+extern void pci_conf_write_8(pci_fun_t *, int, uint8_t);
+extern void pci_conf_write_16(pci_fun_t *, int, uint16_t);
+extern void pci_conf_write_32(pci_fun_t *, int, uint32_t);
+
+extern void pci_add_range(pci_fun_t *, uint64_t, size_t, bool);
+extern int pci_read_bar(pci_fun_t *, int);
+extern void pci_read_interrupt(pci_fun_t *);
+extern void pci_add_interrupt(pci_fun_t *, int);
+
+extern pci_fun_t *pci_fun_new(pci_bus_t *);
+extern void pci_fun_init(pci_fun_t *, int, int, int);
+extern void pci_fun_delete(pci_fun_t *);
+extern char *pci_fun_create_name(pci_fun_t *);
+
+extern void pci_bus_scan(pci_bus_t *, int);
+
+extern bool pci_alloc_resource_list(pci_fun_t *);
+extern void pci_clean_resource_list(pci_fun_t *);
+
+extern void pci_read_bars(pci_fun_t *);
+extern size_t pci_bar_mask_to_size(uint32_t);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/pci/pciintel/pci_regs.h
===================================================================
--- uspace/drv/bus/pci/pciintel/pci_regs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/pci/pciintel/pci_regs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,101 @@
+/*
+ * 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 pciintel
+ * @{
+ */
+/** @file
+ */
+
+#ifndef PCI_REGS_H_
+#define PCI_REGS_H_
+
+/* Header types */
+#define PCI_HEADER_TYPE_DEV	0
+#define PCI_HEADER_TYPE_BRIDGE	1
+#define PCI_HEADER_TYPE_CARDBUS	2
+
+/* Header type 0 and 1 */
+#define PCI_VENDOR_ID		0x00
+#define PCI_DEVICE_ID		0x02
+#define PCI_COMMAND		0x04
+#define PCI_STATUS		0x06
+#define PCI_REVISION_ID		0x08
+#define PCI_PROG_IF		0x09
+#define PCI_SUB_CLASS		0x0A
+#define PCI_BASE_CLASS		0x0B
+#define PCI_CACHE_LINE_SIZE	0x0C
+#define PCI_LATENCY_TIMER	0x0D
+#define PCI_HEADER_TYPE		0x0E
+#define PCI_BIST		0x0F
+
+#define PCI_BASE_ADDR_0		0x10
+#define PCI_BASE_ADDR_1		0x14
+
+/* Header type 0 */
+#define PCI_BASE_ADDR_2			0x18
+#define PCI_BASE_ADDR_3			0x1B
+#define PCI_BASE_ADDR_4			0x20
+#define PCI_BASE_ADDR_5			0x24
+
+#define PCI_CARDBUS_CIS_PTR		0x28
+#define PCI_SUBSYSTEM_VENDOR_ID		0x2C
+#define PCI_SUBSYSTEM_ID		0x2E
+#define PCI_EXP_ROM_BASE		0x30
+#define PCI_CAP_PTR			0x34
+#define PCI_INT_LINE			0x3C
+#define PCI_INT_PIN			0x3D
+#define PCI_MIN_GNT			0x3E
+#define PCI_MAX_LAT			0x3F
+
+/* Header type 1 */
+#define PCI_BRIDGE_PRIM_BUS_NUM		0x18
+#define PCI_BRIDGE_SEC_BUS_NUM		0x19
+#define PCI_BRIDGE_SUBORD_BUS_NUM	0x1A
+#define PCI_BRIDGE_SEC_LATENCY_TIMER	0x1B
+#define PCI_BRIDGE_IO_BASE		0x1C
+#define PCI_BRIDGE_IO_LIMIT		0x1D
+#define PCI_BRIDGE_SEC_STATUS		0x1E
+#define PCI_BRIDGE_MEMORY_BASE		0x20
+#define PCI_BRIDGE_MEMORY_LIMIT		0x22
+#define PCI_BRIDGE_PREF_MEMORY_BASE	0x24
+#define PCI_BRIDGE_PREF_MEMORY_LIMIT	0x26
+#define PCI_BRIDGE_PREF_MEMORY_BASE_UP	0x28
+#define PCI_BRIDGE_PREF_MEMORY_LIMIT_UP	0x2C
+#define PCI_BRIDGE_IO_BASE_UP		0x30
+#define PCI_BRIDGE_IO_LIMIT_UP		0x32
+#define PCI_BRIDGE_EXP_ROM_BASE		0x38
+#define PCI_BRIDGE_INT_LINE		0x3C
+#define PCI_BRIDGE_INT_PIN		0x3D
+#define PCI_BRIDGE_CTL			0x3E
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/pci/pciintel/pciintel.ma
===================================================================
--- uspace/drv/bus/pci/pciintel/pciintel.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/pci/pciintel/pciintel.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 intel_pci
Index: uspace/drv/bus/usb/ehci/Makefile
===================================================================
--- uspace/drv/bus/usb/ehci/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ehci/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = ehci
+
+SOURCES = \
+	hc_iface.c \
+	main.c \
+	pci.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/ehci/ehci.h
===================================================================
--- uspace/drv/bus/usb/ehci/ehci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ehci/ehci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 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 drvusbehci
+ * @{
+ */
+/** @file
+ * Common EHCI definitions.
+ */
+#ifndef DRV_EHCI_EHCI_H
+#define DRV_EHCI_EHCI_H
+
+#include <usbhc_iface.h>
+
+#define NAME "ehci"
+
+extern usbhc_iface_t ehci_hc_iface;
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ehci/ehci.ma
===================================================================
--- uspace/drv/bus/usb/ehci/ehci.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ehci/ehci.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,39 @@
+10 pci/ven=1002&dev=4345
+10 pci/ven=1002&dev=4386
+10 pci/ven=1002&dev=4396
+10 pci/ven=1002&dev=4373
+10 pci/ven=1022&dev=7463
+10 pci/ven=1022&dev=7808
+10 pci/ven=102f&dev=01b5
+10 pci/ven=10cf&dev=1415
+10 pci/ven=10de&dev=00e8
+10 pci/ven=10de&dev=055f
+10 pci/ven=10de&dev=056a
+10 pci/ven=10de&dev=077c
+10 pci/ven=10de&dev=077e
+10 pci/ven=10de&dev=0aa6
+10 pci/ven=10de&dev=0aa9
+10 pci/ven=10de&dev=0aaa
+10 pci/ven=10de&dev=0d9d
+10 pci/ven=1166&dev=0414
+10 pci/ven=1166&dev=0416
+10 pci/ven=1414&dev=5805
+10 pci/ven=1414&dev=5807
+10 pci/ven=15ad&dev=0770
+10 pci/ven=17a0&dev=8084
+10 pci/ven=8086&dev=24cd
+10 pci/ven=8086&dev=24dd
+10 pci/ven=8086&dev=265c
+10 pci/ven=8086&dev=268c
+10 pci/ven=8086&dev=27cc
+10 pci/ven=8086&dev=2836
+10 pci/ven=8086&dev=283a
+10 pci/ven=8086&dev=293a
+10 pci/ven=8086&dev=293c
+10 pci/ven=8086&dev=3a3a
+10 pci/ven=8086&dev=3a3c
+10 pci/ven=8086&dev=3a6a
+10 pci/ven=8086&dev=3a6c
+10 pci/ven=8086&dev=8117
+10 pci/ven=8086&dev=8807
+10 pci/ven=8086&dev=880f
Index: uspace/drv/bus/usb/ehci/hc_iface.c
===================================================================
--- uspace/drv/bus/usb/ehci/hc_iface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ehci/hc_iface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2011 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 drvusbehci
+ * @{
+ */
+/** @file
+ * USB-HC interface implementation.
+ */
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
+#include <device/hw_res.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "ehci.h"
+
+#define UNSUPPORTED(methodname) \
+	usb_log_debug("Client called unsupported interface method " \
+	    "`%s()' in %s:%d.\n", \
+	    methodname, __FILE__, __LINE__)
+
+/** Found free USB address.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] speed Speed of the device that will get this address.
+ * @param[out] address Non-null pointer where to store the free address.
+ * @return Error code.
+ */
+static int request_address(ddf_fun_t *fun, usb_speed_t speed,
+    usb_address_t *address)
+{
+	UNSUPPORTED("request_address");
+
+	return ENOTSUP;
+}
+
+/** Bind USB address with device devman handle.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] handle Devman handle of the device.
+ * @return Error code.
+ */
+static int bind_address(ddf_fun_t *fun,
+    usb_address_t address, devman_handle_t handle)
+{
+	UNSUPPORTED("bind_address");
+
+	return ENOTSUP;
+}
+
+/** Find device handle by USB address.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	UNSUPPORTED("find_by_address");
+
+	return ENOTSUP;
+}
+
+/** Release previously requested address.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	UNSUPPORTED("release_address");
+
+	return ENOTSUP;
+}
+
+/** Register endpoint for bandwidth reservation.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] speed Endpoint speed (invalid means to use device one).
+ * @param[in] endpoint Endpoint number.
+ * @param[in] transfer_type USB transfer type.
+ * @param[in] direction Endpoint data direction.
+ * @param[in] max_packet_size Max packet size of the endpoint.
+ * @param[in] interval Polling interval.
+ * @return Error code.
+ */
+static int register_endpoint(ddf_fun_t *fun,
+    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	UNSUPPORTED("register_endpoint");
+
+	return ENOTSUP;
+}
+
+/** Unregister endpoint (free some bandwidth reservation).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint Endpoint number.
+ * @param[in] direction Endpoint data direction.
+ * @return Error code.
+ */
+static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	UNSUPPORTED("unregister_endpoint");
+
+	return ENOTSUP;
+}
+
+/** Schedule interrupt out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	UNSUPPORTED("interrupt_out");
+
+	return ENOTSUP;
+}
+
+/** Schedule interrupt in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	UNSUPPORTED("interrupt_in");
+
+	return ENOTSUP;
+}
+
+/** Schedule bulk out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_out(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	UNSUPPORTED("bulk_out");
+
+	return ENOTSUP;
+}
+
+/** Schedule bulk in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_in(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	UNSUPPORTED("bulk_in");
+
+	return ENOTSUP;
+}
+
+/** Schedule control write transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Data buffer (in USB endianess, allocated and
+ *	deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_write(ddf_fun_t *fun, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data_buffer, size_t data_buffer_size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	UNSUPPORTED("control_write");
+
+	return ENOTSUP;
+}
+
+/** Schedule control read transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_read(ddf_fun_t *fun, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data_buffer, size_t data_buffer_size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	UNSUPPORTED("control_read");
+
+	return ENOTSUP;
+}
+
+/** Host controller interface implementation for EHCI. */
+usbhc_iface_t ehci_hc_iface = {
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.find_by_address = find_by_address,
+	.release_address = release_address,
+
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.bulk_out = bulk_out,
+	.bulk_in = bulk_in,
+
+	.control_write = control_write,
+	.control_read = control_read
+};
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ehci/main.c
===================================================================
--- uspace/drv/bus/usb/ehci/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ehci/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2011 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 drvusbehci
+ * @{
+ */
+/** @file
+ * Main routines of EHCI driver.
+ */
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
+#include <device/hw_res.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "pci.h"
+#include "ehci.h"
+
+static int ehci_add_device(ddf_dev_t *device);
+/*----------------------------------------------------------------------------*/
+static driver_ops_t ehci_driver_ops = {
+	.add_device = ehci_add_device,
+};
+/*----------------------------------------------------------------------------*/
+static driver_t ehci_driver = {
+	.name = NAME,
+	.driver_ops = &ehci_driver_ops
+};
+static ddf_dev_ops_t hc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &ehci_hc_iface,
+};
+
+/*----------------------------------------------------------------------------*/
+/** Initializes a new ddf driver instance of EHCI hcd.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int ehci_add_device(ddf_dev_t *device)
+{
+	assert(device);
+#define CHECK_RET_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	return ret; \
+}
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
+	int irq = 0;
+
+	int ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_RETURN(ret,
+	    "Failed to get memory addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_info("Memory mapped regs at 0x%" PRIxn " (size %zu), IRQ %d.\n",
+	    reg_base, reg_size, irq);
+
+	ret = pci_disable_legacy(device, reg_base, reg_size, irq);
+	CHECK_RET_RETURN(ret,
+	    "Failed to disable legacy USB: %s.\n", str_error(ret));
+
+	ddf_fun_t *hc_fun = ddf_fun_create(device, fun_exposed, "ehci_hc");
+	if (hc_fun == NULL) {
+		usb_log_error("Failed to create EHCI function.\n");
+		return ENOMEM;
+	}
+	hc_fun->ops = &hc_ops;
+
+	ret = ddf_fun_bind(hc_fun);
+	CHECK_RET_RETURN(ret,
+	    "Failed to bind EHCI function: %s.\n",
+	    str_error(ret));
+	ret = ddf_fun_add_to_category(hc_fun, USB_HC_CATEGORY);
+	CHECK_RET_RETURN(ret,
+	    "Failed to add EHCI to HC class: %s.\n",
+	    str_error(ret));
+
+	usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",
+	    device->name, device->handle);
+
+	return EOK;
+#undef CHECK_RET_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initializes global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	return ddf_driver_main(&ehci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ehci/pci.c
===================================================================
--- uspace/drv/bus/usb/ehci/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ehci/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,391 @@
+/*
+ * 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 drvusbehci
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the EHCI driver.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+#include <as.h>
+#include <devman.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <device/hw_res.h>
+
+#include <usb/debug.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+#define PAGE_SIZE_MASK 0xfffff000
+
+#define HCC_PARAMS_OFFSET 0x8
+#define HCC_PARAMS_EECP_MASK 0xff
+#define HCC_PARAMS_EECP_OFFSET 8
+
+#define CMD_OFFSET 0x0
+#define STS_OFFSET 0x4
+#define INT_OFFSET 0x8
+#define CFG_OFFSET 0x40
+
+#define USBCMD_RUN 1
+#define USBSTS_HALTED (1 << 12)
+
+#define USBLEGSUP_OFFSET 0
+#define USBLEGSUP_BIOS_CONTROL (1 << 16)
+#define USBLEGSUP_OS_CONTROL (1 << 24)
+#define USBLEGCTLSTS_OFFSET 4
+
+#define DEFAULT_WAIT 1000
+#define WAIT_STEP 10
+
+#define PCI_READ(size) \
+do { \
+	async_sess_t *parent_sess = \
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, \
+	    IPC_FLAG_BLOCKING); \
+	if (!parent_sess) \
+		return ENOMEM; \
+	\
+	sysarg_t add = (sysarg_t) address; \
+	sysarg_t val; \
+	\
+	async_exch_t *exch = async_exchange_begin(parent_sess); \
+	\
+	const int ret = \
+	    async_req_2_1(exch, DEV_IFACE_ID(PCI_DEV_IFACE), \
+	        IPC_M_CONFIG_SPACE_READ_##size, add, &val); \
+	\
+	async_exchange_end(exch); \
+	async_hangup(parent_sess); \
+	\
+	assert(value); \
+	\
+	*value = val; \
+	return ret; \
+} while (0)
+
+static int pci_read32(const ddf_dev_t *dev, int address, uint32_t *value)
+{
+	PCI_READ(32);
+}
+
+static int pci_read16(const ddf_dev_t *dev, int address, uint16_t *value)
+{
+	PCI_READ(16);
+}
+
+static int pci_read8(const ddf_dev_t *dev, int address, uint8_t *value)
+{
+	PCI_READ(8);
+}
+
+#define PCI_WRITE(size) \
+do { \
+	async_sess_t *parent_sess = \
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, \
+	    IPC_FLAG_BLOCKING); \
+	if (!parent_sess) \
+		return ENOMEM; \
+	\
+	sysarg_t add = (sysarg_t) address; \
+	sysarg_t val = value; \
+	\
+	async_exch_t *exch = async_exchange_begin(parent_sess); \
+	\
+	const int ret = \
+	    async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE), \
+	        IPC_M_CONFIG_SPACE_WRITE_##size, add, val); \
+	\
+	async_exchange_end(exch); \
+	async_hangup(parent_sess); \
+	\
+	return ret; \
+} while(0)
+
+static int pci_write32(const ddf_dev_t *dev, int address, uint32_t value)
+{
+	PCI_WRITE(32);
+}
+
+static int pci_write16(const ddf_dev_t *dev, int address, uint16_t value)
+{
+	PCI_WRITE(16);
+}
+
+static int pci_write8(const ddf_dev_t *dev, int address, uint8_t value)
+{
+	PCI_WRITE(8);
+}
+
+/** Get address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] mem_reg_address Base address of the memory range.
+ * @param[out] mem_reg_size Size of the memory range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(const ddf_dev_t *dev,
+    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
+{
+	assert(dev != NULL);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	hw_resource_list_t hw_resources;
+	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (rc != EOK) {
+		async_hangup(parent_sess);
+		return rc;
+	}
+	
+	uintptr_t mem_address = 0;
+	size_t mem_size = 0;
+	bool mem_found = false;
+	
+	int irq = 0;
+	bool irq_found = false;
+	
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			irq = res->res.interrupt.irq;
+			irq_found = true;
+			usb_log_debug2("Found interrupt: %d.\n", irq);
+			break;
+		case MEM_RANGE:
+			if (res->res.mem_range.address != 0
+			    && res->res.mem_range.size != 0 ) {
+				mem_address = res->res.mem_range.address;
+				mem_size = res->res.mem_range.size;
+				usb_log_debug2("Found mem: %" PRIxn" %zu.\n",
+				    mem_address, mem_size);
+				mem_found = true;
+			}
+		default:
+			break;
+		}
+	}
+	
+	if (mem_found && irq_found) {
+		*mem_reg_address = mem_address;
+		*mem_reg_size = mem_size;
+		*irq_no = irq;
+		rc = EOK;
+	} else {
+		rc = ENOENT;
+	}
+	
+	async_hangup(parent_sess);
+	return rc;
+}
+/*----------------------------------------------------------------------------*/
+/** Calls the PCI driver with a request to enable interrupts
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_enable_interrupts(const ddf_dev_t *device)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	const bool enabled = hw_res_enable_interrupt(parent_sess);
+	async_hangup(parent_sess);
+	
+	return enabled ? EOK : EIO;
+}
+/*----------------------------------------------------------------------------*/
+/** Implements BIOS handoff routine as decribed in EHCI spec
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_disable_legacy(
+    const ddf_dev_t *device, uintptr_t reg_base, size_t reg_size, int irq)
+{
+	assert(device);
+	(void) pci_read16;
+	(void) pci_read8;
+	(void) pci_write16;
+
+#define CHECK_RET_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		return ret; \
+	} else (void)0
+
+	/* Map EHCI registers */
+	void *regs = NULL;
+	int ret = pio_enable((void*)reg_base, reg_size, &regs);
+	CHECK_RET_RETURN(ret, "Failed to map registers %p: %s.\n",
+	    (void *) reg_base, str_error(ret));
+
+	const uint32_t hcc_params =
+	    *(uint32_t*)(regs + HCC_PARAMS_OFFSET);
+	usb_log_debug("Value of hcc params register: %x.\n", hcc_params);
+
+	/* Read value of EHCI Extended Capabilities Pointer
+	 * position of EEC registers (points to PCI config space) */
+	const uint32_t eecp =
+	    (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK;
+	usb_log_debug("Value of EECP: %x.\n", eecp);
+
+	/* Read the first EEC. i.e. Legacy Support register */
+	uint32_t usblegsup;
+	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
+	CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
+	usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
+
+	/* Request control from firmware/BIOS, by writing 1 to highest byte.
+	 * (OS Control semaphore)*/
+	usb_log_debug("Requesting OS control.\n");
+	ret = pci_write8(device, eecp + USBLEGSUP_OFFSET + 3, 1);
+	CHECK_RET_RETURN(ret, "Failed to request OS EHCI control: %s.\n",
+	    str_error(ret));
+
+	size_t wait = 0;
+	/* Wait for BIOS to release control. */
+	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
+	while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) {
+		async_usleep(WAIT_STEP);
+		ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
+		wait += WAIT_STEP;
+	}
+
+
+	if ((usblegsup & USBLEGSUP_BIOS_CONTROL) == 0) {
+		usb_log_info("BIOS released control after %zu usec.\n", wait);
+	} else {
+		/* BIOS failed to hand over control, this should not happen. */
+		usb_log_warning( "BIOS failed to release control after "
+		    "%zu usecs, force it.\n", wait);
+		ret = pci_write32(device, eecp + USBLEGSUP_OFFSET,
+		    USBLEGSUP_OS_CONTROL);
+		CHECK_RET_RETURN(ret, "Failed to force OS control: %s.\n",
+		    str_error(ret));
+		/* Check capability type here, A value of 01h
+		 * identifies the capability as Legacy Support.
+		 * This extended capability requires one
+		 * additional 32-bit register for control/status information,
+		 * and this register is located at offset EECP+04h
+		 * */
+		if ((usblegsup & 0xff) == 1) {
+			/* Read the second EEC
+			 * Legacy Support and Control register */
+			uint32_t usblegctlsts;
+			ret = pci_read32(
+			    device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
+			CHECK_RET_RETURN(ret,
+			    "Failed to get USBLEGCTLSTS: %s.\n", str_error(ret));
+			usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n",
+			    usblegctlsts);
+			/* Zero SMI enables in legacy control register.
+			 * It should prevent pre-OS code from interfering. */
+			ret = pci_write32(device, eecp + USBLEGCTLSTS_OFFSET,
+			    0xe0000000); /* three upper bits are WC */
+			CHECK_RET_RETURN(ret,
+			    "Failed(%d) zero USBLEGCTLSTS.\n", ret);
+			udelay(10);
+			ret = pci_read32(
+			    device, eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts);
+			CHECK_RET_RETURN(ret,
+			    "Failed to get USBLEGCTLSTS 2: %s.\n",
+			    str_error(ret));
+			usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n",
+			    usblegctlsts);
+		}
+	}
+
+
+	/* Read again Legacy Support register */
+	ret = pci_read32(device, eecp + USBLEGSUP_OFFSET, &usblegsup);
+	CHECK_RET_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", str_error(ret));
+	usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup);
+
+	/*
+	 * TURN OFF EHCI FOR NOW, DRIVER WILL REINITIALIZE IT
+	 */
+
+	/* Get size of capability registers in memory space. */
+	const unsigned operation_offset = *(uint8_t*)regs;
+	usb_log_debug("USBCMD offset: %d.\n", operation_offset);
+
+	/* Zero USBCMD register. */
+	volatile uint32_t *usbcmd =
+	    (uint32_t*)((uint8_t*)regs + operation_offset + CMD_OFFSET);
+	volatile uint32_t *usbsts =
+	    (uint32_t*)((uint8_t*)regs + operation_offset + STS_OFFSET);
+	volatile uint32_t *usbconf =
+	    (uint32_t*)((uint8_t*)regs + operation_offset + CFG_OFFSET);
+	volatile uint32_t *usbint =
+	    (uint32_t*)((uint8_t*)regs + operation_offset + INT_OFFSET);
+	usb_log_debug("USBCMD value: %x.\n", *usbcmd);
+	if (*usbcmd & USBCMD_RUN) {
+		*usbsts = 0x3f; /* ack all interrupts */
+		*usbint = 0; /* disable all interrutps */
+		*usbconf = 0; /* relase control of RH ports */
+
+		*usbcmd = 0;
+		/* Wait until hc is halted */
+		while ((*usbsts & USBSTS_HALTED) == 0);
+		usb_log_info("EHCI turned off.\n");
+	} else {
+		usb_log_info("EHCI was not running.\n");
+	}
+	usb_log_debug("Registers: \n"
+	    "\t USBCMD: %x(0x00080000 = at least 1ms between interrupts)\n"
+	    "\t USBSTS: %x(0x00001000 = HC halted)\n"
+	    "\t USBINT: %x(0x0 = no interrupts).\n"
+	    "\t CONFIG: %x(0x0 = ports controlled by companion hc).\n",
+	    *usbcmd, *usbsts, *usbint, *usbconf);
+
+	return ret;
+#undef CHECK_RET_RETURN
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ehci/pci.h
===================================================================
--- uspace/drv/bus/usb/ehci/pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ehci/pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 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 drvusbehci
+ * @{
+ */
+/** @file
+ * PCI related functions needed by EHCI driver.
+ */
+#ifndef DRV_EHCI_PCI_H
+#define DRV_EHCI_PCI_H
+
+#include <ddf/driver.h>
+
+int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(const ddf_dev_t *);
+int pci_disable_legacy(const ddf_dev_t *, uintptr_t, size_t, int);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/Makefile
===================================================================
--- uspace/drv/bus/usb/ohci/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = ohci
+
+SOURCES = \
+	batch.c \
+	endpoint_list.c \
+	hc.c \
+	hcd_endpoint.c \
+	iface.c \
+	main.c \
+	ohci.c \
+	pci.c \
+	root_hub.c \
+	hw_struct/endpoint_descriptor.c \
+	hw_struct/transfer_descriptor.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/ohci/batch.c
===================================================================
--- uspace/drv/bus/usb/ohci/batch.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/batch.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,429 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver USB transaction structure
+ */
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/usb.h>
+#include <usb/debug.h>
+
+#include "batch.h"
+#include "hcd_endpoint.h"
+#include "utils/malloc32.h"
+#include "hw_struct/endpoint_descriptor.h"
+#include "hw_struct/transfer_descriptor.h"
+
+/** OHCI specific data required for USB transfer */
+typedef struct ohci_transfer_batch {
+	/** Endpoint descriptor of the target endpoint. */
+	ed_t *ed;
+	/** List of TDs needed for the transfer */
+	td_t **tds;
+	/** Number of TDs used by the transfer */
+	size_t td_count;
+	/** Dummy TD to be left at the ED and used by the next transfer */
+	size_t leave_td;
+	/** Data buffer, must be accessible byb the OHCI hw. */
+	void *device_buffer;
+} ohci_transfer_batch_t;
+/*----------------------------------------------------------------------------*/
+static void batch_control(usb_transfer_batch_t *instance,
+    usb_direction_t data_dir, usb_direction_t status_dir);
+static void batch_data(usb_transfer_batch_t *instance);
+/*----------------------------------------------------------------------------*/
+/** Safely destructs ohci_transfer_batch_t structure
+ *
+ * @param[in] ohci_batch Instance to destroy.
+ */
+static void ohci_transfer_batch_dispose(void *ohci_batch)
+{
+	ohci_transfer_batch_t *instance = ohci_batch;
+	if (!instance)
+		return;
+	free32(instance->device_buffer);
+	unsigned i = 0;
+	if (instance->tds) {
+		for (; i< instance->td_count; ++i) {
+			if (i != instance->leave_td)
+				free32(instance->tds[i]);
+		}
+		free(instance->tds);
+	}
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Allocate memory initialize internal structures
+ *
+ * @param[in] fun DDF function to pass to callback.
+ * @param[in] ep Communication target
+ * @param[in] buffer Data source/destination.
+ * @param[in] buffer_size Size of the buffer.
+ * @param[in] setup_buffer Setup data source (if not NULL)
+ * @param[in] setup_size Size of setup_buffer (should be always 8)
+ * @param[in] func_in function to call on inbound transfer completion
+ * @param[in] func_out function to call on outbound transfer completion
+ * @param[in] arg additional parameter to func_in or func_out
+ * @return Valid pointer if all structures were successfully created,
+ * NULL otherwise.
+ *
+ * Allocates and initializes structures needed by the OHCI hw for the transfer.
+ */
+usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
+    char *buffer, size_t buffer_size,
+    const char *setup_buffer, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out, void *arg)
+{
+#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
+        if (ptr == NULL) { \
+                usb_log_error(message); \
+                if (instance) { \
+                        usb_transfer_batch_dispose(instance); \
+                } \
+                return NULL; \
+        } else (void)0
+
+	usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
+	CHECK_NULL_DISPOSE_RETURN(instance,
+	    "Failed to allocate batch instance.\n");
+	usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size,
+	    NULL, setup_size, func_in, func_out, arg, fun, NULL,
+	    ohci_transfer_batch_dispose);
+
+	const hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
+	assert(hcd_ep);
+
+	ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1);
+	CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
+	instance->private_data = data;
+
+	data->td_count =
+	    ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER);
+	/* Control transfer need Setup and Status stage */
+	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
+		data->td_count += 2;
+	}
+
+	/* We need an extra place for TD that is currently assigned to hcd_ep*/
+	data->tds = calloc(sizeof(td_t*), data->td_count + 1);
+	CHECK_NULL_DISPOSE_RETURN(data->tds,
+	    "Failed to allocate transfer descriptors.\n");
+
+	/* Add TD left over by the previous transfer */
+	data->tds[0] = hcd_ep->td;
+	data->leave_td = 0;
+	unsigned i = 1;
+	for (; i <= data->td_count; ++i) {
+		data->tds[i] = malloc32(sizeof(td_t));
+		CHECK_NULL_DISPOSE_RETURN(data->tds[i],
+		    "Failed to allocate TD %d.\n", i );
+	}
+
+	data->ed = hcd_ep->ed;
+
+	/* NOTE: OHCI is capable of handling buffer that crosses page boundaries
+	 * it is, however, not capable of handling buffer that occupies more
+	 * than two pages (the first page is computed using start pointer, the
+	 * other using the end pointer) */
+        if (setup_size + buffer_size > 0) {
+		data->device_buffer = malloc32(setup_size + buffer_size);
+                CHECK_NULL_DISPOSE_RETURN(data->device_buffer,
+                    "Failed to allocate device accessible buffer.\n");
+		instance->setup_buffer = data->device_buffer;
+		instance->data_buffer = data->device_buffer + setup_size;
+                memcpy(instance->setup_buffer, setup_buffer, setup_size);
+        }
+
+	return instance;
+}
+/*----------------------------------------------------------------------------*/
+/** Check batch TDs' status.
+ *
+ * @param[in] instance Batch structure to use.
+ * @return False, if there is an active TD, true otherwise.
+ *
+ * Walk all TDs (usually there is just one). Stop with false if there is an
+ * active TD. Stop with true if an error is found. Return true if the walk
+ * completes with the last TD.
+ */
+bool batch_is_complete(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n",
+	    instance, data->td_count);
+	usb_log_debug("ED: %x:%x:%x:%x.\n",
+	    data->ed->status, data->ed->td_head, data->ed->td_tail,
+	    data->ed->next);
+	size_t i = 0;
+	instance->transfered_size = instance->buffer_size;
+	for (; i < data->td_count; ++i) {
+		assert(data->tds[i] != NULL);
+		usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
+		    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
+		    data->tds[i]->be);
+		if (!td_is_finished(data->tds[i])) {
+			return false;
+		}
+		instance->error = td_error(data->tds[i]);
+		if (instance->error != EOK) {
+			usb_log_debug("Batch(%p) found error TD(%zu):%x.\n",
+			    instance, i, data->tds[i]->status);
+			/* Make sure TD queue is empty (one TD),
+			 * ED should be marked as halted */
+			data->ed->td_tail =
+			    (data->ed->td_head & ED_TDTAIL_PTR_MASK);
+			++i;
+			break;
+		}
+	}
+	data->leave_td = i;
+	assert(data->leave_td <= data->td_count);
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep);
+	assert(hcd_ep);
+	hcd_ep->td = data->tds[i];
+	assert(i > 0);
+	for (--i;i < data->td_count; ++i)
+		instance->transfered_size -= td_remain_size(data->tds[i]);
+
+	/* Clear possible ED HALT */
+	data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+	const uint32_t pa = addr_to_phys(hcd_ep->td);
+	assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK));
+	assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK));
+
+	return true;
+}
+/*----------------------------------------------------------------------------*/
+/** Starts execution of the TD list
+ *
+ * @param[in] instance Batch structure to use
+ */
+void batch_commit(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	ed_set_end_td(data->ed, data->tds[data->td_count]);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares control write transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control transfer using direction OUT(data stage) and
+ * IN(status stage).
+ */
+void batch_control_write(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN);
+	usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares control read transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control transfer using direction IN(data stage) and
+ * OUT(status stage).
+ */
+void batch_control_read(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT);
+	usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare interrupt in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
+void batch_interrupt_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_data(instance);
+	usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare interrupt out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
+void batch_interrupt_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	batch_data(instance);
+	usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare bulk in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
+void batch_bulk_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	batch_data(instance);
+	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare bulk out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer.
+ */
+void batch_bulk_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	batch_data(instance);
+	usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare generic control transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] data_dir Direction to use for data stage.
+ * @param[in] status_dir Direction to use for status stage.
+ *
+ * Setup stage with toggle 0 and direction BOTH(SETUP_PID)
+ * Data stage with alternating toggle and direction supplied by parameter.
+ * Status stage with toggle 1 and direction supplied by parameter.
+ */
+void batch_control(usb_transfer_batch_t *instance,
+    usb_direction_t data_dir, usb_direction_t status_dir)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
+	    data->ed->status, data->ed->td_tail, data->ed->td_head,
+	    data->ed->next);
+	int toggle = 0;
+	/* setup stage */
+	td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,
+		instance->setup_size, toggle);
+	td_set_next(data->tds[0], data->tds[1]);
+	usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status,
+	    data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be);
+
+	/* data stage */
+	size_t td_current = 1;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
+		    OHCI_TD_MAX_TRANSFER : remain_size;
+		toggle = 1 - toggle;
+
+		td_init(data->tds[td_current], data_dir, buffer,
+		    transfer_size, toggle);
+		td_set_next(data->tds[td_current], data->tds[td_current + 1]);
+		usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
+		    data->tds[td_current]->status, data->tds[td_current]->cbp,
+		    data->tds[td_current]->next, data->tds[td_current]->be);
+
+		buffer += transfer_size;
+		remain_size -= transfer_size;
+		assert(td_current < data->td_count - 1);
+		++td_current;
+	}
+
+	/* status stage */
+	assert(td_current == data->td_count - 1);
+	td_init(data->tds[td_current], status_dir, NULL, 0, 1);
+	td_set_next(data->tds[td_current], data->tds[td_current + 1]);
+	usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n",
+	    data->tds[td_current]->status, data->tds[td_current]->cbp,
+	    data->tds[td_current]->next, data->tds[td_current]->be);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare generic data transfer
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Direction is supplied by the associated ep and toggle is maintained by the
+ * OHCI hw in ED.
+ */
+void batch_data(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	ohci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,
+	    data->ed->status, data->ed->td_tail, data->ed->td_head,
+	    data->ed->next);
+
+	size_t td_current = 0;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		const size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER
+		    ? OHCI_TD_MAX_TRANSFER : remain_size;
+
+		td_init(data->tds[td_current], instance->ep->direction,
+		    buffer, transfer_size, -1);
+		td_set_next(data->tds[td_current], data->tds[td_current + 1]);
+		usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
+		    data->tds[td_current]->status, data->tds[td_current]->cbp,
+		    data->tds[td_current]->next, data->tds[td_current]->be);
+
+		buffer += transfer_size;
+		remain_size -= transfer_size;
+		assert(td_current < data->td_count);
+		++td_current;
+	}
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/batch.h
===================================================================
--- uspace/drv/bus/usb/ohci/batch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/batch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,68 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver USB transaction structure
+ */
+#ifndef DRV_OHCI_BATCH_H
+#define DRV_OHCI_BATCH_H
+
+#include <usbhc_iface.h>
+#include <usb/usb.h>
+#include <usb/host/device_keeper.h>
+#include <usb/host/endpoint.h>
+#include <usb/host/batch.h>
+
+usb_transfer_batch_t * batch_get(
+    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
+    const char *setup_buffer, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out,
+    void *arg);
+
+bool batch_is_complete(usb_transfer_batch_t *instance);
+
+void batch_commit(usb_transfer_batch_t *instance);
+
+void batch_control_write(usb_transfer_batch_t *instance);
+
+void batch_control_read(usb_transfer_batch_t *instance);
+
+void batch_interrupt_in(usb_transfer_batch_t *instance);
+
+void batch_interrupt_out(usb_transfer_batch_t *instance);
+
+void batch_bulk_in(usb_transfer_batch_t *instance);
+
+void batch_bulk_out(usb_transfer_batch_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/endpoint_list.c
===================================================================
--- uspace/drv/bus/usb/ohci/endpoint_list.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/endpoint_list.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,179 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver transfer list implementation
+ */
+
+#include <errno.h>
+#include <usb/debug.h>
+#include <libarch/barrier.h>
+#include "endpoint_list.h"
+
+/** Initialize transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ * @param[in] name Name of the new list.
+ * @return Error code
+ *
+ * Allocates memory for internal ed_t structure.
+ */
+int endpoint_list_init(endpoint_list_t *instance, const char *name)
+{
+	assert(instance);
+	instance->name = name;
+	instance->list_head = malloc32(sizeof(ed_t));
+	if (!instance->list_head) {
+		usb_log_error("Failed to allocate list head.\n");
+		return ENOMEM;
+	}
+	instance->list_head_pa = addr_to_phys(instance->list_head);
+	usb_log_debug2("Transfer list %s setup with ED: %p(0x%0" PRIx32 ")).\n",
+	    name, instance->list_head, instance->list_head_pa);
+
+	ed_init(instance->list_head, NULL);
+	list_initialize(&instance->endpoint_list);
+	fibril_mutex_initialize(&instance->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Set the next list in transfer list chain.
+ *
+ * @param[in] instance List to lead.
+ * @param[in] next List to append.
+ *
+ * Does not check whether this replaces an existing list.
+ */
+void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
+{
+	assert(instance);
+	assert(next);
+	ed_append_ed(instance->list_head, next->list_head);
+}
+/*----------------------------------------------------------------------------*/
+/** Add endpoint to the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] endpoint Endpoint to add.
+ *
+ * The endpoint is added to the end of the list and queue.
+ */
+void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
+{
+	assert(instance);
+	assert(hcd_ep);
+	usb_log_debug2("Queue %s: Adding endpoint(%p).\n",
+	    instance->name, hcd_ep);
+
+	fibril_mutex_lock(&instance->guard);
+
+	ed_t *last_ed = NULL;
+	/* Add to the hardware queue. */
+	if (list_empty(&instance->endpoint_list)) {
+		/* There are no active EDs */
+		last_ed = instance->list_head;
+	} else {
+		/* There are active EDs, get the last one */
+		hcd_endpoint_t *last = list_get_instance(
+		    list_last(&instance->endpoint_list), hcd_endpoint_t, link);
+		last_ed = last->ed;
+	}
+	/* Keep link */
+	hcd_ep->ed->next = last_ed->next;
+	/* Make sure ED is written to the memory */
+	write_barrier();
+
+	/* Add ed to the hw queue */
+	ed_append_ed(last_ed, hcd_ep->ed);
+	/* Make sure ED is updated */
+	write_barrier();
+
+	/* Add to the sw list */
+	list_append(&hcd_ep->link, &instance->endpoint_list);
+
+	hcd_endpoint_t *first = list_get_instance(
+	    list_first(&instance->endpoint_list), hcd_endpoint_t, link);
+	usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n",
+		hcd_ep, instance->name, first, first->ed);
+	if (last_ed == instance->list_head) {
+		usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n",
+		    instance->name, last_ed, instance->list_head_pa,
+		    last_ed->status, last_ed->td_tail, last_ed->td_head,
+		    last_ed->next);
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Remove endpoint from the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] endpoint Endpoint to remove.
+ */
+void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep)
+{
+	assert(instance);
+	assert(instance->list_head);
+	assert(hcd_ep);
+	assert(hcd_ep->ed);
+
+	fibril_mutex_lock(&instance->guard);
+
+	usb_log_debug2(
+	    "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep);
+
+	const char *qpos = NULL;
+	ed_t *prev_ed;
+	/* Remove from the hardware queue */
+	if (list_first(&instance->endpoint_list) == &hcd_ep->link) {
+		/* I'm the first one here */
+		prev_ed = instance->list_head;
+		qpos = "FIRST";
+	} else {
+		hcd_endpoint_t *prev =
+		    list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link);
+		prev_ed = prev->ed;
+		qpos = "NOT FIRST";
+	}
+	assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed));
+	prev_ed->next = hcd_ep->ed->next;
+	/* Make sure ED is updated */
+	write_barrier();
+
+	usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n",
+	    hcd_ep, qpos, instance->name, hcd_ep->ed->next);
+
+	/* Remove from the endpoint list */
+	list_remove(&hcd_ep->link);
+	fibril_mutex_unlock(&instance->guard);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/endpoint_list.h
===================================================================
--- uspace/drv/bus/usb/ohci/endpoint_list.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/endpoint_list.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,76 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver transfer list structure
+ */
+#ifndef DRV_OHCI_ENDPOINT_LIST_H
+#define DRV_OHCI_ENDPOINT_LIST_H
+
+#include <fibril_synch.h>
+
+#include "hcd_endpoint.h"
+#include "hw_struct/endpoint_descriptor.h"
+#include "utils/malloc32.h"
+
+/** Structure maintains both OHCI queue and software list of active endpoints.*/
+typedef struct endpoint_list {
+	/** Guard against add/remove races */
+	fibril_mutex_t guard;
+	/** OHCI hw structure at the beginning of the queue */
+	ed_t *list_head;
+	/** Physical address of the first(dummy) ED */
+	uint32_t list_head_pa;
+	/** Assigned name, provides nicer debug output */
+	const char *name;
+	/** Sw list of all active EDs */
+	list_t endpoint_list;
+} endpoint_list_t;
+
+/** Dispose transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ *
+ * Frees memory of the internal ed_t structure.
+ */
+static inline void endpoint_list_fini(endpoint_list_t *instance)
+{
+	assert(instance);
+	free32(instance->list_head);
+}
+
+int endpoint_list_init(endpoint_list_t *instance, const char *name);
+void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
+void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
+void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,665 @@
+/*
+ * 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 drvusbohcihc
+ * @{
+ */
+/** @file
+ * @brief OHCI Host controller driver routines
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <adt/list.h>
+#include <libarch/ddi.h>
+
+#include <usb/debug.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+
+#include "hc.h"
+#include "hcd_endpoint.h"
+
+#define OHCI_USED_INTERRUPTS \
+    (I_SO | I_WDH | I_UE | I_RHSC)
+
+static const irq_cmd_t ohci_irq_commands[] =
+{
+	{ .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ },
+	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS },
+	{ .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
+	{ .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ },
+	{ .cmd = CMD_ACCEPT },
+};
+
+static void hc_gain_control(hc_t *instance);
+static void hc_start(hc_t *instance);
+static int hc_init_transfer_lists(hc_t *instance);
+static int hc_init_memory(hc_t *instance);
+static int interrupt_emulator(hc_t *instance);
+
+/*----------------------------------------------------------------------------*/
+/** Get number of commands used in IRQ code.
+ * @return Number of commands.
+ */
+size_t hc_irq_cmd_count(void)
+{
+	return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
+}
+/*----------------------------------------------------------------------------*/
+/** Generate IRQ code commands.
+ * @param[out] cmds Place to store the commands.
+ * @param[in] cmd_size Size of the place (bytes).
+ * @param[in] regs Physical address of device's registers.
+ * @param[in] reg_size Size of the register area (bytes).
+ *
+ * @return Error code.
+ */
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
+{
+	if (cmd_size < sizeof(ohci_irq_commands)
+	    || reg_size < sizeof(ohci_regs_t))
+		return EOVERFLOW;
+
+	/* Create register mapping to use in IRQ handler.
+	 * This mapping should be present in kernel only.
+	 * Remove it from here when kernel knows how to create mappings
+	 * and accepts physical addresses in IRQ code.
+	 * TODO: remove */
+	ohci_regs_t *registers;
+	const int ret = pio_enable((void*)regs, reg_size, (void**)&registers);
+	if (ret != EOK)
+		return ret;
+
+	/* Some bogus access to force create mapping. DO NOT remove,
+	 * unless whole virtual addresses in irq is replaced
+	 * NOTE: Compiler won't remove this as ohci_regs_t members
+	 * are declared volatile.
+	 *
+	 * Introducing CMD_MEM set of IRQ code commands broke
+	 * assumption that IRQ code does not cause page faults.
+	 * If this happens during idling (THREAD == NULL)
+	 * it causes kernel panic.
+	 */
+	registers->revision;
+
+	memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
+
+	void *address = (void*)&registers->interrupt_status;
+	cmds[0].addr = address;
+	cmds[3].addr = address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Announce OHCI root hub to the DDF
+ *
+ * @param[in] instance OHCI driver intance
+ * @param[in] hub_fun DDF fuction representing OHCI root hub
+ * @return Error code
+ */
+int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun)
+{
+	assert(instance);
+	assert(hub_fun);
+
+	const usb_address_t hub_address =
+	    device_keeper_get_free_address(&instance->manager, USB_SPEED_FULL);
+	if (hub_address <= 0) {
+		usb_log_error("Failed to get OHCI root hub address: %s\n",
+		    str_error(hub_address));
+		return hub_address;
+	}
+	instance->rh.address = hub_address;
+	usb_device_keeper_bind(
+	    &instance->manager, hub_address, hub_fun->handle);
+
+#define CHECK_RET_RELEASE(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	hc_remove_endpoint(instance, hub_address, 0, USB_DIRECTION_BOTH); \
+	usb_device_keeper_release(&instance->manager, hub_address); \
+	return ret; \
+} else (void)0
+
+	int ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL,
+	    USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0);
+	CHECK_RET_RELEASE(ret,
+	    "Failed to add OHCI root hub endpoint 0: %s.\n", str_error(ret));
+
+	ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100);
+	CHECK_RET_RELEASE(ret,
+	    "Failed to add root hub match-id: %s.\n", str_error(ret));
+
+	ret = ddf_fun_bind(hub_fun);
+	CHECK_RET_RELEASE(ret,
+	    "Failed to bind root hub function: %s.\n", str_error(ret));
+
+	return EOK;
+#undef CHECK_RET_RELEASE
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize OHCI hc driver structure
+ *
+ * @param[in] instance Memory place for the structure.
+ * @param[in] regs Address of the memory mapped I/O registers.
+ * @param[in] reg_size Size of the memory mapped area.
+ * @param[in] interrupts True if w interrupts should be used
+ * @return Error code
+ */
+int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts)
+{
+	assert(instance);
+
+#define CHECK_RET_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
+
+	int ret =
+	    pio_enable((void*)regs, reg_size, (void**)&instance->registers);
+	CHECK_RET_RETURN(ret,
+	    "Failed to gain access to device registers: %s.\n", str_error(ret));
+
+	list_initialize(&instance->pending_batches);
+	usb_device_keeper_init(&instance->manager);
+
+	ret = usb_endpoint_manager_init(&instance->ep_manager,
+	    BANDWIDTH_AVAILABLE_USB11);
+	CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
+	    str_error(ret));
+
+	ret = hc_init_memory(instance);
+	CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",
+	    str_error(ret));
+#undef CHECK_RET_RETURN
+
+	fibril_mutex_initialize(&instance->guard);
+
+	hc_gain_control(instance);
+
+	if (!interrupts) {
+		instance->interrupt_emulator =
+		    fibril_create((int(*)(void*))interrupt_emulator, instance);
+		fibril_add_ready(instance->interrupt_emulator);
+	}
+
+	rh_init(&instance->rh, instance->registers);
+	hc_start(instance);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Create and register endpoint structures.
+ *
+ * @param[in] instance OHCI driver structure.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint USB endpoint number.
+ * @param[in] speed Communication speeed of the device.
+ * @param[in] type Endpoint's transfer type.
+ * @param[in] direction Endpoint's direction.
+ * @param[in] mps Maximum packet size the endpoint accepts.
+ * @param[in] size Maximum allowed buffer size.
+ * @param[in] interval Time between transfers(interrupt transfers only).
+ * @return Error code
+ */
+int hc_add_endpoint(
+    hc_t *instance, usb_address_t address, usb_endpoint_t endpoint,
+    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
+    size_t mps, size_t size, unsigned interval)
+{
+	endpoint_t *ep =
+	    endpoint_get(address, endpoint, direction, type, speed, mps);
+	if (ep == NULL)
+		return ENOMEM;
+
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
+	if (hcd_ep == NULL) {
+		endpoint_destroy(ep);
+		return ENOMEM;
+	}
+
+	int ret =
+	    usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
+	if (ret != EOK) {
+		hcd_endpoint_clear(ep);
+		endpoint_destroy(ep);
+		return ret;
+	}
+
+	/* Enqueue hcd_ep */
+	switch (ep->transfer_type) {
+	case USB_TRANSFER_CONTROL:
+		instance->registers->control &= ~C_CLE;
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control_current = 0;
+		instance->registers->control |= C_CLE;
+		break;
+	case USB_TRANSFER_BULK:
+		instance->registers->control &= ~C_BLE;
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control |= C_BLE;
+		break;
+	case USB_TRANSFER_ISOCHRONOUS:
+	case USB_TRANSFER_INTERRUPT:
+		instance->registers->control &= (~C_PLE & ~C_IE);
+		endpoint_list_add_ep(
+		    &instance->lists[ep->transfer_type], hcd_ep);
+		instance->registers->control |= C_PLE | C_IE;
+		break;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Dequeue and delete endpoint structures
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint USB endpoint number.
+ * @param[in] direction Direction of the endpoint.
+ * @return Error code
+ */
+int hc_remove_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
+	    address, endpoint, direction, NULL);
+	if (ep == NULL) {
+		usb_log_error("Endpoint unregister failed: No such EP.\n");
+		fibril_mutex_unlock(&instance->guard);
+		return ENOENT;
+	}
+
+	hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep);
+	if (hcd_ep) {
+		/* Dequeue hcd_ep */
+		switch (ep->transfer_type) {
+		case USB_TRANSFER_CONTROL:
+			instance->registers->control &= ~C_CLE;
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control_current = 0;
+			instance->registers->control |= C_CLE;
+			break;
+		case USB_TRANSFER_BULK:
+			instance->registers->control &= ~C_BLE;
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control |= C_BLE;
+			break;
+		case USB_TRANSFER_ISOCHRONOUS:
+		case USB_TRANSFER_INTERRUPT:
+			instance->registers->control &= (~C_PLE & ~C_IE);
+			endpoint_list_remove_ep(
+			    &instance->lists[ep->transfer_type], hcd_ep);
+			instance->registers->control |= C_PLE | C_IE;
+			break;
+		default:
+			break;
+		}
+		hcd_endpoint_clear(ep);
+	} else {
+		usb_log_warning("Endpoint without hcd equivalent structure.\n");
+	}
+	int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager,
+	    address, endpoint, direction);
+	fibril_mutex_unlock(&instance->guard);
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Get access to endpoint structures
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint USB endpoint number.
+ * @param[in] direction Direction of the endpoint.
+ * @param[out] bw Reserved bandwidth.
+ * @return Error code
+ */
+endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager,
+	    address, endpoint, direction, bw);
+	fibril_mutex_unlock(&instance->guard);
+	return ep;
+}
+/*----------------------------------------------------------------------------*/
+/** Add USB transfer to the schedule.
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @param[in] batch Batch representing the transfer.
+ * @return Error code.
+ */
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	assert(batch->ep);
+
+	/* Check for root hub communication */
+	if (batch->ep->address == instance->rh.address) {
+		rh_request(&instance->rh, batch);
+		return EOK;
+	}
+
+	fibril_mutex_lock(&instance->guard);
+	list_append(&batch->link, &instance->pending_batches);
+	batch_commit(batch);
+
+	/* Control and bulk schedules need a kick to start working */
+	switch (batch->ep->transfer_type)
+	{
+	case USB_TRANSFER_CONTROL:
+		instance->registers->command_status |= CS_CLF;
+		break;
+	case USB_TRANSFER_BULK:
+		instance->registers->command_status |= CS_BLF;
+		break;
+	default:
+		break;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Interrupt handling routine
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @param[in] status Value of the status register at the time of interrupt.
+ */
+void hc_interrupt(hc_t *instance, uint32_t status)
+{
+	assert(instance);
+	if ((status & ~I_SF) == 0) /* ignore sof status */
+		return;
+	usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
+	if (status & I_RHSC)
+		rh_interrupt(&instance->rh);
+
+	if (status & I_WDH) {
+		fibril_mutex_lock(&instance->guard);
+		usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
+		    instance->registers->hcca,
+		    (void *) addr_to_phys(instance->hcca));
+		usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
+		    instance->registers->periodic_current);
+
+		link_t *current = instance->pending_batches.head.next;
+		while (current != &instance->pending_batches.head) {
+			link_t *next = current->next;
+			usb_transfer_batch_t *batch =
+			    usb_transfer_batch_from_link(current);
+
+			if (batch_is_complete(batch)) {
+				list_remove(current);
+				usb_transfer_batch_finish(batch);
+			}
+
+			current = next;
+		}
+		fibril_mutex_unlock(&instance->guard);
+	}
+
+	if (status & I_UE) {
+		hc_start(instance);
+	}
+
+}
+/*----------------------------------------------------------------------------*/
+/** Check status register regularly
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @return Error code
+ */
+int interrupt_emulator(hc_t *instance)
+{
+	assert(instance);
+	usb_log_info("Started interrupt emulator.\n");
+	while (1) {
+		const uint32_t status = instance->registers->interrupt_status;
+		instance->registers->interrupt_status = status;
+		hc_interrupt(instance, status);
+		async_usleep(10000);
+	}
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Turn off any (BIOS)driver that might be in control of the device.
+ *
+ * This function implements routines described in chapter 5.1.1.3 of the OHCI
+ * specification (page 40, pdf page 54).
+ *
+ * @param[in] instance OHCI hc driver structure.
+ */
+void hc_gain_control(hc_t *instance)
+{
+	assert(instance);
+
+	usb_log_debug("Requesting OHCI control.\n");
+	if (instance->registers->revision & R_LEGACY_FLAG) {
+		/* Turn off legacy emulation, it should be enough to zero
+		 * the lowest bit, but it caused problems. Thus clear all
+		 * except GateA20 (causes restart on some hw).
+		 * See page 145 of the specs for details.
+		 */
+		volatile uint32_t *ohci_emulation_reg =
+		(uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
+		usb_log_debug("OHCI legacy register %p: %x.\n",
+		    ohci_emulation_reg, *ohci_emulation_reg);
+		/* Zero everything but A20State */
+		*ohci_emulation_reg &= 0x100;
+		usb_log_debug(
+		    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
+		    ohci_emulation_reg, *ohci_emulation_reg);
+	}
+
+	/* Interrupt routing enabled => smm driver is active */
+	if (instance->registers->control & C_IR) {
+		usb_log_debug("SMM driver: request ownership change.\n");
+		instance->registers->command_status |= CS_OCR;
+		/* Hope that SMM actually knows its stuff or we can hang here */
+		while (instance->registers->control & C_IR) {
+			async_usleep(1000);
+		}
+		usb_log_info("SMM driver: Ownership taken.\n");
+		C_HCFS_SET(instance->registers->control, C_HCFS_RESET);
+		async_usleep(50000);
+		return;
+	}
+
+	const unsigned hc_status = C_HCFS_GET(instance->registers->control);
+	/* Interrupt routing disabled && status != USB_RESET => BIOS active */
+	if (hc_status != C_HCFS_RESET) {
+		usb_log_debug("BIOS driver found.\n");
+		if (hc_status == C_HCFS_OPERATIONAL) {
+			usb_log_info("BIOS driver: HC operational.\n");
+			return;
+		}
+		/* HC is suspended assert resume for 20ms, */
+		C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
+		async_usleep(20000);
+		usb_log_info("BIOS driver: HC resumed.\n");
+		return;
+	}
+
+	/* HC is in reset (hw startup) => no other driver
+	 * maintain reset for at least the time specified in USB spec (50 ms)*/
+	usb_log_debug("Host controller found in reset state.\n");
+	async_usleep(50000);
+}
+/*----------------------------------------------------------------------------*/
+/** OHCI hw initialization routine.
+ *
+ * @param[in] instance OHCI hc driver structure.
+ */
+void hc_start(hc_t *instance)
+{
+	/* OHCI guide page 42 */
+	assert(instance);
+	usb_log_debug2("Started hc initialization routine.\n");
+
+	/* Save contents of fm_interval register */
+	const uint32_t fm_interval = instance->registers->fm_interval;
+	usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
+
+	/* Reset hc */
+	usb_log_debug2("HC reset.\n");
+	size_t time = 0;
+	instance->registers->command_status = CS_HCR;
+	while (instance->registers->command_status & CS_HCR) {
+		async_usleep(10);
+		time += 10;
+	}
+	usb_log_debug2("HC reset complete in %zu us.\n", time);
+
+	/* Restore fm_interval */
+	instance->registers->fm_interval = fm_interval;
+	assert((instance->registers->command_status & CS_HCR) == 0);
+
+	/* hc is now in suspend state */
+	usb_log_debug2("HC should be in suspend state(%x).\n",
+	    instance->registers->control);
+
+	/* Use HCCA */
+	instance->registers->hcca = addr_to_phys(instance->hcca);
+
+	/* Use queues */
+	instance->registers->bulk_head =
+	    instance->lists[USB_TRANSFER_BULK].list_head_pa;
+	usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
+	    instance->lists[USB_TRANSFER_BULK].list_head,
+	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
+
+	instance->registers->control_head =
+	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
+	usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
+	    instance->lists[USB_TRANSFER_CONTROL].list_head,
+	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
+
+	/* Enable queues */
+	instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
+	usb_log_debug2("All queues enabled(%x).\n",
+	    instance->registers->control);
+
+	/* Enable interrupts */
+	instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;
+	usb_log_debug2("Enabled interrupts: %x.\n",
+	    instance->registers->interrupt_enable);
+	instance->registers->interrupt_enable = I_MI;
+
+	/* Set periodic start to 90% */
+	uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
+	instance->registers->periodic_start = (frame_length / 10) * 9;
+	usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
+	    instance->registers->periodic_start,
+	    instance->registers->periodic_start, frame_length);
+
+	C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
+	usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
+	    instance->registers->control);
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize schedule queues
+ *
+ * @param[in] instance OHCI hc driver structure
+ * @return Error code
+ */
+int hc_init_transfer_lists(hc_t *instance)
+{
+	assert(instance);
+#define SETUP_ENDPOINT_LIST(type) \
+do { \
+	const char *name = usb_str_transfer_type(type); \
+	int ret = endpoint_list_init(&instance->lists[type], name); \
+	if (ret != EOK) { \
+		usb_log_error("Failed to setup %s endpoint list: %s.\n", \
+		    name, str_error(ret)); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \
+		endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \
+		return ret; \
+	} \
+} while (0)
+
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL);
+	SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK);
+#undef SETUP_ENDPOINT_LIST
+	endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT],
+	    &instance->lists[USB_TRANSFER_ISOCHRONOUS]);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize memory structures used by the OHCI hcd.
+ *
+ * @param[in] instance OHCI hc driver structure.
+ * @return Error code.
+ */
+int hc_init_memory(hc_t *instance)
+{
+	assert(instance);
+
+	bzero(&instance->rh, sizeof(instance->rh));
+	/* Init queues */
+	const int ret = hc_init_transfer_lists(instance);
+	if (ret != EOK) {
+		return ret;
+	}
+
+	/*Init HCCA */
+	instance->hcca = malloc32(sizeof(hcca_t));
+	if (instance->hcca == NULL)
+		return ENOMEM;
+	bzero(instance->hcca, sizeof(hcca_t));
+	usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
+
+	unsigned i = 0;
+	for (; i < 32; ++i) {
+		instance->hcca->int_ep[i] =
+		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
+	}
+	usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
+	    instance->lists[USB_TRANSFER_INTERRUPT].list_head,
+	    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hc.h
===================================================================
--- uspace/drv/bus/usb/ohci/hc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,114 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI host controller driver structure
+ */
+#ifndef DRV_OHCI_HC_H
+#define DRV_OHCI_HC_H
+
+#include <fibril.h>
+#include <fibril_synch.h>
+#include <adt/list.h>
+#include <ddi.h>
+
+#include <usb/usb.h>
+#include <usb/host/device_keeper.h>
+#include <usb/host/usb_endpoint_manager.h>
+#include <usbhc_iface.h>
+
+#include "batch.h"
+#include "ohci_regs.h"
+#include "root_hub.h"
+#include "endpoint_list.h"
+#include "hw_struct/hcca.h"
+
+/** Main OHCI driver structure */
+typedef struct hc {
+	/** USB bus driver, devices and addresses */
+	usb_device_keeper_t manager;
+	/** USB bus driver, endpoints */
+	usb_endpoint_manager_t ep_manager;
+
+	/** Memory mapped I/O registers area */
+	ohci_regs_t *registers;
+	/** Host controller communication area structure */
+	hcca_t *hcca;
+
+	/** Transfer schedules */
+	endpoint_list_t lists[4];
+	/** List of active transfers */
+	list_t pending_batches;
+
+	/** Fibril for periodic checks if interrupts can't be used */
+	fid_t interrupt_emulator;
+
+	/** Guards schedule and endpoint manipulation */
+	fibril_mutex_t guard;
+
+	/** USB hub emulation structure */
+	rh_t rh;
+} hc_t;
+
+size_t hc_irq_cmd_count(void);
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
+int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
+int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun);
+
+/** Safely dispose host controller internal structures
+ *
+ * @param[in] instance Host controller structure to use.
+ */
+static inline void hc_fini(hc_t *instance)
+	{ /* TODO: implement*/ };
+
+int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep,
+    usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction,
+    size_t max_packet_size, size_t size, unsigned interval);
+int hc_remove_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction);
+endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw);
+
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
+void hc_interrupt(hc_t *instance, uint32_t status);
+
+/** Get and cast pointer to the driver data
+ *
+ * @param[in] fun DDF function pointer
+ * @return cast pointer to driver_data
+ */
+static inline hc_t * fun_to_hc(ddf_fun_t *fun)
+	{ return fun->driver_data; }
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hcd_endpoint.c
===================================================================
--- uspace/drv/bus/usb/ohci/hcd_endpoint.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hcd_endpoint.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,110 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include "utils/malloc32.h"
+#include "hcd_endpoint.h"
+
+/** Callback to set toggle on ED.
+ *
+ * @param[in] hcd_ep hcd endpoint structure
+ * @param[in] toggle new value of toggle bit
+ */
+static void hcd_ep_toggle_set(void *hcd_ep, int toggle)
+{
+	hcd_endpoint_t *instance = hcd_ep;
+	assert(instance);
+	assert(instance->ed);
+	ed_toggle_set(instance->ed, toggle);
+}
+/*----------------------------------------------------------------------------*/
+/** Callback to get value of toggle bit.
+ *
+ * @param[in] hcd_ep hcd endpoint structure
+ * @return Current value of toggle bit.
+ */
+static int hcd_ep_toggle_get(void *hcd_ep)
+{
+	hcd_endpoint_t *instance = hcd_ep;
+	assert(instance);
+	assert(instance->ed);
+	return ed_toggle_get(instance->ed);
+}
+/*----------------------------------------------------------------------------*/
+/** Creates new hcd endpoint representation.
+ *
+ * @param[in] ep USBD endpoint structure
+ * @return pointer to a new hcd endpoint structure, NULL on failure.
+ */
+hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep)
+{
+	assert(ep);
+	hcd_endpoint_t *hcd_ep = malloc(sizeof(hcd_endpoint_t));
+	if (hcd_ep == NULL)
+		return NULL;
+
+	hcd_ep->ed = malloc32(sizeof(ed_t));
+	if (hcd_ep->ed == NULL) {
+		free(hcd_ep);
+		return NULL;
+	}
+
+	hcd_ep->td = malloc32(sizeof(td_t));
+	if (hcd_ep->td == NULL) {
+		free32(hcd_ep->ed);
+		free(hcd_ep);
+		return NULL;
+	}
+
+	ed_init(hcd_ep->ed, ep);
+	ed_set_td(hcd_ep->ed, hcd_ep->td);
+	endpoint_set_hc_data(ep, hcd_ep, hcd_ep_toggle_get, hcd_ep_toggle_set);
+
+	return hcd_ep;
+}
+/*----------------------------------------------------------------------------*/
+/** Disposes assigned hcd endpoint structure
+ *
+ * @param[in] ep USBD endpoint structure
+ */
+void hcd_endpoint_clear(endpoint_t *ep)
+{
+	assert(ep);
+	hcd_endpoint_t *hcd_ep = ep->hc_data.data;
+	assert(hcd_ep);
+	free32(hcd_ep->ed);
+	free32(hcd_ep->td);
+	free(hcd_ep);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hcd_endpoint.h
===================================================================
--- uspace/drv/bus/usb/ohci/hcd_endpoint.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hcd_endpoint.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,70 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HCD_ENDPOINT_H
+#define DRV_OHCI_HCD_ENDPOINT_H
+
+#include <assert.h>
+#include <adt/list.h>
+#include <usb/host/endpoint.h>
+
+#include "hw_struct/endpoint_descriptor.h"
+#include "hw_struct/transfer_descriptor.h"
+
+/** Connector structure linking ED to to prepared TD. */
+typedef struct hcd_endpoint {
+	/** OHCI endpoint descriptor */
+	ed_t *ed;
+	/** Currently enqueued transfer descriptor */
+	td_t *td;
+	/** Linked list used by driver software */
+	link_t link;
+} hcd_endpoint_t;
+
+hcd_endpoint_t * hcd_endpoint_assign(endpoint_t *ep);
+void hcd_endpoint_clear(endpoint_t *ep);
+
+/** Get and convert assigned hcd_endpoint_t structure
+ * @param[in] ep USBD endpoint structure.
+ * @return Pointer to assigned hcd endpoint structure
+ */
+static inline hcd_endpoint_t * hcd_endpoint_get(endpoint_t *ep)
+{
+	assert(ep);
+	return ep->hc_data.data;
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hw_struct/completion_codes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,91 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H
+#define DRV_OHCI_HW_STRUCT_COMPLETION_CODES_H
+
+#include <errno.h>
+
+#define CC_NOERROR (0x0)
+#define CC_CRC (0x1)
+#define CC_BITSTUFF (0x2)
+#define CC_TOGGLE (0x3)
+#define CC_STALL (0x4)
+#define CC_NORESPONSE (0x5)
+#define CC_PIDFAIL (0x6)
+#define CC_PIDUNEXPECTED (0x7)
+#define CC_DATAOVERRRUN (0x8)
+#define CC_DATAUNDERRRUN (0x9)
+#define CC_BUFFEROVERRRUN (0xc)
+#define CC_BUFFERUNDERRUN (0xd)
+#define CC_NOACCESS1 (0xe)
+#define CC_NOACCESS2 (0xf)
+
+inline static int cc_to_rc(int cc)
+{
+	switch (cc) {
+	case CC_NOERROR:
+		return EOK;
+
+	case CC_CRC:
+		return EBADCHECKSUM;
+
+	case CC_PIDUNEXPECTED:
+	case CC_PIDFAIL:
+	case CC_BITSTUFF:
+		return EIO;
+
+	case CC_TOGGLE:
+	case CC_STALL:
+		return ESTALL;
+
+	case CC_NORESPONSE:
+		return ETIMEOUT;
+
+	case CC_DATAOVERRRUN:
+	case CC_DATAUNDERRRUN:
+	case CC_BUFFEROVERRRUN:
+	case CC_BUFFERUNDERRUN:
+		return EOVERFLOW;
+
+	case CC_NOACCESS1:
+	case CC_NOACCESS2:
+	default:
+		return ENOTSUP;
+	}
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,66 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include "endpoint_descriptor.h"
+
+static unsigned direc[3] =
+    { ED_STATUS_D_IN, ED_STATUS_D_OUT, ED_STATUS_D_TRANSFER };
+
+void ed_init(ed_t *instance, endpoint_t *ep)
+{
+	assert(instance);
+	bzero(instance, sizeof(ed_t));
+	if (ep == NULL) {
+		instance->status = ED_STATUS_K_FLAG;
+		return;
+	}
+	assert(ep);
+	instance->status = 0
+	    | ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
+	    | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)
+	    | ((direc[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)
+	    | ((ep->max_packet_size & ED_STATUS_MPS_MASK)
+	        << ED_STATUS_MPS_SHIFT);
+
+
+	if (ep->speed == USB_SPEED_LOW)
+		instance->status |= ED_STATUS_S_FLAG;
+	if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
+		instance->status |= ED_STATUS_F_FLAG;
+
+	if (ep->toggle)
+		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,131 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
+#define DRV_OHCI_HW_STRUCT_ENDPOINT_DESCRIPTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <usb/host/endpoint.h>
+
+#include "../utils/malloc32.h"
+#include "transfer_descriptor.h"
+
+#include "completion_codes.h"
+
+typedef struct ed {
+	volatile uint32_t status;
+#define ED_STATUS_FA_MASK (0x7f)   /* USB device address   */
+#define ED_STATUS_FA_SHIFT (0)
+#define ED_STATUS_EN_MASK (0xf)    /* USB endpoint address */
+#define ED_STATUS_EN_SHIFT (7)
+#define ED_STATUS_D_MASK (0x3)     /* direction */
+#define ED_STATUS_D_SHIFT (11)
+#define ED_STATUS_D_OUT (0x1)
+#define ED_STATUS_D_IN (0x2)
+#define ED_STATUS_D_TRANSFER (0x3)
+
+#define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */
+#define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */
+#define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/
+#define ED_STATUS_MPS_MASK (0x3ff) /* max_packet_size*/
+#define ED_STATUS_MPS_SHIFT (16)
+
+	volatile uint32_t td_tail;
+#define ED_TDTAIL_PTR_MASK (0xfffffff0)
+#define ED_TDTAIL_PTR_SHIFT (0)
+
+	volatile uint32_t td_head;
+#define ED_TDHEAD_PTR_MASK (0xfffffff0)
+#define ED_TDHEAD_PTR_SHIFT (0)
+#define ED_TDHEAD_ZERO_MASK (0x3)
+#define ED_TDHEAD_ZERO_SHIFT (2)
+#define ED_TDHEAD_TOGGLE_CARRY (0x2)
+#define ED_TDHEAD_HALTED_FLAG (0x1)
+
+	volatile uint32_t next;
+#define ED_NEXT_PTR_MASK (0xfffffff0)
+#define ED_NEXT_PTR_SHIFT (0)
+} __attribute__((packed)) ed_t;
+
+void ed_init(ed_t *instance, endpoint_t *ep);
+
+static inline void ed_set_td(ed_t *instance, td_t *td)
+{
+	assert(instance);
+	uintptr_t pa = addr_to_phys(td);
+	instance->td_head =
+	    ((pa & ED_TDHEAD_PTR_MASK)
+	    | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
+	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+}
+
+static inline void ed_set_end_td(ed_t *instance, td_t *td)
+{
+	assert(instance);
+	uintptr_t pa = addr_to_phys(td);
+	instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
+}
+
+static inline void ed_append_ed(ed_t *instance, ed_t *next)
+{
+	assert(instance);
+	assert(next);
+	uint32_t pa = addr_to_phys(next);
+	assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);
+	instance->next = pa;
+}
+
+static inline int ed_toggle_get(ed_t *instance)
+{
+	assert(instance);
+	return (instance->td_head & ED_TDHEAD_TOGGLE_CARRY) ? 1 : 0;
+}
+
+static inline void ed_toggle_set(ed_t *instance, int toggle)
+{
+	assert(instance);
+	assert(toggle == 0 || toggle == 1);
+	if (toggle == 1) {
+		instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
+	} else {
+		/* clear halted flag when reseting toggle */
+		instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
+		instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
+	}
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/hw_struct/hcca.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hw_struct/hcca.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_HCCA_H
+#define DRV_OHCI_HW_STRUCT_HCCA_H
+
+#include <stdint.h>
+
+/** Host controller communication area.
+ * Shared memory used for communication between the controller and the driver.
+ */
+typedef struct hcca {
+	uint32_t int_ep[32];
+	uint16_t frame_number;
+	uint16_t pad1;
+	uint32_t done_head;
+	uint32_t reserved[29];
+} __attribute__((packed, aligned)) hcca_t;
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hw_struct/iso_transfer_descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,75 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H
+#define DRV_OHCI_HW_STRUCT_ISO_TRANSFER_DESCRIPTOR_H
+
+#include <stdint.h>
+
+#include "completion_codes.h"
+
+typedef struct itd {
+	volatile uint32_t status;
+#define ITD_STATUS_SF_MASK (0xffff) /* starting frame */
+#define ITD_STATUS_SF_SHIFT (0)
+#define ITD_STATUS_DI_MASK (0x7) /* delay int, wait DI frames before int */
+#define ITD_STATUS_DI_SHIFT (21)
+#define ITD_STATUS_DI_NO_INTERRUPT (0x7)
+#define ITD_STATUS_FC_MASK (0x7) /* frame count */
+#define ITD_STATUS_FC_SHIFT (24)
+#define ITD_STATUS_CC_MASK (0xf) /* condition code */
+#define ITD_STATUS_CC_SHIFT (28)
+
+	volatile uint32_t page;   /* page number of the first byte in buffer */
+#define ITD_PAGE_BP0_MASK (0xfffff000)
+#define ITD_PAGE_BP0_SHIFT (0)
+
+	volatile uint32_t next;
+#define ITD_NEXT_PTR_MASK (0xfffffff0)
+#define ITD_NEXT_PTR_SHIFT (0)
+
+	volatile uint32_t be; /* buffer end, address of the last byte */
+
+	volatile uint16_t offset[8];
+#define ITD_OFFSET_SIZE_MASK (0x3ff)
+#define ITD_OFFSET_SIZE_SHIFT (0)
+#define ITD_OFFSET_CC_MASK (0xf)
+#define ITD_OFFSET_CC_SHIFT (12)
+
+} __attribute__((packed)) itd_t;
+#endif
+/**
+ * @}
+ */
+
+
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,64 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include <usb/usb.h>
+#include "transfer_descriptor.h"
+
+static unsigned dp[3] =
+    { TD_STATUS_DP_IN, TD_STATUS_DP_OUT, TD_STATUS_DP_SETUP };
+static unsigned togg[2] = { TD_STATUS_T_0, TD_STATUS_T_1 };
+
+void td_init(
+    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle)
+{
+	assert(instance);
+	bzero(instance, sizeof(td_t));
+	instance->status = 0
+	    | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
+	    | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
+	if (toggle == 0 || toggle == 1) {
+		instance->status |= togg[toggle] << TD_STATUS_T_SHIFT;
+	}
+	if (dir == USB_DIRECTION_IN) {
+		instance->status |= TD_STATUS_ROUND_FLAG;
+	}
+	if (buffer != NULL) {
+		assert(size != 0);
+		instance->cbp = addr_to_phys(buffer);
+		instance->be = addr_to_phys(buffer + size - 1);
+	}
+}
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,118 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
+#define DRV_OHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
+
+#include <bool.h>
+#include <stdint.h>
+#include "../utils/malloc32.h"
+
+#include "completion_codes.h"
+
+/* OHCI TDs can handle up to 8KB buffers, however, it can use max 2 pages.
+ * Using 4KB buffers guarantees the page count condition.
+ * (OHCI assumes 4KB pages) */
+#define OHCI_TD_MAX_TRANSFER (4 * 1024)
+
+typedef struct td {
+	volatile uint32_t status;
+#define TD_STATUS_ROUND_FLAG (1 << 18)
+#define TD_STATUS_DP_MASK (0x3) /* direction/PID */
+#define TD_STATUS_DP_SHIFT (19)
+#define TD_STATUS_DP_SETUP (0x0)
+#define TD_STATUS_DP_OUT (0x1)
+#define TD_STATUS_DP_IN (0x2)
+#define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */
+#define TD_STATUS_DI_SHIFT (21)
+#define TD_STATUS_DI_NO_INTERRUPT (0x7)
+#define TD_STATUS_T_MASK (0x3)  /* data toggle 1x = use ED toggle carry */
+#define TD_STATUS_T_SHIFT (24)
+#define TD_STATUS_T_0 (0x2)
+#define TD_STATUS_T_1 (0x3)
+#define TD_STATUS_T_ED (0)
+#define TD_STATUS_EC_MASK (0x3) /* error count */
+#define TD_STATUS_EC_SHIFT (26)
+#define TD_STATUS_CC_MASK (0xf) /* condition code */
+#define TD_STATUS_CC_SHIFT (28)
+
+	volatile uint32_t cbp; /* current buffer ptr, data to be transfered */
+	volatile uint32_t next;
+#define TD_NEXT_PTR_MASK (0xfffffff0)
+#define TD_NEXT_PTR_SHIFT (0)
+
+	volatile uint32_t be; /* buffer end, address of the last byte */
+} __attribute__((packed)) td_t;
+
+void td_init(
+    td_t *instance, usb_direction_t dir, void *buffer, size_t size, int toggle);
+
+inline static void td_set_next(td_t *instance, td_t *next)
+{
+	assert(instance);
+	instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
+}
+
+inline static bool td_is_finished(td_t *instance)
+{
+	assert(instance);
+	int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
+	/* something went wrong, error code is set */
+	if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
+		return true;
+	}
+	/* everything done */
+	if (cc == CC_NOERROR && instance->cbp == 0) {
+		return true;
+	}
+	return false;
+}
+
+static inline int td_error(td_t *instance)
+{
+	assert(instance);
+	int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
+	return cc_to_rc(cc);
+}
+
+static inline size_t td_remain_size(td_t *instance)
+{
+	assert(instance);
+	if (instance->cbp == 0)
+		return 0;
+	return instance->be - instance->cbp + 1;
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/iface.c
===================================================================
--- uspace/drv/bus/usb/ohci/iface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/iface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver hc interface implementation
+ */
+#include <ddf/driver.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+#include <usb/host/endpoint.h>
+
+#include "iface.h"
+#include "hc.h"
+
+static inline int setup_batch(
+    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
+    void *data, size_t size, void * setup_data, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t in,
+    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
+    hc_t **hc, usb_transfer_batch_t **batch)
+{
+	assert(hc);
+	assert(batch);
+	assert(fun);
+	*hc = fun_to_hc(fun);
+	assert(*hc);
+
+	size_t res_bw;
+	endpoint_t *ep = hc_get_endpoint(*hc,
+	    target.address, target.endpoint, direction, &res_bw);
+	if (ep == NULL) {
+		usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
+		    target.address, target.endpoint, name);
+		return ENOENT;
+	}
+
+	usb_log_debug("%s %d:%d %zu(%zu).\n",
+	    name, target.address, target.endpoint, size, ep->max_packet_size);
+
+	const size_t bw = bandwidth_count_usb11(
+	    ep->speed, ep->transfer_type, size, ep->max_packet_size);
+	if (res_bw < bw) {
+		usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
+		    "but only %zu is reserved.\n",
+		    target.address, target.endpoint, name, bw, res_bw);
+		return ENOSPC;
+	}
+
+	*batch = batch_get(
+	    fun, ep, data, size, setup_data, setup_size, in, out, arg);
+	if (!*batch)
+		return ENOMEM;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Request address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] speed Speed to associate with the new default address.
+ * @param[out] address Place to write a new address.
+ * @return Error code.
+ */
+static int request_address(
+    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	assert(address);
+
+	usb_log_debug("Address request with speed %d.\n", speed);
+	*address = device_keeper_get_free_address(&hc->manager, speed);
+	usb_log_debug("Address request with result: %d.\n", *address);
+	if (*address <= 0)
+		return *address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Bind address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address of the device
+ * @param[in] handle Devman handle of the device driver.
+ * @return Error code.
+ */
+static int bind_address(
+  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
+	usb_device_keeper_bind(&hc->manager, address, handle);
+	return EOK;
+}
+
+
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	bool found =
+	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
+	return found ? EOK : ENOENT;
+}
+
+/*----------------------------------------------------------------------------*/
+/** Release address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address release %d.\n", address);
+	usb_device_keeper_release(&hc->manager, address);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Register endpoint for bandwidth reservation.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] ep_speed Endpoint speed (invalid means to use device one).
+ * @param[in] endpoint Endpoint number.
+ * @param[in] transfer_type USB transfer type.
+ * @param[in] direction Endpoint data direction.
+ * @param[in] max_packet_size Max packet size of the endpoint.
+ * @param[in] interval Polling interval.
+ * @return Error code.
+ */
+static int register_endpoint(ddf_fun_t *fun,
+    usb_address_t address, usb_speed_t ep_speed, usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+
+	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
+	if (speed >= USB_SPEED_MAX) {
+		speed = ep_speed;
+	}
+	const size_t size = max_packet_size;
+
+	usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
+	    address, endpoint, usb_str_transfer_type(transfer_type),
+	    usb_str_speed(speed), direction, size, max_packet_size, interval);
+
+	return hc_add_endpoint(hc, address, endpoint, speed, transfer_type,
+	    direction, max_packet_size, size, interval);
+}
+/*----------------------------------------------------------------------------*/
+static int unregister_endpoint(
+    ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Unregister endpoint %d:%d %d.\n",
+	    address, endpoint, direction);
+	return hc_remove_endpoint(hc, address, endpoint, direction);
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule interrupt out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_out(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
+	    NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_interrupt_out(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule interrupt in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_in(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
+	    NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_interrupt_in(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule bulk out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_out(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
+	    NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_bulk_out(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule bulk in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_in(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
+	    NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_bulk_in(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule control write transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Data buffer (in USB endianess, allocated and
+ *	deallocated by the caller).
+ * @param[in] size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_write(
+    ddf_fun_t *fun, usb_target_t target,
+    void *setup_data, size_t setup_size, void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
+	    setup_data, setup_size, NULL, callback, arg, "Control WRITE",
+	    &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
+	batch_control_write(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule control read transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_read(
+    ddf_fun_t *fun, usb_target_t target,
+    void *setup_data, size_t setup_size, void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
+	    setup_data, setup_size, callback, NULL, arg, "Control READ",
+	    &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	batch_control_read(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+usbhc_iface_t hc_iface = {
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.find_by_address = find_by_address,
+	.release_address = release_address,
+
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.bulk_out = bulk_out,
+	.bulk_in = bulk_in,
+
+	.control_write = control_write,
+	.control_read = control_read,
+};
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/iface.h
===================================================================
--- uspace/drv/bus/usb/ohci/iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 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 drvusbohci
+ * @{
+ */
+/** @file
+ * Common OHCI definitions.
+ */
+#ifndef DRV_OHCI_IFACE_H
+#define DRV_OHCI_IFACE_H
+
+#include <usbhc_iface.h>
+
+extern usbhc_iface_t hc_iface;
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/main.c
===================================================================
--- uspace/drv/bus/usb/ohci/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * Copyright (c) 2011 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 drvusbohci
+ * @{
+ */
+/** @file
+ * Main routines of OHCI driver.
+ */
+#include <ddf/driver.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/debug.h>
+
+#include "ohci.h"
+
+#define NAME "ohci"
+
+/** Initializes a new ddf driver instance of OHCI hcd.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int ohci_add_device(ddf_dev_t *device)
+{
+	usb_log_debug("ohci_add_device() called\n");
+	assert(device);
+
+	int ret = device_setup_ohci(device);
+	if (ret != EOK) {
+		usb_log_error("Failed to initialize OHCI driver: %s.\n",
+		    str_error(ret));
+		return ret;
+	}
+	usb_log_info("Controlling new OHCI device '%s'.\n", device->name);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static driver_ops_t ohci_driver_ops = {
+	.add_device = ohci_add_device,
+};
+/*----------------------------------------------------------------------------*/
+static driver_t ohci_driver = {
+	.name = NAME,
+	.driver_ops = &ohci_driver_ops
+};
+/*----------------------------------------------------------------------------*/
+/** Initializes global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	return ddf_driver_main(&ohci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,258 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/interrupt.h>
+#include <usb_iface.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "ohci.h"
+#include "iface.h"
+#include "pci.h"
+#include "hc.h"
+#include "root_hub.h"
+
+typedef struct ohci {
+	ddf_fun_t *hc_fun;
+	ddf_fun_t *rh_fun;
+
+	hc_t hc;
+	rh_t rh;
+} ohci_t;
+
+static inline ohci_t * dev_to_ohci(ddf_dev_t *dev)
+{
+	assert(dev);
+	return dev->driver_data;
+}
+/** IRQ handling callback, identifies device
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
+static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	assert(dev);
+
+	ohci_t *ohci = dev_to_ohci(dev);
+	if (!ohci) {
+		usb_log_warning("Interrupt on device that is not ready.\n");
+		return;
+	}
+	const uint16_t status = IPC_GET_ARG1(*call);
+	hc_interrupt(&ohci->hc, status);
+}
+/*----------------------------------------------------------------------------*/
+/** Get address of the device identified by handle.
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call that represents interrupt.
+ */
+static int usb_iface_get_address(
+    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
+{
+	assert(fun);
+	usb_device_keeper_t *manager = &dev_to_ohci(fun->dev)->hc.manager;
+
+	usb_address_t addr = usb_device_keeper_find(manager, handle);
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Gets handle of the respective hc (this device, hc function).
+ *
+ * @param[in] root_hub_fun Root hub function seeking hc handle.
+ * @param[out] handle Place to write the handle.
+ * @return Error code.
+ */
+static int usb_iface_get_hc_handle(
+    ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+	ddf_fun_t *hc_fun = dev_to_ohci(fun->dev)->hc_fun;
+	assert(hc_fun);
+
+	if (handle != NULL)
+		*handle = hc_fun->handle;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Root hub USB interface */
+static usb_iface_t usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle,
+	.get_address = usb_iface_get_address
+};
+/*----------------------------------------------------------------------------*/
+/** Standard USB HC options (HC interface) */
+static ddf_dev_ops_t hc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
+};
+/*----------------------------------------------------------------------------*/
+/** Standard USB RH options (RH interface) */
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface,
+};
+/*----------------------------------------------------------------------------*/
+/** Initialize hc and rh ddf structures and their respective drivers.
+ *
+ * @param[in] device DDF instance of the device to use.
+ * @param[in] instance OHCI structure to use.
+ *
+ * This function does all the preparatory work for hc and rh drivers:
+ *  - gets device hw resources
+ *  - disables OHCI legacy support
+ *  - asks for interrupt
+ *  - registers interrupt handler
+ */
+int device_setup_ohci(ddf_dev_t *device)
+{
+	ohci_t *instance = malloc(sizeof(ohci_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate OHCI driver.\n");
+		return ENOMEM;
+	}
+
+#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+if (ret != EOK) { \
+	if (instance->hc_fun) { \
+		instance->hc_fun->ops = NULL; \
+		instance->hc_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->hc_fun); \
+	} \
+	if (instance->rh_fun) { \
+		instance->rh_fun->ops = NULL; \
+		instance->rh_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->rh_fun); \
+	} \
+	free(instance); \
+	device->driver_data = NULL; \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
+
+	instance->rh_fun = NULL;
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc");
+	int ret = instance->hc_fun ? EOK : ENOMEM;
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to create OHCI HC function: %s.\n", str_error(ret));
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh");
+	ret = instance->rh_fun ? EOK : ENOMEM;
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to create OHCI RH function: %s.\n", str_error(ret));
+	instance->rh_fun->ops = &rh_ops;
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
+	int irq = 0;
+
+	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to get memory addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
+	    (void *) reg_base, reg_size, irq);
+
+	const size_t cmd_count = hc_irq_cmd_count();
+	irq_cmd_t irq_cmds[cmd_count];
+	ret =
+	    hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to generate IRQ commands: %s.\n", str_error(ret));
+
+	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
+
+	/* Register handler to avoid interrupt lockup */
+	ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to register interrupt handler: %s.\n", str_error(ret));
+
+	/* Try to enable interrupts */
+	bool interrupts = false;
+	ret = pci_enable_interrupts(device);
+	if (ret != EOK) {
+		usb_log_warning("Failed to enable interrupts: %s."
+		    " Falling back to polling\n", str_error(ret));
+		/* We don't need that handler */
+		unregister_interrupt_handler(device, irq);
+	} else {
+		usb_log_debug("Hw interrupts enabled.\n");
+		interrupts = true;
+	}
+
+	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to init ohci_hcd: %s.\n", str_error(ret));
+
+	device->driver_data = instance;
+
+#define CHECK_RET_FINI_RETURN(ret, message...) \
+if (ret != EOK) { \
+	unregister_interrupt_handler(device, irq); \
+	hc_fini(&instance->hc); \
+	CHECK_RET_DEST_FREE_RETURN(ret, message); \
+} else (void)0
+
+
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to bind OHCI device function: %s.\n", str_error(ret));
+
+	ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
+
+	hc_register_hub(&instance->hc, instance->rh_fun);
+	return EOK;
+
+#undef CHECK_RET_DEST_FUN_RETURN
+#undef CHECK_RET_FINI_RETURN
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/ohci.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/ohci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver main structure for both host controller and root-hub.
+ */
+#ifndef DRV_OHCI_OHCI_H
+#define DRV_OHCI_OHCI_H
+#include <ddi.h>
+#include <ddf/driver.h>
+
+int device_setup_ohci(ddf_dev_t *device);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/ohci.ma
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/ohci.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,15 @@
+10 pci/ven=106b&dev=0026
+10 pci/ven=106b&dev=003f
+10 pci/ven=10de&dev=0aa5
+
+10 pci/ven=1002&dev=4374
+10 pci/ven=1002&dev=4375
+
+10 pci/ven=1002&dev=4387
+10 pci/ven=1002&dev=4388
+10 pci/ven=1002&dev=4389
+10 pci/ven=1002&dev=438a
+10 pci/ven=1002&dev=438b
+10 pci/ven=1002&dev=4397
+10 pci/ven=1002&dev=4398
+10 pci/ven=1002&dev=4399
Index: uspace/drv/bus/usb/ohci/ohci_regs.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_regs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/ohci_regs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,234 @@
+/*
+ * 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 drvusbohcihc
+ * @{
+ */
+/** @file
+ * @brief OHCI host controller register structure
+ */
+#ifndef DRV_OHCI_OHCI_REGS_H
+#define DRV_OHCI_OHCI_REGS_H
+#include <sys/types.h>
+
+#define LEGACY_REGS_OFFSET 0x100
+
+/** OHCI memory mapped registers structure */
+typedef struct ohci_regs {
+	const ioport32_t revision;
+#define R_REVISION_MASK (0x3f)
+#define R_REVISION_SHIFT (0)
+#define R_LEGACY_FLAG   (0x80)
+
+	ioport32_t control;
+#define C_CBSR_MASK (0x3) /* Control-bulk service ratio */
+#define C_CBSR_1_1  (0x0)
+#define C_CBSR_1_2  (0x1)
+#define C_CBSR_1_3  (0x2)
+#define C_CBSR_1_4  (0x3)
+#define C_CBSR_SHIFT (0)
+
+#define C_PLE (1 << 2)   /* Periodic list enable */
+#define C_IE  (1 << 3)   /* Isochronous enable */
+#define C_CLE (1 << 4)   /* Control list enable */
+#define C_BLE (1 << 5)   /* Bulk list enable */
+
+#define C_HCFS_MASK        (0x3) /* Host controller functional state */
+#define C_HCFS_RESET       (0x0)
+#define C_HCFS_RESUME      (0x1)
+#define C_HCFS_OPERATIONAL (0x2)
+#define C_HCFS_SUSPEND     (0x3)
+#define C_HCFS_SHIFT       (6)
+
+#define C_HCFS_GET(reg) \
+	((reg >> C_HCFS_SHIFT) & C_HCFS_MASK)
+#define C_HCFS_SET(reg, hcfs_state) \
+do { \
+	reg = (reg & ~(C_HCFS_MASK << C_HCFS_SHIFT)) \
+	    | ((hcfs_state & C_HCFS_MASK) << C_HCFS_SHIFT); \
+} while (0)
+
+
+#define C_IR  (1 << 8)   /* Interrupt routing, make sure it's 0 */
+#define C_RWC (1 << 9)   /* Remote wakeup connected, host specific */
+#define C_RWE (1 << 10)  /* Remote wakeup enable */
+
+	ioport32_t command_status;
+#define CS_HCR (1 << 0)   /* Host controller reset */
+#define CS_CLF (1 << 1)   /* Control list filled */
+#define CS_BLF (1 << 2)   /* Bulk list filled */
+#define CS_OCR (1 << 3)   /* Ownership change request */
+#define CS_SOC_MASK (0x3) /* Scheduling overrun count */
+#define CS_SOC_SHIFT (16)
+
+	/** Interupt enable/disable/status,
+	 * reads give the same value,
+	 * writing causes enable/disable,
+	 * status is write-clean (writing 1 clears the bit*/
+	ioport32_t interrupt_status;
+	ioport32_t interrupt_enable;
+	ioport32_t interrupt_disable;
+#define I_SO   (1 << 0)   /* Scheduling overrun */
+#define I_WDH  (1 << 1)   /* Done head write-back */
+#define I_SF   (1 << 2)   /* Start of frame */
+#define I_RD   (1 << 3)   /* Resume detect */
+#define I_UE   (1 << 4)   /* Unrecoverable error */
+#define I_FNO  (1 << 5)   /* Frame number overflow */
+#define I_RHSC (1 << 6)   /* Root hub status change */
+#define I_OC   (1 << 30)  /* Ownership change */
+#define I_MI   (1 << 31)  /* Master interrupt (all/any interrupts) */
+
+	/** HCCA pointer (see hw_struct hcca.h) */
+	ioport32_t hcca;
+#define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
+
+	/** Currently executed periodic endpoint */
+	const ioport32_t periodic_current;
+
+	/** The first control endpoint */
+	ioport32_t control_head;
+
+	/** Currently executed control endpoint */
+	ioport32_t control_current;
+
+	/** The first bulk endpoint */
+	ioport32_t bulk_head;
+
+	/** Currently executed bulk endpoint */
+	ioport32_t bulk_current;
+
+	/** Done TD list, this value is periodically written to HCCA */
+	const ioport32_t done_head;
+
+	/** Frame time and max packet size for all transfers */
+	ioport32_t fm_interval;
+#define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/
+#define FMI_FI_SHIFT (0)
+#define FMI_FSMPS_MASK (0x7fff) /* Full speed max packet size */
+#define FMI_FSMPS_SHIFT (16)
+#define FMI_TOGGLE_FLAG (1 << 31)
+
+	/** Bit times remaining in current frame */
+	const ioport32_t fm_remaining;
+#define FMR_FR_MASK FMI_FI_MASK
+#define FMR_FR_SHIFT FMI_FI_SHIFT
+#define FMR_TOGGLE_FLAG FMI_TOGGLE_FLAG
+
+	/** Frame number */
+	const ioport32_t fm_number;
+#define FMN_NUMBER_MASK (0xffff)
+
+	/** Remaining bit time in frame to start periodic transfers */
+	ioport32_t periodic_start;
+#define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
+
+	/** Threshold for starting LS transaction */
+	ioport32_t ls_threshold;
+#define LST_LST_MASK (0x7fff)
+
+	/** The first root hub control register */
+	ioport32_t rh_desc_a;
+#define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
+#define RHDA_NDS_SHIFT (0)
+#define RHDA_PSM_FLAG  (1 << 8)  /* Power switching mode: 0-global, 1-per port*/
+#define RHDA_NPS_FLAG  (1 << 9)  /* No power switch: 1-power on, 0-use PSM*/
+#define RHDA_DT_FLAG   (1 << 10) /* 1-Compound device, must be 0 */
+#define RHDA_OCPM_FLAG (1 << 11) /* Over-current mode: 0-global, 1-per port */
+#define RHDA_NOCP_FLAG (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
+#define RHDA_POTPGT_MASK (0xff)  /* Power on to power good time */
+#define RHDA_POTPGT_SHIFT (24)
+
+	/** The other root hub control register */
+	ioport32_t rh_desc_b;
+#define RHDB_DR_MASK (0xffff) /* Device removable mask */
+#define RHDB_DR_SHIFT (0)
+#define RHDB_PCC_MASK (0xffff) /* Power control mask */
+#define RHDB_PCC_SHIFT (16)
+
+/* Port device removable status */
+#define RHDB_DR_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
+/* Port power control status: 1-per port power control, 0-global power switch */
+#define RHDB_PPC_FLAG(port) (((1 << port) & RHDB_DR_MASK) << RHDB_DR_SHIFT)
+
+	/** Root hub status register */
+	ioport32_t rh_status;
+#define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
+                                * write: 0-no effect,
+                                *        1-turn off port power for ports
+                                *        specified in PPCM(RHDB), or all ports,
+                                *        if power is set globally */
+#define RHS_CLEAR_GLOBAL_POWER RHS_LPS_FLAG /* synonym for the above */
+#define RHS_OCI_FLAG  (1 <<  1)/* Over-current indicator, if per-port: 0 */
+#define RHS_DRWE_FLAG (1 << 15)/* read: 0-connect status change does not wake HC
+                                *       1-connect status change wakes HC
+                                * write: 1-set DRWE, 0-no effect */
+#define RHS_SET_DRWE RHS_DRWE_FLAG
+#define RHS_LPSC_FLAG (1 << 16)/* read: 0,
+                                * write: 0-no effect
+                                *        1-turn on port power for ports
+                                *        specified in PPCM(RHDB), or all ports,
+                                *        if power is set globally */
+#define RHS_SET_GLOBAL_POWER RHS_LPSC_FLAG /* synonym for the above */
+#define RHS_OCIC_FLAG (1 << 17)/* Over-current indicator change   */
+#define RHS_CLEAR_DRWE (1 << 31)
+
+	/** Root hub per port status */
+	ioport32_t rh_port_status[];
+#define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
+                                * w: 1-clear port enable, 0-nothing */
+#define RHPS_CLEAR_PORT_ENABLE RHPS_CCS_FLAG
+#define RHPS_PES_FLAG (1 << 1) /* r: port enable status
+                                * w: 1-set port enable, 0-nothing */
+#define RHPS_SET_PORT_ENABLE RHPS_PES_FLAG
+#define RHPS_PSS_FLAG (1 << 2) /* r: port suspend status
+                                * w: 1-set port suspend, 0-nothing */
+#define RHPS_SET_PORT_SUSPEND RHPS_PSS_FLAG
+#define RHPS_POCI_FLAG (1 << 3) /* r: port over-current (if reports are per-port
+                                 * w: 1-clear port suspend (start resume
+                                 *      if suspened)
+                                 *    0-nothing */
+#define RHPS_CLEAR_PORT_SUSPEND RHPS_POCI_FLAG
+#define RHPS_PRS_FLAG (1 << 4) /* r: port reset status
+                                * w: 1-set port reset, 0-nothing */
+#define RHPS_SET_PORT_RESET RHPS_PRS_FLAG
+#define RHPS_PPS_FLAG (1 << 8) /* r: port power status
+                                * w: 1-set port power, 0-nothing */
+#define RHPS_SET_PORT_POWER RHPS_PPS_FLAG
+#define RHPS_LSDA_FLAG (1 << 9) /* r: low speed device attached
+                                 * w: 1-clear port power, 0-nothing */
+#define RHPS_CLEAR_PORT_POWER RHPS_LSDA_FLAG
+#define RHPS_CSC_FLAG  (1 << 16) /* connect status change Write-Clean */
+#define RHPS_PESC_FLAG (1 << 17) /* port enable status change WC */
+#define RHPS_PSSC_FLAG (1 << 18) /* port suspend status change WC */
+#define RHPS_OCIC_FLAG (1 << 19) /* port over-current change WC */
+#define RHPS_PRSC_FLAG (1 << 20) /* port reset status change WC */
+#define RHPS_CHANGE_WC_MASK 0x1f0000
+} __attribute__((packed)) ohci_regs_t;
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/pci.c
===================================================================
--- uspace/drv/bus/usb/ohci/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,143 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the OHCI driver.
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include <as.h>
+#include <devman.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <device/hw_res.h>
+
+#include <usb/debug.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+/** Get address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] mem_reg_address Base address of the memory range.
+ * @param[out] mem_reg_size Size of the memory range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(ddf_dev_t *dev,
+    uintptr_t *mem_reg_address, size_t *mem_reg_size, int *irq_no)
+{
+	assert(dev);
+	assert(mem_reg_address);
+	assert(mem_reg_size);
+	assert(irq_no);
+
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	hw_resource_list_t hw_resources;
+	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (rc != EOK) {
+		async_hangup(parent_sess);
+		return rc;
+	}
+	
+	uintptr_t mem_address = 0;
+	size_t mem_size = 0;
+	bool mem_found = false;
+	
+	int irq = 0;
+	bool irq_found = false;
+	
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			irq = res->res.interrupt.irq;
+			irq_found = true;
+			usb_log_debug2("Found interrupt: %d.\n", irq);
+			break;
+		case MEM_RANGE:
+			if (res->res.mem_range.address != 0
+			    && res->res.mem_range.size != 0 ) {
+				mem_address = res->res.mem_range.address;
+				mem_size = res->res.mem_range.size;
+				usb_log_debug2("Found mem: %p %zu.\n",
+				    (void *) mem_address, mem_size);
+				mem_found = true;
+			}
+		default:
+			break;
+		}
+	}
+	
+	if (mem_found && irq_found) {
+		*mem_reg_address = mem_address;
+		*mem_reg_size = mem_size;
+		*irq_no = irq;
+		rc = EOK;
+	} else
+		rc = ENOENT;
+	
+	async_hangup(parent_sess);
+	return rc;
+}
+
+/** Call the PCI driver with a request to enable interrupts
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_enable_interrupts(ddf_dev_t *device)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	bool enabled = hw_res_enable_interrupt(parent_sess);
+	async_hangup(parent_sess);
+	
+	return enabled ? EOK : EIO;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/pci.h
===================================================================
--- uspace/drv/bus/usb/ohci/pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 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 drvusbohci
+ * @{
+ */
+/** @file
+ * PCI related functions needed by OHCI driver.
+ */
+#ifndef DRV_OHCI_PCI_H
+#define DRV_OHCI_PCI_H
+
+#include <ddf/driver.h>
+
+int pci_get_my_registers(ddf_dev_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(ddf_dev_t *);
+int pci_disable_legacy(ddf_dev_t *);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/ohci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/root_hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,747 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/debug.h>
+
+#include "root_hub.h"
+#include <usb/classes/classes.h>
+#include <usb/classes/hub.h>
+#include <usb/dev/driver.h>
+#include "ohci_regs.h"
+
+#include <usb/dev/request.h>
+#include <usb/classes/hub.h>
+
+/**
+ * standart device descriptor for ohci root hub
+ */
+static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = {
+	.configuration_count = 1,
+	.descriptor_type = USB_DESCTYPE_DEVICE,
+	.device_class = USB_CLASS_HUB,
+	.device_protocol = 0,
+	.device_subclass = 0,
+	.device_version = 0,
+	.length = sizeof(usb_standard_device_descriptor_t),
+	.max_packet_size = 64,
+	.vendor_id = 0x16db, /* HelenOS does not have USB vendor ID assigned.*/
+	.product_id = 0x0001,
+	.str_serial_number = 0,
+	.usb_spec_version = 0x110,
+};
+
+/**
+ * standart configuration descriptor with filled common values
+ * for ohci root hubs
+ */
+static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = {
+	.attributes = 1 << 7,
+	.configuration_number = 1,
+	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
+	.interface_count = 1,
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.max_power = 0, /* root hubs don't need no power */
+	.str_configuration = 0,
+};
+
+/**
+ * standart ohci root hub interface descriptor
+ */
+static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = {
+	.alternate_setting = 0,
+	.descriptor_type = USB_DESCTYPE_INTERFACE,
+	.endpoint_count = 1,
+	.interface_class = USB_CLASS_HUB,
+	.interface_number = 1,
+	.interface_protocol = 0,
+	.interface_subclass = 0,
+	.length = sizeof(usb_standard_interface_descriptor_t),
+	.str_interface = 0,
+};
+
+/**
+ * standart ohci root hub endpoint descriptor
+ */
+static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = {
+	.attributes = USB_TRANSFER_INTERRUPT,
+	.descriptor_type = USB_DESCTYPE_ENDPOINT,
+	.endpoint_address = 1 + (1 << 7),
+	.length = sizeof(usb_standard_endpoint_descriptor_t),
+	.max_packet_size = 2,
+	.poll_interval = 255,
+};
+
+static void create_serialized_hub_descriptor(rh_t *instance);
+static void rh_init_descriptors(rh_t *instance);
+static uint16_t create_interrupt_mask(rh_t *instance);
+static int get_status(rh_t *instance, usb_transfer_batch_t *request);
+static int get_descriptor(rh_t *instance, usb_transfer_batch_t *request);
+static int set_feature(rh_t *instance, usb_transfer_batch_t *request);
+static int clear_feature(rh_t *instance, usb_transfer_batch_t *request);
+static int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
+static int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
+static int control_request(rh_t *instance, usb_transfer_batch_t *request);
+static inline void interrupt_request(
+    usb_transfer_batch_t *request, uint16_t mask, size_t size)
+{
+	assert(request);
+
+	memcpy(request->data_buffer, &mask, size);
+	request->transfered_size = size;
+	usb_transfer_batch_finish_error(request, EOK);
+}
+
+#define TRANSFER_OK(bytes) \
+do { \
+	request->transfered_size = bytes; \
+	return EOK; \
+} while (0)
+
+/** Root Hub driver structure initialization.
+ *
+ * Reads info registers and prepares descriptors. Sets power mode.
+ */
+void rh_init(rh_t *instance, ohci_regs_t *regs)
+{
+	assert(instance);
+	assert(regs);
+
+	instance->registers = regs;
+	instance->port_count =
+	    (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
+	if (instance->port_count > 15) {
+		usb_log_warning("OHCI specification does not allow more than 15"
+		    " ports. Max 15 ports will be used");
+		instance->port_count = 15;
+	}
+
+	/* Don't forget the hub status bit and round up */
+	instance->interrupt_mask_size = 1 + (instance->port_count / 8);
+	instance->unfinished_interrupt_transfer = NULL;
+
+#ifdef OHCI_POWER_SWITCH_no
+	/* Set port power mode to no power-switching. (always on) */
+	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
+	/* Set to no over-current reporting */
+	instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
+#elif defined OHCI_POWER_SWITCH_ganged
+	/* Set port power mode to no ganged power-switching. */
+	instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
+	instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG;
+	instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+	/* Set to global over-current */
+	instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
+	instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;
+#else
+	/* Set port power mode to no per port power-switching. */
+	instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG;
+	instance->registers->rh_desc_a |= RHDA_PSM_FLAG;
+
+	/* Control all ports by global switch and turn them off */
+	instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
+	instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+	/* Return control to per port state */
+	instance->registers->rh_desc_b |=
+		((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
+	/* Set per port over-current */
+	instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
+	instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;
+#endif
+
+	rh_init_descriptors(instance);
+
+	usb_log_info("Root hub (%zu ports) initialized.\n",
+	    instance->port_count);
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process root hub request.
+ *
+ * @param instance Root hub instance
+ * @param request Structure containing both request and response information
+ * @return Error code
+ */
+void rh_request(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	switch (request->ep->transfer_type)
+	{
+	case USB_TRANSFER_CONTROL:
+		usb_log_debug("Root hub got CONTROL packet\n");
+		const int ret = control_request(instance, request);
+		usb_transfer_batch_finish_error(request, ret);
+		break;
+	case USB_TRANSFER_INTERRUPT:
+		usb_log_debug("Root hub got INTERRUPT packet\n");
+		const uint16_t mask = create_interrupt_mask(instance);
+		if (mask == 0) {
+			usb_log_debug("No changes..\n");
+			assert(instance->unfinished_interrupt_transfer == NULL);
+			instance->unfinished_interrupt_transfer = request;
+			break;
+		}
+		usb_log_debug("Processing changes...\n");
+		interrupt_request(request, mask, instance->interrupt_mask_size);
+		break;
+
+	default:
+		usb_log_error("Root hub got unsupported request.\n");
+		usb_transfer_batch_finish_error(request, EINVAL);
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process interrupt on a hub device.
+ *
+ * If there is no pending interrupt transfer, nothing happens.
+ * @param instance
+ */
+void rh_interrupt(rh_t *instance)
+{
+	assert(instance);
+
+	if (!instance->unfinished_interrupt_transfer)
+		return;
+
+	usb_log_debug("Finalizing interrupt transfer\n");
+	const uint16_t mask = create_interrupt_mask(instance);
+	interrupt_request(instance->unfinished_interrupt_transfer,
+	    mask, instance->interrupt_mask_size);
+
+	instance->unfinished_interrupt_transfer = NULL;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Create hub descriptor.
+ *
+ * For descriptor format see USB hub specification (chapter 11.15.2.1, pg. 263)
+ *
+ * @param instance Root hub instance
+ * @return Error code
+ */
+void create_serialized_hub_descriptor(rh_t *instance)
+{
+	assert(instance);
+
+	/* 7 bytes + 2 port bit fields (port count + global bit) */
+	const size_t size = 7 + (instance->interrupt_mask_size * 2);
+	assert(size <= HUB_DESCRIPTOR_MAX_SIZE);
+	instance->hub_descriptor_size = size;
+
+	const uint32_t hub_desc = instance->registers->rh_desc_a;
+	const uint32_t port_desc = instance->registers->rh_desc_b;
+
+	/* bDescLength */
+	instance->descriptors.hub[0] = size;
+	/* bDescriptorType */
+	instance->descriptors.hub[1] = USB_DESCTYPE_HUB;
+	/* bNmbrPorts */
+	instance->descriptors.hub[2] = instance->port_count;
+	/* wHubCharacteristics */
+	instance->descriptors.hub[3] = 0 |
+	    /* The lowest 2 bits indicate power switching mode */
+	    (((hub_desc & RHDA_PSM_FLAG)  ? 1 : 0) << 0) |
+	    (((hub_desc & RHDA_NPS_FLAG)  ? 1 : 0) << 1) |
+	    /* Bit 3 indicates device type (compound device) */
+	    (((hub_desc & RHDA_DT_FLAG)   ? 1 : 0) << 2) |
+	    /* Bits 4,5 indicate over-current protection mode */
+	    (((hub_desc & RHDA_OCPM_FLAG) ? 1 : 0) << 3) |
+	    (((hub_desc & RHDA_NOCP_FLAG) ? 1 : 0) << 4);
+
+	/* Reserved */
+	instance->descriptors.hub[4] = 0;
+	/* bPwrOn2PwrGood */
+	instance->descriptors.hub[5] =
+	    (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK;
+	/* bHubContrCurrent, root hubs don't need no power. */
+	instance->descriptors.hub[6] = 0;
+
+	/* Device Removable and some legacy 1.0 stuff*/
+	instance->descriptors.hub[7] =
+	    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff;
+	instance->descriptors.hub[8] = 0xff;
+	if (instance->interrupt_mask_size == 2) {
+		instance->descriptors.hub[8] =
+		    (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK >> 8;
+		instance->descriptors.hub[9]  = 0xff;
+		instance->descriptors.hub[10] = 0xff;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize hub descriptors.
+ *
+ * A full configuration descriptor is assembled. The configuration and endpoint
+ * descriptors have local modifications.
+ * @param instance Root hub instance
+ * @return Error code
+ */
+void rh_init_descriptors(rh_t *instance)
+{
+	assert(instance);
+
+	instance->descriptors.configuration = ohci_rh_conf_descriptor;
+	instance->descriptors.interface = ohci_rh_iface_descriptor;
+	instance->descriptors.endpoint = ohci_rh_ep_descriptor;
+	create_serialized_hub_descriptor(instance);
+
+	instance->descriptors.endpoint.max_packet_size =
+	    instance->interrupt_mask_size;
+
+	instance->descriptors.configuration.total_length =
+	    sizeof(usb_standard_configuration_descriptor_t) +
+	    sizeof(usb_standard_endpoint_descriptor_t) +
+	    sizeof(usb_standard_interface_descriptor_t) +
+	    instance->hub_descriptor_size;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Create bitmap of changes to answer status interrupt.
+ *
+ * Result contains bitmap where bit 0 indicates change on hub and
+ * bit i indicates change on i`th port (i>0). For more info see
+ * Hub and Port status bitmap specification in USB specification
+ * (chapter 11.13.4).
+ * @param instance root hub instance
+ * @return Mask of changes.
+ */
+uint16_t create_interrupt_mask(rh_t *instance)
+{
+	assert(instance);
+	uint16_t mask = 0;
+
+	/* Only local power source change and over-current change can happen */
+	if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
+		mask |= 1;
+	}
+	size_t port = 1;
+	for (; port <= instance->port_count; ++port) {
+		/* Write-clean bits are those that indicate change */
+		if (RHPS_CHANGE_WC_MASK
+		    & instance->registers->rh_port_status[port - 1]) {
+
+			mask |= (1 << port);
+		}
+	}
+	/* USB is little endian */
+	return host2uint32_t_le(mask);
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Create answer to status request.
+ *
+ * This might be either hub status or port status request. If neither,
+ * ENOTSUP is returned.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+int get_status(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	const usb_device_request_setup_packet_t *request_packet =
+	    (usb_device_request_setup_packet_t*)request->setup_buffer;
+
+	if (request->buffer_size < 4) {
+		usb_log_error("Buffer too small for get status request.\n");
+		return EOVERFLOW;
+	}
+
+	/* Hub status: just filter relevant info from rh_status reg */
+	if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) {
+		const uint32_t data = instance->registers->rh_status &
+		    (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG);
+		memcpy(request->data_buffer, &data, 4);
+		TRANSFER_OK(4);
+	}
+
+	/* Copy appropriate rh_port_status register, OHCI designers were
+	 * kind enough to make those bit values match USB specification */
+	if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) {
+		const unsigned port = request_packet->index;
+		if (port < 1 || port > instance->port_count)
+			return EINVAL;
+
+		const uint32_t data =
+		    instance->registers->rh_port_status[port - 1];
+		memcpy(request->data_buffer, &data, 4);
+		TRANSFER_OK(4);
+	}
+
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Create answer to a descriptor request.
+ *
+ * This might be a request for standard (configuration, device, endpoint or
+ * interface) or device specific (hub) descriptor.
+ * @param instance Root hub instance
+ * @param request Structure containing both request and response information
+ * @return Error code
+ */
+int get_descriptor(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	const usb_device_request_setup_packet_t *setup_request =
+	    (usb_device_request_setup_packet_t *) request->setup_buffer;
+	size_t size;
+	const void *descriptor = NULL;
+	const uint16_t setup_request_value = setup_request->value_high;
+	//(setup_request->value_low << 8);
+	switch (setup_request_value)
+	{
+	case USB_DESCTYPE_HUB:
+		usb_log_debug2("USB_DESCTYPE_HUB\n");
+		/* Hub descriptor was generated locally */
+		descriptor = instance->descriptors.hub;
+		size = instance->hub_descriptor_size;
+		break;
+
+	case USB_DESCTYPE_DEVICE:
+		usb_log_debug2("USB_DESCTYPE_DEVICE\n");
+		/* Device descriptor is shared (No one should ask for it)*/
+		descriptor = &ohci_rh_device_descriptor;
+		size = sizeof(ohci_rh_device_descriptor);
+		break;
+
+	case USB_DESCTYPE_CONFIGURATION:
+		usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
+		/* Start with configuration and add others depending on
+		 * request size */
+		descriptor = &instance->descriptors;
+		size = instance->descriptors.configuration.total_length;
+		break;
+
+	case USB_DESCTYPE_INTERFACE:
+		usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
+		/* Use local interface descriptor. There is one and it
+		 * might be modified */
+		descriptor = &instance->descriptors.interface;
+		size = sizeof(instance->descriptors.interface);
+		break;
+
+	case USB_DESCTYPE_ENDPOINT:
+		/* Use local endpoint descriptor. There is one
+		 * it might have max_packet_size field modified*/
+		usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
+		descriptor = &instance->descriptors.endpoint;
+		size = sizeof(instance->descriptors.endpoint);
+		break;
+
+	default:
+		usb_log_debug2("USB_DESCTYPE_EINVAL %d \n"
+		    "\ttype %d\n\trequest %d\n\tvalue "
+		    "%d\n\tindex %d\n\tlen %d\n ",
+		    setup_request->value,
+		    setup_request->request_type, setup_request->request,
+		    setup_request_value, setup_request->index,
+		    setup_request->length);
+		return EINVAL;
+	}
+	if (request->buffer_size < size) {
+		size = request->buffer_size;
+	}
+
+	memcpy(request->data_buffer, descriptor, size);
+	TRANSFER_OK(size);
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * process feature-enabling request on hub
+ *
+ * @param instance root hub instance
+ * @param feature feature selector
+ * @param port port number, counted from 1
+ * @param enable enable or disable the specified feature
+ * @return error code
+ */
+int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
+{
+	assert(instance);
+
+	if (port < 1 || port > instance->port_count)
+		return EINVAL;
+
+	switch (feature)
+	{
+	case USB_HUB_FEATURE_PORT_POWER:   //8
+		/* No power switching */
+		if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
+			return EOK;
+		/* Ganged power switching */
+		if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
+			instance->registers->rh_status = RHS_SET_GLOBAL_POWER;
+			return EOK;
+		}
+	case USB_HUB_FEATURE_PORT_ENABLE:  //1
+	case USB_HUB_FEATURE_PORT_SUSPEND: //2
+	case USB_HUB_FEATURE_PORT_RESET:   //4
+		/* Nice thing is that these shifts correspond to the position
+		 * of control bits in register */
+		instance->registers->rh_port_status[port - 1] = (1 << feature);
+		return EOK;
+	default:
+		return ENOTSUP;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process feature clear request.
+ *
+ * @param instance root hub instance
+ * @param feature feature selector
+ * @param port port number, counted from 1
+ * @param enable enable or disable the specified feature
+ * @return error code
+ */
+int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
+{
+	assert(instance);
+
+	if (port < 1 || port > instance->port_count)
+		return EINVAL;
+
+	/* Enabled features to clear: see page 269 of USB specs */
+	switch (feature)
+	{
+	case USB_HUB_FEATURE_PORT_POWER:          //8
+		/* No power switching */
+		if (instance->registers->rh_desc_a & RHDA_NPS_FLAG)
+			return ENOTSUP;
+		/* Ganged power switching */
+		if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) {
+			instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
+			return EOK;
+		}
+		instance->registers->rh_port_status[port - 1] =
+			RHPS_CLEAR_PORT_POWER;
+		return EOK;
+
+	case USB_HUB_FEATURE_PORT_ENABLE:         //1
+		instance->registers->rh_port_status[port - 1] =
+			RHPS_CLEAR_PORT_ENABLE;
+		return EOK;
+
+	case USB_HUB_FEATURE_PORT_SUSPEND:        //2
+		instance->registers->rh_port_status[port - 1] =
+			RHPS_CLEAR_PORT_SUSPEND;
+		return EOK;
+
+	case USB_HUB_FEATURE_C_PORT_CONNECTION:   //16
+	case USB_HUB_FEATURE_C_PORT_ENABLE:       //17
+	case USB_HUB_FEATURE_C_PORT_SUSPEND:      //18
+	case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19
+	case USB_HUB_FEATURE_C_PORT_RESET:        //20
+		/* Nice thing is that these shifts correspond to the position
+		 * of control bits in register */
+		instance->registers->rh_port_status[port - 1] = (1 << feature);
+		return EOK;
+
+	default:
+		return ENOTSUP;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * process one of requests that do not request nor carry additional data
+ *
+ * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or
+ * USB_DEVREQ_SET_ADDRESS.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+int set_feature(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	const usb_device_request_setup_packet_t *setup_request =
+	    (usb_device_request_setup_packet_t *) request->setup_buffer;
+	switch (setup_request->request_type)
+	{
+	case USB_HUB_REQ_TYPE_SET_PORT_FEATURE:
+		usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
+		return set_feature_port(instance,
+		    setup_request->value, setup_request->index);
+
+	case USB_HUB_REQ_TYPE_SET_HUB_FEATURE:
+		/* Chapter 11.16.2 specifies that hub can be recipient
+		 * only for C_HUB_LOCAL_POWER and C_HUB_OVER_CURRENT
+		 * features. It makes no sense to SET either. */
+		usb_log_error("Invalid HUB set feature request.\n");
+		return ENOTSUP;
+	default:
+		usb_log_error("Invalid set feature request type: %d\n",
+		    setup_request->request_type);
+		return EINVAL;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * process one of requests that do not request nor carry additional data
+ *
+ * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or
+ * USB_DEVREQ_SET_ADDRESS.
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+int clear_feature(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	const usb_device_request_setup_packet_t *setup_request =
+	    (usb_device_request_setup_packet_t *) request->setup_buffer;
+	request->transfered_size = 0;
+	switch (setup_request->request_type)
+	{
+	case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE:
+		usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n");
+		return clear_feature_port(instance,
+		    setup_request->value, setup_request->index);
+
+	case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE:
+		usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE\n");
+		/*
+		 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and
+		 * C_HUB_OVER_CURRENT are supported. C_HUB_OVER_CURRENT is represented
+		 * by OHCI RHS_OCIC_FLAG. C_HUB_LOCAL_POWER is not supported
+		 * as root hubs do not support local power status feature.
+		 * (OHCI pg. 127) */
+		if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
+			instance->registers->rh_status = RHS_OCIC_FLAG;
+			TRANSFER_OK(0);
+		}
+	default:
+		usb_log_error("Invalid clear feature request type: %d\n",
+		    setup_request->request_type);
+		return EINVAL;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process hub control request.
+ *
+ * If needed, writes answer into the request structure.
+ * Request can be one of
+ * USB_DEVREQ_GET_STATUS,
+ * USB_DEVREQ_GET_DESCRIPTOR,
+ * USB_DEVREQ_GET_CONFIGURATION,
+ * USB_DEVREQ_CLEAR_FEATURE,
+ * USB_DEVREQ_SET_FEATURE,
+ * USB_DEVREQ_SET_ADDRESS,
+ * USB_DEVREQ_SET_DESCRIPTOR or
+ * USB_DEVREQ_SET_CONFIGURATION.
+ *
+ * @param instance root hub instance
+ * @param request structure containing both request and response information
+ * @return error code
+ */
+int control_request(rh_t *instance, usb_transfer_batch_t *request)
+{
+	assert(instance);
+	assert(request);
+
+	if (!request->setup_buffer) {
+		usb_log_error("Root hub received empty transaction!");
+		return EINVAL;
+	}
+
+	if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
+		usb_log_error("Setup packet too small\n");
+		return EOVERFLOW;
+	}
+
+	usb_log_debug2("CTRL packet: %s.\n",
+	    usb_debug_str_buffer((uint8_t *) request->setup_buffer, 8, 8));
+	const usb_device_request_setup_packet_t *setup_request =
+	    (usb_device_request_setup_packet_t *) request->setup_buffer;
+	switch (setup_request->request)
+	{
+	case USB_DEVREQ_GET_STATUS:
+		usb_log_debug("USB_DEVREQ_GET_STATUS\n");
+		return get_status(instance, request);
+
+	case USB_DEVREQ_GET_DESCRIPTOR:
+		usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
+		return get_descriptor(instance, request);
+
+	case USB_DEVREQ_GET_CONFIGURATION:
+		usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
+		if (request->buffer_size != 1)
+			return EINVAL;
+		request->data_buffer[0] = 1;
+		TRANSFER_OK(1);
+
+	case USB_DEVREQ_CLEAR_FEATURE:
+		usb_log_debug2("Processing request without "
+		    "additional data\n");
+		return clear_feature(instance, request);
+	case USB_DEVREQ_SET_FEATURE:
+		usb_log_debug2("Processing request without "
+		    "additional data\n");
+		return set_feature(instance, request);
+
+	case USB_DEVREQ_SET_ADDRESS:
+		usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
+		instance->address = setup_request->value;
+		TRANSFER_OK(0);
+
+	case USB_DEVREQ_SET_CONFIGURATION:
+		usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n");
+		/* We don't need to do anything */
+		TRANSFER_OK(0);
+
+	case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */
+	default:
+		usb_log_error("Received unsupported request: %d.\n",
+		    setup_request->request);
+		return ENOTSUP;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/root_hub.h
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/root_hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,79 @@
+/*
+ * 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_ROOT_HUB_H
+#define DRV_OHCI_ROOT_HUB_H
+
+#include <usb/usb.h>
+#include <usb/dev/driver.h>
+
+#include "ohci_regs.h"
+#include "batch.h"
+
+#define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
+
+/**
+ * ohci root hub representation
+ */
+typedef struct rh {
+	/** pointer to ohci driver registers */
+	ohci_regs_t *registers;
+	/** usb address of the root hub */
+	usb_address_t address;
+	/** hub port count */
+	size_t port_count;
+	/** interrupt transfer waiting for an actual interrupt to occur */
+	usb_transfer_batch_t *unfinished_interrupt_transfer;
+	/** size of interrupt buffer */
+	size_t interrupt_mask_size;
+	/** Descriptors */
+	struct {
+		usb_standard_configuration_descriptor_t configuration;
+		usb_standard_interface_descriptor_t interface;
+		usb_standard_endpoint_descriptor_t endpoint;
+		uint8_t hub[HUB_DESCRIPTOR_MAX_SIZE];
+	} __attribute__ ((packed)) descriptors;
+	/** size of hub descriptor */
+	size_t hub_descriptor_size;
+
+} rh_t;
+
+void rh_init(rh_t *instance, ohci_regs_t *regs);
+
+void rh_request(rh_t *instance, usb_transfer_batch_t *request);
+
+void rh_interrupt(rh_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/ohci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/ohci/utils/malloc32.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/ohci/utils/malloc32.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 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 drvusbohci
+ * @{
+ */
+/** @file
+ * @brief OHCI driver
+ */
+#ifndef DRV_OHCI_UTILS_MALLOC32_H
+#define DRV_OHCI_UTILS_MALLOC32_H
+
+#include <assert.h>
+#include <malloc.h>
+#include <errno.h>
+#include <mem.h>
+#include <as.h>
+
+/** Get physical address translation
+ *
+ * @param[in] addr Virtual address to translate
+ * @return Physical address if exists, NULL otherwise.
+ */
+static inline uintptr_t addr_to_phys(void *addr)
+{
+	uintptr_t result;
+	int ret = as_get_physical_mapping(addr, &result);
+
+	if (ret != EOK)
+		return 0;
+	return (result | ((uintptr_t)addr & 0xfff));
+}
+/*----------------------------------------------------------------------------*/
+/** Physical mallocator simulator
+ *
+ * @param[in] size Size of the required memory space
+ * @return Address of the aligned and big enough memory place, NULL on failure.
+ */
+static inline void * malloc32(size_t size)
+	{ return memalign(size, size); }
+/*----------------------------------------------------------------------------*/
+/** Physical mallocator simulator
+ *
+ * @param[in] addr Address of the place allocated by malloc32
+ */
+static inline void free32(void *addr)
+	{ if (addr) free(addr); }
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/Makefile
===================================================================
--- uspace/drv/bus/usb/uhci/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = uhci
+
+SOURCES = \
+	iface.c \
+	main.c \
+	transfer_list.c \
+	uhci.c \
+	hc.c \
+	root_hub.c \
+	hw_struct/transfer_descriptor.c \
+	pci.c \
+	batch.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/uhci/batch.c
===================================================================
--- uspace/drv/bus/usb/uhci/batch.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/batch.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,428 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver USB transfer structure
+ */
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/usb.h>
+#include <usb/debug.h>
+
+#include "batch.h"
+#include "transfer_list.h"
+#include "hw_struct/transfer_descriptor.h"
+#include "utils/malloc32.h"
+
+#define DEFAULT_ERROR_COUNT 3
+
+/** UHCI specific data required for USB transfer */
+typedef struct uhci_transfer_batch {
+	/** Queue head
+	 * This QH is used to maintain UHCI schedule structure and the element
+	 * pointer points to the first TD of this batch.
+	 */
+	qh_t *qh;
+	/** List of TDs needed for the transfer */
+	td_t *tds;
+	/** Number of TDs used by the transfer */
+	size_t td_count;
+	/** Data buffer, must be accessible by the UHCI hw */
+	void *device_buffer;
+} uhci_transfer_batch_t;
+/*----------------------------------------------------------------------------*/
+static void batch_control(usb_transfer_batch_t *instance,
+    usb_packet_id data_stage, usb_packet_id status_stage);
+static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
+/*----------------------------------------------------------------------------*/
+/** Safely destructs uhci_transfer_batch_t structure
+ *
+ * @param[in] uhci_batch Instance to destroy.
+ */
+static void uhci_transfer_batch_dispose(void *uhci_batch)
+{
+	uhci_transfer_batch_t *instance = uhci_batch;
+	assert(instance);
+	free32(instance->device_buffer);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Allocate memory and initialize internal data structure.
+ *
+ * @param[in] fun DDF function to pass to callback.
+ * @param[in] ep Communication target
+ * @param[in] buffer Data source/destination.
+ * @param[in] buffer_size Size of the buffer.
+ * @param[in] setup_buffer Setup data source (if not NULL)
+ * @param[in] setup_size Size of setup_buffer (should be always 8)
+ * @param[in] func_in function to call on inbound transfer completion
+ * @param[in] func_out function to call on outbound transfer completion
+ * @param[in] arg additional parameter to func_in or func_out
+ * @return Valid pointer if all structures were successfully created,
+ * NULL otherwise.
+ *
+ * Determines the number of needed transfer descriptors (TDs).
+ * Prepares a transport buffer (that is accessible by the hardware).
+ * Initializes parameters needed for the transfer and callback.
+ */
+usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
+    char *buffer, size_t buffer_size,
+    const char* setup_buffer, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out, void *arg)
+{
+	assert(ep);
+	assert(func_in == NULL || func_out == NULL);
+	assert(func_in != NULL || func_out != NULL);
+
+#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
+	if (ptr == NULL) { \
+		usb_log_error(message); \
+		if (uhci_data) { \
+			uhci_transfer_batch_dispose(uhci_data); \
+		} \
+		return NULL; \
+	} else (void)0
+
+	uhci_transfer_batch_t *uhci_data =
+	    malloc(sizeof(uhci_transfer_batch_t));
+	CHECK_NULL_DISPOSE_RETURN(uhci_data,
+	    "Failed to allocate UHCI batch.\n");
+	bzero(uhci_data, sizeof(uhci_transfer_batch_t));
+
+	uhci_data->td_count =
+	    (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
+	if (ep->transfer_type == USB_TRANSFER_CONTROL) {
+		uhci_data->td_count += 2;
+	}
+
+	assert((sizeof(td_t) % 16) == 0);
+	const size_t total_size = (sizeof(td_t) * uhci_data->td_count)
+	    + sizeof(qh_t) + setup_size + buffer_size;
+	uhci_data->device_buffer = malloc32(total_size);
+	CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer,
+	    "Failed to allocate UHCI buffer.\n");
+	bzero(uhci_data->device_buffer, total_size);
+
+	uhci_data->tds = uhci_data->device_buffer;
+	uhci_data->qh =
+	    (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count));
+
+	qh_init(uhci_data->qh);
+	qh_set_element_td(uhci_data->qh, uhci_data->tds);
+
+	usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
+	CHECK_NULL_DISPOSE_RETURN(instance,
+	    "Failed to allocate batch instance.\n");
+	void *setup =
+	    uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)
+	    + sizeof(qh_t);
+	void *data_buffer = setup + setup_size;
+	usb_transfer_batch_init(instance, ep, buffer, data_buffer, buffer_size,
+	    setup, setup_size, func_in, func_out, arg, fun,
+	    uhci_data, uhci_transfer_batch_dispose);
+
+	memcpy(instance->setup_buffer, setup_buffer, setup_size);
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
+	    " memory structures ready.\n", instance,
+	    USB_TRANSFER_BATCH_ARGS(*instance));
+	return instance;
+}
+/*----------------------------------------------------------------------------*/
+/** Check batch TDs for activity.
+ *
+ * @param[in] instance Batch structure to use.
+ * @return False, if there is an active TD, true otherwise.
+ *
+ * Walk all TDs. Stop with false if there is an active one (it is to be
+ * processed). Stop with true if an error is found. Return true if the last TD
+ * is reached.
+ */
+bool batch_is_complete(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	uhci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+
+	usb_log_debug2("Batch(%p) checking %zu transfer(s) for completion.\n",
+	    instance, data->td_count);
+	instance->transfered_size = 0;
+	size_t i = 0;
+	for (;i < data->td_count; ++i) {
+		if (td_is_active(&data->tds[i])) {
+			return false;
+		}
+
+		instance->error = td_status(&data->tds[i]);
+		if (instance->error != EOK) {
+			usb_log_debug("Batch(%p) found error TD(%zu):%"
+			    PRIx32 ".\n", instance, i, data->tds[i].status);
+			td_print_status(&data->tds[i]);
+
+			assert(instance->ep != NULL);
+			endpoint_toggle_set(instance->ep,
+			    td_toggle(&data->tds[i]));
+			if (i > 0)
+				goto substract_ret;
+			return true;
+		}
+
+		instance->transfered_size += td_act_size(&data->tds[i]);
+		if (td_is_short(&data->tds[i]))
+			goto substract_ret;
+	}
+substract_ret:
+	instance->transfered_size -= instance->setup_size;
+	return true;
+}
+
+#define LOG_BATCH_INITIALIZED(batch, name) \
+	usb_log_debug2("Batch %p %s " USB_TRANSFER_BATCH_FMT " initialized.\n", \
+	    (batch), (name), USB_TRANSFER_BATCH_ARGS(*(batch)))
+
+/*----------------------------------------------------------------------------*/
+/** Prepares control write transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control function with pids OUT and IN.
+ */
+void batch_control_write(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	batch_control(instance, USB_PID_OUT, USB_PID_IN);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "control write");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepares control read transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Uses generic control with pids IN and OUT.
+ */
+void batch_control_read(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	batch_control(instance, USB_PID_IN, USB_PID_OUT);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "control read");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare interrupt in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_IN.
+ */
+void batch_interrupt_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	batch_data(instance, USB_PID_IN);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "interrupt in");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare interrupt out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_OUT.
+ */
+void batch_interrupt_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	batch_data(instance, USB_PID_OUT);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "interrupt out");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare bulk in transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_IN.
+ */
+void batch_bulk_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	batch_data(instance, USB_PID_IN);
+	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "bulk in");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare bulk out transfer.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ * Data transfer with PID_OUT.
+ */
+void batch_bulk_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	batch_data(instance, USB_PID_OUT);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
+	LOG_BATCH_INITIALIZED(instance, "bulk out");
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare generic data transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] pid Pid to use for data transactions.
+ *
+ * Transactions with alternating toggle bit and supplied pid value.
+ * The last transfer is marked with IOC flag.
+ */
+void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid)
+{
+	assert(instance);
+	uhci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+
+	const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
+	int toggle = endpoint_toggle_get(instance->ep);
+	assert(toggle == 0 || toggle == 1);
+
+	size_t td = 0;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		const size_t packet_size =
+		    (instance->ep->max_packet_size > remain_size) ?
+		    remain_size : instance->ep->max_packet_size;
+
+		td_t *next_td = (td + 1 < data->td_count)
+		    ? &data->tds[td + 1] : NULL;
+
+
+		usb_target_t target =
+		    { instance->ep->address, instance->ep->endpoint };
+
+		assert(td < data->td_count);
+		td_init(
+		    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, target, pid, buffer, next_td);
+
+		++td;
+		toggle = 1 - toggle;
+		buffer += packet_size;
+		assert(packet_size <= remain_size);
+		remain_size -= packet_size;
+	}
+	td_set_ioc(&data->tds[td - 1]);
+	endpoint_toggle_set(instance->ep, toggle);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare generic control transfer
+ *
+ * @param[in] instance Batch structure to use.
+ * @param[in] data_stage Pid to use for data tds.
+ * @param[in] status_stage Pid to use for data tds.
+ *
+ * Setup stage with toggle 0 and USB_PID_SETUP.
+ * Data stage with alternating toggle and pid supplied by parameter.
+ * Status stage with toggle 1 and pid supplied by parameter.
+ * The last transfer is marked with IOC.
+ */
+void batch_control(usb_transfer_batch_t *instance,
+   usb_packet_id data_stage, usb_packet_id status_stage)
+{
+	assert(instance);
+	uhci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	assert(data->td_count >= 2);
+
+	const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
+	const usb_target_t target =
+	    { instance->ep->address, instance->ep->endpoint };
+
+	/* setup stage */
+	td_init(
+	    data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
+	    low_speed, target, USB_PID_SETUP, instance->setup_buffer,
+	    &data->tds[1]);
+
+	/* data stage */
+	size_t td = 1;
+	unsigned toggle = 1;
+	size_t remain_size = instance->buffer_size;
+	char *buffer = instance->data_buffer;
+	while (remain_size > 0) {
+		const size_t packet_size =
+		    (instance->ep->max_packet_size > remain_size) ?
+		    remain_size : instance->ep->max_packet_size;
+
+		td_init(
+		    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
+		    toggle, false, low_speed, target, data_stage,
+		    buffer, &data->tds[td + 1]);
+
+		++td;
+		toggle = 1 - toggle;
+		buffer += packet_size;
+		assert(td < data->td_count);
+		assert(packet_size <= remain_size);
+		remain_size -= packet_size;
+	}
+
+	/* status stage */
+	assert(td == data->td_count - 1);
+
+	td_init(
+	    &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
+	    target, status_stage, NULL, NULL);
+	td_set_ioc(&data->tds[td]);
+
+	usb_log_debug2("Control last TD status: %x.\n",
+	    data->tds[td].status);
+}
+/*----------------------------------------------------------------------------*/
+/** Provides access to QH data structure.
+ *
+ * @param[in] instance Batch pointer to use.
+ * @return Pointer to the QH used by the batch.
+ */
+qh_t * batch_qh(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	uhci_transfer_batch_t *data = instance->private_data;
+	assert(data);
+	return data->qh;
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/batch.h
===================================================================
--- uspace/drv/bus/usb/uhci/batch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/batch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,65 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver USB tranfer helper functions
+ */
+#ifndef DRV_UHCI_BATCH_H
+#define DRV_UHCI_BATCH_H
+
+#include <usb/host/batch.h>
+
+#include "hw_struct/queue_head.h"
+
+usb_transfer_batch_t * batch_get(
+    ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size,
+    const char *setup_buffer, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out,
+    void *arg);
+
+void batch_dispose(usb_transfer_batch_t *instance);
+
+bool batch_is_complete(usb_transfer_batch_t *instance);
+
+void batch_control_write(usb_transfer_batch_t *instance);
+void batch_control_read(usb_transfer_batch_t *instance);
+
+void batch_interrupt_in(usb_transfer_batch_t *instance);
+void batch_interrupt_out(usb_transfer_batch_t *instance);
+
+void batch_bulk_in(usb_transfer_batch_t *instance);
+void batch_bulk_out(usb_transfer_batch_t *instance);
+
+qh_t * batch_qh(usb_transfer_batch_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,484 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI Host controller driver routines
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <adt/list.h>
+#include <libarch/ddi.h>
+
+#include <usb/debug.h>
+#include <usb/usb.h>
+
+#include "hc.h"
+
+#define UHCI_INTR_ALLOW_INTERRUPTS \
+    (UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET)
+#define UHCI_STATUS_USED_INTERRUPTS \
+    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
+
+static const irq_cmd_t uhci_irq_commands[] =
+{
+	{ .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},
+	{ .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,
+	  .value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS },
+	{ .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
+	{ .cmd = CMD_PIO_WRITE_A_16, .srcarg = 1, .addr = NULL/*filled later*/},
+	{ .cmd = CMD_ACCEPT },
+};
+
+static int hc_init_transfer_lists(hc_t *instance);
+static int hc_init_mem_structures(hc_t *instance);
+static void hc_init_hw(hc_t *instance);
+
+static int hc_interrupt_emulator(void *arg);
+static int hc_debug_checker(void *arg);
+
+/*----------------------------------------------------------------------------*/
+/** Get number of commands used in IRQ code.
+ * @return Number of commands.
+ */
+size_t hc_irq_cmd_count(void)
+{
+	return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t);
+}
+/*----------------------------------------------------------------------------*/
+/** Generate IRQ code commands.
+ * @param[out] cmds Place to store the commands.
+ * @param[in] cmd_size Size of the place (bytes).
+ * @param[in] regs Physical address of device's registers.
+ * @param[in] reg_size Size of the register area (bytes).
+ *
+ * @return Error code.
+ */
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
+{
+	if (cmd_size < sizeof(uhci_irq_commands)
+	    || reg_size < sizeof(uhci_regs_t))
+		return EOVERFLOW;
+
+	uhci_regs_t *registers = (uhci_regs_t*)regs;
+
+	memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
+
+	cmds[0].addr = (void*)&registers->usbsts;
+	cmds[3].addr = (void*)&registers->usbsts;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc driver structure
+ *
+ * @param[in] instance Memory place to initialize.
+ * @param[in] regs Address of I/O control registers.
+ * @param[in] reg_size Size of I/O control registers.
+ * @param[in] interrupts True if hw interrupts should be used.
+ * @return Error code.
+ * @note Should be called only once on any structure.
+ *
+ * Initializes memory structures, starts up hw, and launches debugger and
+ * interrupt fibrils.
+ */
+int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
+{
+	assert(reg_size >= sizeof(uhci_regs_t));
+	int ret;
+
+#define CHECK_RET_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		return ret; \
+	} else (void) 0
+
+	instance->hw_interrupts = interrupts;
+	instance->hw_failures = 0;
+
+	/* allow access to hc control registers */
+	uhci_regs_t *io;
+	ret = pio_enable(regs, reg_size, (void **)&io);
+	CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n",
+	    io, str_error(ret));
+	instance->registers = io;
+	usb_log_debug(
+	    "Device registers at %p (%zuB) accessible.\n", io, reg_size);
+
+	ret = hc_init_mem_structures(instance);
+	CHECK_RET_RETURN(ret,
+	    "Failed to initialize UHCI memory structures: %s.\n",
+	    str_error(ret));
+
+	hc_init_hw(instance);
+	if (!interrupts) {
+		instance->interrupt_emulator =
+		    fibril_create(hc_interrupt_emulator, instance);
+		fibril_add_ready(instance->interrupt_emulator);
+	}
+	(void)hc_debug_checker;
+
+	return EOK;
+#undef CHECK_RET_DEST_FUN_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc hw resources.
+ *
+ * @param[in] instance UHCI structure to use.
+ * For magic values see UHCI Design Guide
+ */
+void hc_init_hw(hc_t *instance)
+{
+	assert(instance);
+	uhci_regs_t *registers = instance->registers;
+
+	/* Reset everything, who knows what touched it before us */
+	pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
+	async_usleep(50000); /* 50ms according to USB spec(root hub reset) */
+	pio_write_16(&registers->usbcmd, 0);
+
+	/* Reset hc, all states and counters. Hope that hw is not broken */
+	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
+	do { async_usleep(10); }
+	while ((pio_read_16(&registers->usbcmd) & UHCI_CMD_HCRESET) != 0);
+
+	/* Set frame to exactly 1ms */
+	pio_write_8(&registers->sofmod, 64);
+
+	/* Set frame list pointer */
+	const uint32_t pa = addr_to_phys(instance->frame_list);
+	pio_write_32(&registers->flbaseadd, pa);
+
+	if (instance->hw_interrupts) {
+		/* Enable all interrupts, but resume interrupt */
+		pio_write_16(&instance->registers->usbintr,
+		    UHCI_INTR_ALLOW_INTERRUPTS);
+	}
+
+	const uint16_t cmd = pio_read_16(&registers->usbcmd);
+	if (cmd != 0)
+		usb_log_warning("Previous command value: %x.\n", cmd);
+
+	/* Start the hc with large(64B) packet FSBR */
+	pio_write_16(&registers->usbcmd,
+	    UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc memory structures.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @return Error code
+ * @note Should be called only once on any structure.
+ *
+ * Structures:
+ *  - interrupt code (I/O addressses are customized per instance)
+ *  - transfer lists (queue heads need to be accessible by the hw)
+ *  - frame list page (needs to be one UHCI hw accessible 4K page)
+ */
+int hc_init_mem_structures(hc_t *instance)
+{
+	assert(instance);
+#define CHECK_RET_RETURN(ret, message...) \
+	if (ret != EOK) { \
+		usb_log_error(message); \
+		return ret; \
+	} else (void) 0
+
+	/* Init transfer lists */
+	int ret = hc_init_transfer_lists(instance);
+	CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
+	usb_log_debug("Initialized transfer lists.\n");
+
+	/* Init device keeper */
+	usb_device_keeper_init(&instance->manager);
+	usb_log_debug("Initialized device keeper.\n");
+
+	ret = usb_endpoint_manager_init(&instance->ep_manager,
+	    BANDWIDTH_AVAILABLE_USB11);
+	CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
+	    str_error(ret));
+
+	/* Init USB frame list page*/
+	instance->frame_list = get_page();
+	if (!instance->frame_list) {
+		usb_log_error("Failed to get frame list page.\n");
+		usb_endpoint_manager_destroy(&instance->ep_manager);
+		return ENOMEM;
+	}
+	usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
+
+	/* Set all frames to point to the first queue head */
+	const uint32_t queue = LINK_POINTER_QH(
+	        addr_to_phys(instance->transfers_interrupt.queue_head));
+	unsigned i = 0;
+	for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
+		instance->frame_list[i] = queue;
+	}
+
+	return EOK;
+#undef CHECK_RET_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI hc transfer lists.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @return Error code
+ * @note Should be called only once on any structure.
+ *
+ * Initializes transfer lists and sets them in one chain to support proper
+ * USB scheduling. Sets pointer table for quick access.
+ */
+int hc_init_transfer_lists(hc_t *instance)
+{
+	assert(instance);
+#define SETUP_TRANSFER_LIST(type, name) \
+do { \
+	int ret = transfer_list_init(&instance->transfers_##type, name); \
+	if (ret != EOK) { \
+		usb_log_error("Failed to setup %s transfer list: %s.\n", \
+		    name, str_error(ret)); \
+		transfer_list_fini(&instance->transfers_bulk_full); \
+		transfer_list_fini(&instance->transfers_control_full); \
+		transfer_list_fini(&instance->transfers_control_slow); \
+		transfer_list_fini(&instance->transfers_interrupt); \
+		return ret; \
+	} \
+} while (0)
+
+	SETUP_TRANSFER_LIST(bulk_full, "BULK FULL");
+	SETUP_TRANSFER_LIST(control_full, "CONTROL FULL");
+	SETUP_TRANSFER_LIST(control_slow, "CONTROL LOW");
+	SETUP_TRANSFER_LIST(interrupt, "INTERRUPT");
+#undef SETUP_TRANSFER_LIST
+	/* Connect lists into one schedule */
+	transfer_list_set_next(&instance->transfers_control_full,
+		&instance->transfers_bulk_full);
+	transfer_list_set_next(&instance->transfers_control_slow,
+		&instance->transfers_control_full);
+	transfer_list_set_next(&instance->transfers_interrupt,
+		&instance->transfers_control_slow);
+
+	/*FSBR, This feature is not needed (adds no benefit) and is supposedly
+	 * buggy on certain hw, enable at your own risk. */
+#ifdef FSBR
+	transfer_list_set_next(&instance->transfers_bulk_full,
+	    &instance->transfers_control_full);
+#endif
+
+	/* Assign pointers to be used during scheduling */
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =
+	  &instance->transfers_interrupt;
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_full;
+	instance->transfers[USB_SPEED_LOW][USB_TRANSFER_CONTROL] =
+	  &instance->transfers_control_slow;
+	instance->transfers[USB_SPEED_FULL][USB_TRANSFER_BULK] =
+	  &instance->transfers_bulk_full;
+
+	return EOK;
+#undef CHECK_RET_CLEAR_RETURN
+}
+/*----------------------------------------------------------------------------*/
+/** Schedule batch for execution.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] batch Transfer batch to schedule.
+ * @return Error code
+ *
+ * Checks for bandwidth availability and appends the batch to the proper queue.
+ */
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+
+	transfer_list_t *list =
+	    instance->transfers[batch->ep->speed][batch->ep->transfer_type];
+	assert(list);
+	transfer_list_add_batch(list, batch);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Take action based on the interrupt cause.
+ *
+ * @param[in] instance UHCI structure to use.
+ * @param[in] status Value of the status register at the time of interrupt.
+ *
+ * Interrupt might indicate:
+ * - transaction completed, either by triggering IOC, SPD, or an error
+ * - some kind of device error
+ * - resume from suspend state (not implemented)
+ */
+void hc_interrupt(hc_t *instance, uint16_t status)
+{
+	assert(instance);
+	/* Lower 2 bits are transaction error and transaction complete */
+	if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
+		LIST_INITIALIZE(done);
+		transfer_list_remove_finished(
+		    &instance->transfers_interrupt, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_control_slow, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_control_full, &done);
+		transfer_list_remove_finished(
+		    &instance->transfers_bulk_full, &done);
+
+		while (!list_empty(&done)) {
+			link_t *item = list_first(&done);
+			list_remove(item);
+			usb_transfer_batch_t *batch =
+			    list_get_instance(item, usb_transfer_batch_t, link);
+			usb_transfer_batch_finish(batch);
+		}
+	}
+	/* Resume interrupts are not supported */
+	if (status & UHCI_STATUS_RESUME) {
+		usb_log_error("Resume interrupt!\n");
+	}
+
+	/* Bits 4 and 5 indicate hc error */
+	if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
+		usb_log_error("UHCI hardware failure!.\n");
+		++instance->hw_failures;
+		transfer_list_abort_all(&instance->transfers_interrupt);
+		transfer_list_abort_all(&instance->transfers_control_slow);
+		transfer_list_abort_all(&instance->transfers_control_full);
+		transfer_list_abort_all(&instance->transfers_bulk_full);
+
+		if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
+			/* reinitialize hw, this triggers virtual disconnect*/
+			hc_init_hw(instance);
+		} else {
+			usb_log_fatal("Too many UHCI hardware failures!.\n");
+			hc_fini(instance);
+		}
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Polling function, emulates interrupts.
+ *
+ * @param[in] arg UHCI hc structure to use.
+ * @return EOK (should never return)
+ */
+int hc_interrupt_emulator(void* arg)
+{
+	usb_log_debug("Started interrupt emulator.\n");
+	hc_t *instance = arg;
+	assert(instance);
+
+	while (1) {
+		/* Read and clear status register */
+		uint16_t status = pio_read_16(&instance->registers->usbsts);
+		pio_write_16(&instance->registers->usbsts, status);
+		if (status != 0)
+			usb_log_debug2("UHCI status: %x.\n", status);
+// Qemu fails to report stalled communication
+// see https://bugs.launchpad.net/qemu/+bug/757654
+// This is a simple workaround to force queue processing every time
+	//	status |= 1;
+		hc_interrupt(instance, status);
+		async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
+	}
+	return EOK;
+}
+/*---------------------------------------------------------------------------*/
+/** Debug function, checks consistency of memory structures.
+ *
+ * @param[in] arg UHCI structure to use.
+ * @return EOK (should never return)
+ */
+int hc_debug_checker(void *arg)
+{
+	hc_t *instance = arg;
+	assert(instance);
+
+#define QH(queue) \
+	instance->transfers_##queue.queue_head
+
+	while (1) {
+		const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
+		const uint16_t sts = pio_read_16(&instance->registers->usbsts);
+		const uint16_t intr =
+		    pio_read_16(&instance->registers->usbintr);
+
+		if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
+			usb_log_debug2("Command: %X Status: %X Intr: %x\n",
+			    cmd, sts, intr);
+		}
+
+		const uintptr_t frame_list =
+		    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
+		if (frame_list != addr_to_phys(instance->frame_list)) {
+			usb_log_debug("Framelist address: %p vs. %p.\n",
+			    (void *) frame_list,
+			    (void *) addr_to_phys(instance->frame_list));
+		}
+
+		int frnum = pio_read_16(&instance->registers->frnum) & 0x3ff;
+
+		uintptr_t expected_pa = instance->frame_list[frnum]
+		    & LINK_POINTER_ADDRESS_MASK;
+		uintptr_t real_pa = addr_to_phys(QH(interrupt));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Interrupt QH: %p (frame %d) vs. %p.\n",
+			    (void *) expected_pa, frnum, (void *) real_pa);
+		}
+
+		expected_pa = QH(interrupt)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(control_slow));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Control Slow QH: %p vs. %p.\n",
+			    (void *) expected_pa, (void *) real_pa);
+		}
+
+		expected_pa = QH(control_slow)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(control_full));
+		if (expected_pa != real_pa) {
+			usb_log_debug("Control Full QH: %p vs. %p.\n",
+			    (void *) expected_pa, (void *) real_pa);
+		}
+
+		expected_pa = QH(control_full)->next & LINK_POINTER_ADDRESS_MASK;
+		real_pa = addr_to_phys(QH(bulk_full));
+		if (expected_pa != real_pa ) {
+			usb_log_debug("Bulk QH: %p vs. %p.\n",
+			    (void *) expected_pa, (void *) real_pa);
+		}
+		async_usleep(UHCI_DEBUGER_TIMEOUT);
+	}
+	return EOK;
+#undef QH
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,152 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI host controller driver structure
+ */
+#ifndef DRV_UHCI_HC_H
+#define DRV_UHCI_HC_H
+
+#include <fibril.h>
+#include <ddi.h>
+
+#include <usb/host/device_keeper.h>
+#include <usb/host/usb_endpoint_manager.h>
+#include <usb/host/batch.h>
+
+#include "transfer_list.h"
+
+/** UHCI I/O registers layout */
+typedef struct uhci_regs {
+	/** Command register, controls HC behaviour */
+	uint16_t usbcmd;
+#define UHCI_CMD_MAX_PACKET (1 << 7)
+#define UHCI_CMD_CONFIGURE  (1 << 6)
+#define UHCI_CMD_DEBUG  (1 << 5)
+#define UHCI_CMD_FORCE_GLOBAL_RESUME  (1 << 4)
+#define UHCI_CMD_FORCE_GLOBAL_SUSPEND  (1 << 3)
+#define UHCI_CMD_GLOBAL_RESET  (1 << 2)
+#define UHCI_CMD_HCRESET  (1 << 1)
+#define UHCI_CMD_RUN_STOP  (1 << 0)
+
+	/** Status register, 1 means interrupt is asserted (if enabled) */
+	uint16_t usbsts;
+#define UHCI_STATUS_HALTED (1 << 5)
+#define UHCI_STATUS_PROCESS_ERROR (1 << 4)
+#define UHCI_STATUS_SYSTEM_ERROR (1 << 3)
+#define UHCI_STATUS_RESUME (1 << 2)
+#define UHCI_STATUS_ERROR_INTERRUPT (1 << 1)
+#define UHCI_STATUS_INTERRUPT (1 << 0)
+#define UHCI_STATUS_NM_INTERRUPTS \
+    (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)
+
+	/** Interrupt enabled registers */
+	uint16_t usbintr;
+#define UHCI_INTR_SHORT_PACKET (1 << 3)
+#define UHCI_INTR_COMPLETE (1 << 2)
+#define UHCI_INTR_RESUME (1 << 1)
+#define UHCI_INTR_CRC (1 << 0)
+
+	/** Register stores frame number used in SOF packet */
+	uint16_t frnum;
+
+	/** Pointer(physical) to the Frame List */
+	uint32_t flbaseadd;
+
+	/** SOF modification to match external timers */
+	uint8_t sofmod;
+} uhci_regs_t;
+
+#define UHCI_FRAME_LIST_COUNT 1024
+#define UHCI_INT_EMULATOR_TIMEOUT 10000
+#define UHCI_DEBUGER_TIMEOUT 5000000
+#define UHCI_ALLOWED_HW_FAIL 5
+#define UHCI_NEEDED_IRQ_COMMANDS 5
+
+/** Main UHCI driver structure */
+typedef struct hc {
+	/** USB bus driver, devices and addresses */
+	usb_device_keeper_t manager;
+	/** USB bus driver, endpoints */
+	usb_endpoint_manager_t ep_manager;
+
+	/** Addresses of I/O registers */
+	uhci_regs_t *registers;
+
+	/** Frame List contains 1024 link pointers */
+	link_pointer_t *frame_list;
+
+	/** List and queue of interrupt transfers */
+	transfer_list_t transfers_interrupt;
+	/** List and queue of low speed control transfers */
+	transfer_list_t transfers_control_slow;
+	/** List and queue of full speed bulk transfers */
+	transfer_list_t transfers_bulk_full;
+	/** List and queue of full speed control transfers */
+	transfer_list_t transfers_control_full;
+
+	/** Pointer table to the above lists, helps during scheduling */
+	transfer_list_t *transfers[2][4];
+	/** Fibril periodically checking status register*/
+	fid_t interrupt_emulator;
+	/** Indicator of hw interrupts availability */
+	bool hw_interrupts;
+
+	/** Number of hw failures detected. */
+	unsigned hw_failures;
+} hc_t;
+size_t hc_irq_cmd_count(void);
+int hc_get_irq_commands(
+    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
+int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
+int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
+void hc_interrupt(hc_t *instance, uint16_t status);
+
+/** Safely dispose host controller internal structures
+ *
+ * @param[in] instance Host controller structure to use.
+ */
+static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
+
+/** Get and cast pointer to the driver data
+ *
+ * @param[in] fun DDF function pointer
+ * @return cast pointer to driver_data
+ */
+static inline hc_t * fun_to_hc(ddf_fun_t *fun)
+{
+	assert(fun);
+	return fun->driver_data;
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/hw_struct/link_pointer.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_HW_STRUCT_LINK_POINTER_H
+#define DRV_UHCI_HW_STRUCT_LINK_POINTER_H
+
+/* UHCI link pointer, used by many data structures */
+typedef uint32_t link_pointer_t;
+
+#define LINK_POINTER_TERMINATE_FLAG (1 << 0)
+#define LINK_POINTER_QUEUE_HEAD_FLAG (1 << 1)
+#define LINK_POINTER_ZERO_BIT_FLAG (1 << 2)
+#define LINK_POINTER_VERTICAL_FLAG (1 << 2)
+#define LINK_POINTER_RESERVED_FLAG (1 << 3)
+
+#define LINK_POINTER_ADDRESS_MASK 0xfffffff0 /* upper 28 bits */
+
+#define LINK_POINTER_QH(address) \
+	((address & LINK_POINTER_ADDRESS_MASK) | LINK_POINTER_QUEUE_HEAD_FLAG)
+
+#define LINK_POINTER_TD(address) \
+	(address & LINK_POINTER_ADDRESS_MASK)
+
+#define LINK_POINTER_TERM \
+	((link_pointer_t)LINK_POINTER_TERMINATE_FLAG)
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/uhci/hw_struct/queue_head.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/queue_head.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/hw_struct/queue_head.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_HW_STRUCT_QH_H
+#define DRV_UHCI_HW_STRUCT_QH_H
+#include <assert.h>
+
+#include "link_pointer.h"
+#include "transfer_descriptor.h"
+#include "../utils/malloc32.h"
+
+/** This structure is defined in UHCI design guide p. 31 */
+typedef struct queue_head {
+	/** Pointer to the next entity (another QH or TD */
+	volatile link_pointer_t next;
+	/** Pointer to the contained entities (execution controlled by vertical flag*/
+	volatile link_pointer_t element;
+} __attribute__((packed)) qh_t;
+/*----------------------------------------------------------------------------*/
+/** Initialize queue head structure
+ *
+ * @param[in] instance qh_t structure to initialize.
+ *
+ * Sets both pointer to terminal NULL.
+ */
+static inline void qh_init(qh_t *instance)
+{
+	assert(instance);
+
+	instance->element = 0 | LINK_POINTER_TERMINATE_FLAG;
+	instance->next = 0 | LINK_POINTER_TERMINATE_FLAG;
+}
+/*----------------------------------------------------------------------------*/
+/** Set queue head next pointer
+ *
+ * @param[in] instance qh_t structure to use.
+ * @param[in] next Address of the next queue.
+ *
+ * Adds proper flag. If the pointer is NULL, sets next to terminal NULL.
+ */
+static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
+{
+	uint32_t pa = addr_to_phys(next);
+	if (pa) {
+		instance->next = LINK_POINTER_QH(pa);
+	} else {
+		instance->next = LINK_POINTER_TERM;
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Set queue head element pointer
+ *
+ * @param[in] instance qh_t structure to use.
+ * @param[in] td Transfer descriptor to set as the first element.
+ *
+ * Adds proper flag. If the pointer is NULL, sets element to terminal NULL.
+ */
+static inline void qh_set_element_td(qh_t *instance, td_t *td)
+{
+	uint32_t pa = addr_to_phys(td);
+	if (pa) {
+		instance->element = LINK_POINTER_TD(pa);
+	} else {
+		instance->element = LINK_POINTER_TERM;
+	}
+}
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,176 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <usb/debug.h>
+
+#include "transfer_descriptor.h"
+#include "../utils/malloc32.h"
+
+/** Initialize Transfer Descriptor
+ *
+ * @param[in] instance Memory place to initialize.
+ * @param[in] err_count Number of retries hc should attempt.
+ * @param[in] size Size of data source.
+ * @param[in] toggle Value of toggle bit.
+ * @param[in] iso True if TD represents Isochronous transfer.
+ * @param[in] low_speed Target device's speed.
+ * @param[in] target Address and endpoint receiving the transfer.
+ * @param[in] pid Packet identification (SETUP, IN or OUT).
+ * @param[in] buffer Source of data.
+ * @param[in] next Net TD in transaction.
+ * @return Error code.
+ *
+ * Uses a mix of supplied and default values.
+ * Implicit values:
+ *  - all TDs have vertical flag set (makes transfers to endpoints atomic)
+ *  - in the error field only active it is set
+ *  - if the packet uses PID_IN and is not isochronous SPD is set
+ *
+ * Dumps 8 bytes of buffer if PID_SETUP is used.
+ */
+void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
+    bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
+    td_t *next)
+{
+	assert(instance);
+	assert(size < 1024);
+	assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
+	    || (pid == USB_PID_OUT));
+
+	const uint32_t next_pa = addr_to_phys(next);
+	assert((next_pa & LINK_POINTER_ADDRESS_MASK) == next_pa);
+
+	instance->next = 0
+	    | LINK_POINTER_VERTICAL_FLAG
+	    | (next_pa ? next_pa : LINK_POINTER_TERMINATE_FLAG);
+
+	instance->status = 0
+	    | ((err_count & TD_STATUS_ERROR_COUNT_MASK)
+	        << TD_STATUS_ERROR_COUNT_POS)
+	    | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
+	    | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
+	    | TD_STATUS_ERROR_ACTIVE;
+
+	if (pid == USB_PID_IN && !iso) {
+		instance->status |= TD_STATUS_SPD_FLAG;
+	}
+
+	instance->device = 0
+	    | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
+	    | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
+	    | ((target.address & TD_DEVICE_ADDRESS_MASK)
+	        << TD_DEVICE_ADDRESS_POS)
+	    | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK)
+	        << TD_DEVICE_ENDPOINT_POS)
+	    | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
+
+	instance->buffer_ptr = addr_to_phys(buffer);
+
+	usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
+	    instance, instance->next, instance->status, instance->device,
+	    instance->buffer_ptr, buffer);
+	td_print_status(instance);
+	if (pid == USB_PID_SETUP) {
+		usb_log_debug2("SETUP BUFFER: %s\n",
+		    usb_debug_str_buffer(buffer, 8, 8));
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Convert TD status into standard error code
+ *
+ * @param[in] instance TD structure to use.
+ * @return Error code.
+ */
+int td_status(td_t *instance)
+{
+	assert(instance);
+
+	/* This is hc internal error it should never be reported. */
+	if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
+		return EAGAIN;
+
+	/* CRC or timeout error, like device not present or bad data,
+	 * it won't be reported unless err count reached zero */
+	if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
+		return EBADCHECKSUM;
+
+	/* HC does not end transactions on these, it should never be reported */
+	if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
+		return EAGAIN;
+
+	/* Buffer overrun or underrun */
+	if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
+		return ERANGE;
+
+	/* Device babble is something serious */
+	if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
+		return EIO;
+
+	/* Stall might represent err count reaching zero or stall response from
+	 * the device. If err count reached zero, one of the above is reported*/
+	if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
+		return ESTALL;
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Print values in status field (dw1) in a human readable way.
+ *
+ * @param[in] instance TD structure to use.
+ */
+void td_print_status(td_t *instance)
+{
+	assert(instance);
+	const uint32_t s = instance->status;
+	usb_log_debug2("TD(%p) status(%#" PRIx32 "):%s %d,%s%s%s%s%s%s%s%s%s%s%s %zu.\n",
+	    instance, instance->status,
+	    (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
+	    (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK,
+	    (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "",
+	    (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "",
+	    (s & TD_STATUS_IOC_FLAG) ? " IOC," : "",
+	    (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "",
+	    (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "",
+	    (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "",
+	    (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "",
+	    (s & TD_STATUS_ERROR_NAK) ? " NAK," : "",
+	    (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "",
+	    (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
+	    (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
+	    td_act_size(instance)
+	);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/hw_struct/transfer_descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,166 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
+#define DRV_UHCI_HW_STRUCT_TRANSFER_DESCRIPTOR_H
+
+#include <mem.h>
+#include <usb/usb.h>
+
+#include "link_pointer.h"
+
+/** Transfer Descriptor, defined in UHCI design guide p. 26 */
+typedef struct transfer_descriptor {
+	/** Pointer to the next entity (TD or QH) */
+	link_pointer_t next;
+
+	/** Status doubleword */
+	volatile uint32_t status;
+#define TD_STATUS_RESERVED_MASK 0xc000f800
+#define TD_STATUS_SPD_FLAG         (1 << 29)
+#define TD_STATUS_ERROR_COUNT_POS 27
+#define TD_STATUS_ERROR_COUNT_MASK 0x3
+#define TD_STATUS_LOW_SPEED_FLAG   (1 << 26)
+#define TD_STATUS_ISOCHRONOUS_FLAG (1 << 25)
+#define TD_STATUS_IOC_FLAG         (1 << 24)
+
+#define TD_STATUS_ERROR_ACTIVE    (1 << 23)
+#define TD_STATUS_ERROR_STALLED   (1 << 22)
+#define TD_STATUS_ERROR_BUFFER    (1 << 21)
+#define TD_STATUS_ERROR_BABBLE    (1 << 20)
+#define TD_STATUS_ERROR_NAK       (1 << 19)
+#define TD_STATUS_ERROR_CRC       (1 << 18)
+#define TD_STATUS_ERROR_BIT_STUFF (1 << 17)
+#define TD_STATUS_ERROR_RESERVED  (1 << 16)
+#define TD_STATUS_ERROR_POS 16
+#define TD_STATUS_ERROR_MASK 0xff
+
+#define TD_STATUS_ACTLEN_POS 0
+#define TD_STATUS_ACTLEN_MASK 0x7ff
+
+	/* double word with USB device specific info */
+	volatile uint32_t device;
+#define TD_DEVICE_MAXLEN_POS 21
+#define TD_DEVICE_MAXLEN_MASK 0x7ff
+#define TD_DEVICE_RESERVED_FLAG        (1 << 20)
+#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG (1 << 19)
+#define TD_DEVICE_ENDPOINT_POS 15
+#define TD_DEVICE_ENDPOINT_MASK 0xf
+#define TD_DEVICE_ADDRESS_POS 8
+#define TD_DEVICE_ADDRESS_MASK 0x7f
+#define TD_DEVICE_PID_POS 0
+#define TD_DEVICE_PID_MASK 0xff
+
+	/** Pointer(physical) to the beginning of the transaction's buffer */
+	volatile uint32_t buffer_ptr;
+
+	/* According to UHCI design guide, there is 16 bytes of
+	 * data available here.
+	 * According to linux kernel the hardware does not care,
+	 * it just needs to be aligned. We don't use it anyway.
+	 */
+} __attribute__((packed)) td_t;
+
+
+void td_init(td_t *instance, int error_count, size_t size, bool toggle,
+    bool iso, bool low_speed, usb_target_t target, usb_packet_id pid,
+    void *buffer, td_t *next);
+
+int td_status(td_t *instance);
+
+void td_print_status(td_t *instance);
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing actual size out of TD.
+ *
+ * @param[in] instance TD structure to use.
+ * @return Parsed actual size.
+ */
+static inline size_t td_act_size(td_t *instance)
+{
+	assert(instance);
+	const uint32_t s = instance->status;
+	return ((s >> TD_STATUS_ACTLEN_POS) + 1) & TD_STATUS_ACTLEN_MASK;
+}
+/*----------------------------------------------------------------------------*/
+/** Check whether less than max data were received on SPD marked transfer.
+ *
+ * @param[in] instance TD structure to use.
+ * @return True if data packet is short (less than max bytes and SPD set),
+ * false otherwise.
+ */
+static inline bool td_is_short(td_t *instance)
+{
+	const size_t act_size = td_act_size(instance);
+	const size_t max_size =
+	    ((instance->device >> TD_DEVICE_MAXLEN_POS) + 1)
+	    & TD_DEVICE_MAXLEN_MASK;
+	return
+	    (instance->status | TD_STATUS_SPD_FLAG) && act_size < max_size;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing value of toggle bit.
+ *
+ * @param[in] instance TD structure to use.
+ * @return Toggle bit value.
+ */
+static inline int td_toggle(td_t *instance)
+{
+	assert(instance);
+	return (instance->device & TD_DEVICE_DATA_TOGGLE_ONE_FLAG) ? 1 : 0;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for parsing value of active bit
+ *
+ * @param[in] instance TD structure to use.
+ * @return Active bit value.
+ */
+static inline bool td_is_active(td_t *instance)
+{
+	assert(instance);
+	return (instance->status & TD_STATUS_ERROR_ACTIVE) != 0;
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function for setting IOC bit.
+ *
+ * @param[in] instance TD structure to use.
+ */
+static inline void td_set_ioc(td_t *instance)
+{
+	assert(instance);
+	instance->status |= TD_STATUS_IOC_FLAG;
+}
+/*----------------------------------------------------------------------------*/
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/iface.c
===================================================================
--- uspace/drv/bus/usb/uhci/iface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/iface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver hc interface implementation
+ */
+#include <ddf/driver.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+#include <usb/host/endpoint.h>
+
+#include "iface.h"
+#include "batch.h"
+#include "hc.h"
+
+static inline int setup_batch(
+    ddf_fun_t *fun, usb_target_t target, usb_direction_t direction,
+    void *data, size_t size, void * setup_data, size_t setup_size,
+    usbhc_iface_transfer_in_callback_t in,
+    usbhc_iface_transfer_out_callback_t out, void *arg, const char* name,
+    hc_t **hc, usb_transfer_batch_t **batch)
+{
+	assert(hc);
+	assert(batch);
+	assert(fun);
+	*hc = fun_to_hc(fun);
+	assert(*hc);
+
+	size_t res_bw;
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,
+	    target.address, target.endpoint, direction, &res_bw);
+	if (ep == NULL) {
+		usb_log_error("Endpoint(%d:%d) not registered for %s.\n",
+		    target.address, target.endpoint, name);
+		return ENOENT;
+	}
+
+	usb_log_debug2("%s %d:%d %zu(%zu).\n",
+	    name, target.address, target.endpoint, size, ep->max_packet_size);
+
+	const size_t bw = bandwidth_count_usb11(
+	    ep->speed, ep->transfer_type, size, ep->max_packet_size);
+	if (res_bw < bw) {
+		usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
+		    "but only %zu is reserved.\n",
+		    target.address, target.endpoint, name, bw, res_bw);
+		return ENOSPC;
+	}
+
+	*batch = batch_get(
+	        fun, ep, data, size, setup_data, setup_size, in, out, arg);
+	if (!*batch)
+		return ENOMEM;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Request address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] speed Speed to associate with the new default address.
+ * @param[out] address Place to write a new address.
+ * @return Error code.
+ */
+static int request_address(
+    ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	assert(address);
+
+	usb_log_debug("Address request with speed %d.\n", speed);
+	*address = device_keeper_get_free_address(&hc->manager, speed);
+	usb_log_debug("Address request with result: %d.\n", *address);
+	if (*address <= 0)
+		return *address;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Bind address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address of the device
+ * @param[in] handle Devman handle of the device driver.
+ * @return Error code.
+ */
+static int bind_address(
+  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
+	usb_device_keeper_bind(&hc->manager, address, handle);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	const bool found =
+	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
+	return found ? EOK : ENOENT;
+}
+/*----------------------------------------------------------------------------*/
+/** Release address interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Address release %d.\n", address);
+	usb_device_keeper_release(&hc->manager, address);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+static int register_endpoint(
+    ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
+    usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	const size_t size = max_packet_size;
+	usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
+	if (speed >= USB_SPEED_MAX) {
+		speed = ep_speed;
+	}
+	usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n",
+	    address, endpoint, usb_str_transfer_type(transfer_type),
+	    usb_str_direction(direction), usb_str_speed(speed),
+	    max_packet_size, interval);
+
+	return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
+	    direction, transfer_type, speed, max_packet_size, size);
+}
+/*----------------------------------------------------------------------------*/
+static int unregister_endpoint(
+    ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	usb_log_debug("Unregister endpoint %d:%d %s.\n",
+	    address, endpoint, usb_str_direction(direction));
+	return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
+	    endpoint, direction);
+}
+/*----------------------------------------------------------------------------*/
+/** Interrupt out transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int interrupt_out(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
+	    NULL, 0, NULL, callback, arg, "Interrupt OUT", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_interrupt_out(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Interrupt in transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[out] data Data destination.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int interrupt_in(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
+	    NULL, 0, callback, NULL, arg, "Interrupt IN", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_interrupt_in(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Bulk out transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int bulk_out(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_OUT, data, size,
+	    NULL, 0, NULL, callback, arg, "Bulk OUT", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_bulk_out(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Bulk in transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[out] data Data destination.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int bulk_in(
+    ddf_fun_t *fun, usb_target_t target, void *data,
+    size_t size, usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_IN, data, size,
+	    NULL, 0, callback, NULL, arg, "Bulk IN", &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_bulk_in(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Control write transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] setup_data Data to send with SETUP transfer.
+ * @param[in] setup_size Size of data to send with SETUP transfer (always 8B).
+ * @param[in] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion.
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int control_write(
+    ddf_fun_t *fun, usb_target_t target,
+    void *setup_data, size_t setup_size, void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
+	    setup_data, setup_size, NULL, callback, arg, "Control WRITE",
+	    &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
+	batch_control_write(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+/** Control read transaction interface function
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] target USB device to write to.
+ * @param[in] setup_data Data to send with SETUP packet.
+ * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).
+ * @param[out] data Source of data.
+ * @param[in] size Size of data source.
+ * @param[in] callback Function to call on transaction completion.
+ * @param[in] arg Additional for callback function.
+ * @return Error code.
+ */
+static int control_read(
+    ddf_fun_t *fun, usb_target_t target,
+    void *setup_data, size_t setup_size, void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	usb_transfer_batch_t *batch = NULL;
+	hc_t *hc = NULL;
+	int ret = setup_batch(fun, target, USB_DIRECTION_BOTH, data, size,
+	    setup_data, setup_size, callback, NULL, arg, "Control READ",
+	    &hc, &batch);
+	if (ret != EOK)
+		return ret;
+	assert(batch);
+	assert(hc);
+	batch_control_read(batch);
+	ret = hc_schedule(hc, batch);
+	if (ret != EOK) {
+		usb_transfer_batch_dispose(batch);
+	}
+	return ret;
+}
+/*----------------------------------------------------------------------------*/
+usbhc_iface_t hc_iface = {
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.find_by_address = find_by_address,
+	.release_address = release_address,
+
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.bulk_out = bulk_out,
+	.bulk_in = bulk_in,
+
+	.control_write = control_write,
+	.control_read = control_read,
+};
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/iface.h
===================================================================
--- uspace/drv/bus/usb/uhci/iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver iface
+ */
+#ifndef DRV_UHCI_IFACE_H
+#define DRV_UHCI_IFACE_H
+
+#include <usbhc_iface.h>
+
+extern usbhc_iface_t hc_iface;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/main.c
===================================================================
--- uspace/drv/bus/usb/uhci/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky, 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver initialization
+ */
+#include <ddf/driver.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "uhci.h"
+
+#define NAME "uhci"
+
+static int uhci_add_device(ddf_dev_t *device);
+/*----------------------------------------------------------------------------*/
+static driver_ops_t uhci_driver_ops = {
+	.add_device = uhci_add_device,
+};
+/*----------------------------------------------------------------------------*/
+static driver_t uhci_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_driver_ops
+};
+/*----------------------------------------------------------------------------*/
+/** Initialize a new ddf driver instance for uhci hc and hub.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+int uhci_add_device(ddf_dev_t *device)
+{
+	usb_log_debug2("uhci_add_device() called\n");
+	assert(device);
+
+	int ret = device_setup_uhci(device);
+	if (ret != EOK) {
+		usb_log_error("Failed to initialize UHCI driver: %s.\n",
+		    str_error(ret));
+		return ret;
+	}
+	usb_log_info("Controlling new UHCI device '%s'.\n", device->name);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize global driver structures (NONE).
+ *
+ * @param[in] argc Number of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS UHCI driver.\n");
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return ddf_driver_main(&uhci_driver);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/pci.c
===================================================================
--- uspace/drv/bus/usb/uhci/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2011 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 drvusbuhcihc
+ * @{
+ */
+/**
+ * @file
+ * PCI related functions needed by the UHCI driver.
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include <devman.h>
+#include <device/hw_res.h>
+
+#include <usb/debug.h>
+#include <pci_dev_iface.h>
+
+#include "pci.h"
+
+/** Get I/O address of registers and IRQ for given device.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the I/O range.
+ * @param[out] io_reg_size Size of the I/O range.
+ * @param[out] irq_no IRQ assigned to the device.
+ * @return Error code.
+ */
+int pci_get_my_registers(const ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
+{
+	assert(dev);
+	assert(io_reg_address);
+	assert(io_reg_size);
+	assert(irq_no);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	hw_resource_list_t hw_resources;
+	int rc = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (rc != EOK) {
+		async_hangup(parent_sess);
+		return rc;
+	}
+	
+	uintptr_t io_address = 0;
+	size_t io_size = 0;
+	bool io_found = false;
+	
+	int irq = 0;
+	bool irq_found = false;
+	
+	size_t i;
+	for (i = 0; i < hw_resources.count; i++) {
+		const hw_resource_t *res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			irq = res->res.interrupt.irq;
+			irq_found = true;
+			usb_log_debug2("Found interrupt: %d.\n", irq);
+			break;
+		case IO_RANGE:
+			io_address = res->res.io_range.address;
+			io_size = res->res.io_range.size;
+			usb_log_debug2("Found io: %" PRIx64" %zu.\n",
+			    res->res.io_range.address, res->res.io_range.size);
+			io_found = true;
+			break;
+		default:
+			break;
+		}
+	}
+	
+	async_hangup(parent_sess);
+	
+	if (!io_found || !irq_found)
+		return ENOENT;
+	
+	*io_reg_address = io_address;
+	*io_reg_size = io_size;
+	*irq_no = irq;
+	
+	return EOK;
+}
+
+/** Call the PCI driver with a request to enable interrupts
+ *
+ * @param[in] device Device asking for interrupts
+ * @return Error code.
+ */
+int pci_enable_interrupts(const ddf_dev_t *device)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	const bool enabled = hw_res_enable_interrupt(parent_sess);
+	async_hangup(parent_sess);
+	
+	return enabled ? EOK : EIO;
+}
+
+/** Call the PCI driver with a request to clear legacy support register
+ *
+ * @param[in] device Device asking to disable interrupts
+ * @return Error code.
+ */
+int pci_disable_legacy(const ddf_dev_t *device)
+{
+	assert(device);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	/* See UHCI design guide for these values p.45,
+	 * write all WC bits in USB legacy register */
+	const sysarg_t address = 0xc0;
+	const sysarg_t value = 0xaf00;
+	
+	async_exch_t *exch = async_exchange_begin(parent_sess);
+	
+	const int rc = async_req_3_0(exch, DEV_IFACE_ID(PCI_DEV_IFACE),
+	    IPC_M_CONFIG_SPACE_WRITE_16, address, value);
+	
+	async_exchange_end(exch);
+	async_hangup(parent_sess);
+	
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/pci.h
===================================================================
--- uspace/drv/bus/usb/uhci/pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver PCI helper functions
+ */
+#ifndef DRV_UHCI_PCI_H
+#define DRV_UHCI_PCI_H
+
+#include <ddf/driver.h>
+
+int pci_get_my_registers(const ddf_dev_t *, uintptr_t *, size_t *, int *);
+int pci_enable_interrupts(const ddf_dev_t *);
+int pci_disable_legacy(const ddf_dev_t *);
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/uhci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhci/root_hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/root_hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,76 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+/** Root hub initialization
+ * @param[in] instance RH structure to initialize
+ * @param[in] fun DDF function representing UHCI root hub
+ * @param[in] reg_addr Address of root hub status and control registers.
+ * @param[in] reg_size Size of accessible address space.
+ * @return Error code.
+ */
+int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
+{
+	int ret;
+
+	assert(fun);
+
+	ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
+	if (ret != EOK) {
+		usb_log_error("Failed to add root hub match id: %s\n",
+		    str_error(ret));
+		return ret;
+	}
+
+	/* Initialize resource structure */
+	instance->resource_list.count = 1;
+	instance->resource_list.resources = &instance->io_regs;
+
+	instance->io_regs.type = IO_RANGE;
+	instance->io_regs.res.io_range.address = reg_addr;
+	instance->io_regs.res.io_range.size = reg_size;
+	instance->io_regs.res.io_range.endianness = LITTLE_ENDIAN;
+
+	return EOK;
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/root_hub.h
===================================================================
--- uspace/drv/bus/usb/uhci/root_hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/root_hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_RH_H
+#define DRV_UHCI_RH_H
+
+#include <ddf/driver.h>
+#include <ops/hw_res.h>
+
+/** DDF support structure for uhci_rhd driver, provides I/O resources */
+typedef struct rh {
+	/** List of resources available to the root hub. */
+	hw_resource_list_t resource_list;
+	/** The only resource in the RH resource list */
+	hw_resource_t io_regs;
+} rh_t;
+
+int rh_init(
+    rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/transfer_list.c
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/transfer_list.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,241 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver transfer list implementation
+ */
+
+#include <errno.h>
+#include <usb/debug.h>
+#include <libarch/barrier.h>
+#include "transfer_list.h"
+#include "batch.h"
+
+static void transfer_list_remove_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch);
+/*----------------------------------------------------------------------------*/
+/** Initialize transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ * @param[in] name Name of the new list.
+ * @return Error code
+ *
+ * Allocates memory for internal qh_t structure.
+ */
+int transfer_list_init(transfer_list_t *instance, const char *name)
+{
+	assert(instance);
+	instance->name = name;
+	instance->queue_head = malloc32(sizeof(qh_t));
+	if (!instance->queue_head) {
+		usb_log_error("Failed to allocate queue head.\n");
+		return ENOMEM;
+	}
+	const uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
+	usb_log_debug2("Transfer list %s setup with QH: %p (%#" PRIx32" ).\n",
+	    name, instance->queue_head, queue_head_pa);
+
+	qh_init(instance->queue_head);
+	list_initialize(&instance->batch_list);
+	fibril_mutex_initialize(&instance->guard);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Dispose transfer list structures.
+ *
+ * @param[in] instance Memory place to use.
+ *
+ * Frees memory of the internal qh_t structure.
+ */
+void transfer_list_fini(transfer_list_t *instance)
+{
+	assert(instance);
+	free32(instance->queue_head);
+}
+/** Set the next list in transfer list chain.
+ *
+ * @param[in] instance List to lead.
+ * @param[in] next List to append.
+ * @return Error code
+ *
+ * Does not check whether this replaces an existing list .
+ */
+void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
+{
+	assert(instance);
+	assert(instance->queue_head);
+	assert(next);
+	/* Set queue_head.next to point to the follower */
+	qh_set_next_qh(instance->queue_head, next->queue_head);
+}
+/*----------------------------------------------------------------------------*/
+/** Add transfer batch to the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] batch Transfer batch to submit.
+ *
+ * The batch is added to the end of the list and queue.
+ */
+void transfer_list_add_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(batch);
+	usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
+
+	fibril_mutex_lock(&instance->guard);
+
+	qh_t *last_qh = NULL;
+	/* Add to the hardware queue. */
+	if (list_empty(&instance->batch_list)) {
+		/* There is nothing scheduled */
+		last_qh = instance->queue_head;
+	} else {
+		/* There is something scheduled */
+		usb_transfer_batch_t *last = usb_transfer_batch_from_link(
+		    list_last(&instance->batch_list));
+		last_qh = batch_qh(last);
+	}
+	const uint32_t pa = addr_to_phys(batch_qh(batch));
+	assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
+
+	/* Make sure all data in the batch are written */
+	write_barrier();
+
+	/* keep link */
+	batch_qh(batch)->next = last_qh->next;
+	qh_set_next_qh(last_qh, batch_qh(batch));
+
+	/* Make sure the pointer is updated */
+	write_barrier();
+
+	/* Add to the driver's list */
+	list_append(&batch->link, &instance->batch_list);
+
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
+	    batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name);
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Add completed batches to the provided list.
+ *
+ * @param[in] instance List to use.
+ * @param[in] done list to fill
+ */
+void transfer_list_remove_finished(transfer_list_t *instance, list_t *done)
+{
+	assert(instance);
+	assert(done);
+
+	fibril_mutex_lock(&instance->guard);
+	link_t *current = instance->batch_list.head.next;
+	while (current != &instance->batch_list.head) {
+		link_t * const next = current->next;
+		usb_transfer_batch_t *batch =
+		    usb_transfer_batch_from_link(current);
+
+		if (batch_is_complete(batch)) {
+			/* Save for processing */
+			transfer_list_remove_batch(instance, batch);
+			list_append(current, done);
+		}
+		current = next;
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Walk the list and finish all batches with EINTR.
+ *
+ * @param[in] instance List to use.
+ */
+void transfer_list_abort_all(transfer_list_t *instance)
+{
+	fibril_mutex_lock(&instance->guard);
+	while (!list_empty(&instance->batch_list)) {
+		link_t * const current = list_first(&instance->batch_list);
+		usb_transfer_batch_t *batch =
+		    usb_transfer_batch_from_link(current);
+		transfer_list_remove_batch(instance, batch);
+		usb_transfer_batch_finish_error(batch, EINTR);
+	}
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Remove a transfer batch from the list and queue.
+ *
+ * @param[in] instance List to use.
+ * @param[in] batch Transfer batch to remove.
+ *
+ * Does not lock the transfer list, caller is responsible for that.
+ */
+void transfer_list_remove_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch)
+{
+	assert(instance);
+	assert(instance->queue_head);
+	assert(batch);
+	assert(batch_qh(batch));
+	assert(fibril_mutex_is_locked(&instance->guard));
+
+	usb_log_debug2(
+	    "Queue %s: removing batch(%p).\n", instance->name, batch);
+
+	const char *qpos = NULL;
+	qh_t *prev_qh = NULL;
+	/* Remove from the hardware queue */
+	if (list_first(&instance->batch_list) == &batch->link) {
+		/* I'm the first one here */
+		prev_qh = instance->queue_head;
+		qpos = "FIRST";
+	} else {
+		/* The thing before me is a batch too */
+		usb_transfer_batch_t *prev =
+		    usb_transfer_batch_from_link(batch->link.prev);
+		prev_qh = batch_qh(prev);
+		qpos = "NOT FIRST";
+	}
+	assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
+	    == addr_to_phys(batch_qh(batch)));
+	prev_qh->next = batch_qh(batch)->next;
+
+	/* Make sure the pointer is updated */
+	write_barrier();
+
+	/* Remove from the batch list */
+	list_remove(&batch->link);
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) "
+	    "from %s, next: %x.\n",
+	    batch, USB_TRANSFER_BATCH_ARGS(*batch),
+	    qpos, instance->name, batch_qh(batch)->next);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/transfer_list.h
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/transfer_list.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,66 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI driver transfer list structure
+ */
+#ifndef DRV_UHCI_TRANSFER_LIST_H
+#define DRV_UHCI_TRANSFER_LIST_H
+
+#include <fibril_synch.h>
+#include <usb/host/batch.h>
+
+#include "hw_struct/queue_head.h"
+
+/** Structure maintaining both hw queue and software list
+ * of currently executed transfers
+ */
+typedef struct transfer_list {
+	/** Guard against multiple add/remove races */
+	fibril_mutex_t guard;
+	/** UHCI hw structure represeting this queue */
+	qh_t *queue_head;
+	/** Assigned name, for nicer debug output */
+	const char *name;
+	/** List of all batches in this list */
+	list_t batch_list;
+} transfer_list_t;
+
+void transfer_list_fini(transfer_list_t *instance);
+int transfer_list_init(transfer_list_t *instance, const char *name);
+void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
+void transfer_list_add_batch(
+    transfer_list_t *instance, usb_transfer_batch_t *batch);
+void transfer_list_remove_finished(transfer_list_t *instance, list_t *done);
+void transfer_list_abort_all(transfer_list_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,287 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/interrupt.h>
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "uhci.h"
+#include "iface.h"
+#include "pci.h"
+
+#include "hc.h"
+#include "root_hub.h"
+
+/** Structure representing both functions of UHCI hc, USB host controller
+ * and USB root hub */
+typedef struct uhci {
+	/** Pointer to DDF represenation of UHCI host controller */
+	ddf_fun_t *hc_fun;
+	/** Pointer to DDF represenation of UHCI root hub */
+	ddf_fun_t *rh_fun;
+
+	/** Internal driver's represenation of UHCI host controller */
+	hc_t hc;
+	/** Internal driver's represenation of UHCI root hub */
+	rh_t rh;
+} uhci_t;
+
+static inline uhci_t * dev_to_uhci(const ddf_dev_t *dev)
+{
+	assert(dev);
+	return dev->driver_data;
+}
+/*----------------------------------------------------------------------------*/
+/** IRQ handling callback, forward status from call to diver structure.
+ *
+ * @param[in] dev DDF instance of the device to use.
+ * @param[in] iid (Unused).
+ * @param[in] call Pointer to the call from kernel.
+ */
+static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
+{
+	assert(dev);
+	uhci_t *uhci = dev_to_uhci(dev);
+	if (!uhci) {
+		usb_log_error("Interrupt on not yet initialized device.\n");
+		return;
+	}
+	const uint16_t status = IPC_GET_ARG1(*call);
+	hc_interrupt(&uhci->hc, status);
+}
+/*----------------------------------------------------------------------------*/
+/** Operations supported by the HC driver */
+static ddf_dev_ops_t hc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
+};
+/*----------------------------------------------------------------------------*/
+/** Get address of the device identified by handle.
+ *
+ * @param[in] fun DDF instance of the function to use.
+ * @param[in] handle DDF handle of the driver seeking its USB address.
+ * @param[out] address Found address.
+ */
+static int usb_iface_get_address(
+    ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address)
+{
+	assert(fun);
+	usb_device_keeper_t *manager = &dev_to_uhci(fun->dev)->hc.manager;
+	usb_address_t addr = usb_device_keeper_find(manager, handle);
+
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Gets handle of the respective hc.
+ *
+ * @param[in] fun DDF function of uhci device.
+ * @param[out] handle Host cotnroller handle.
+ * @return Error code.
+ */
+static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+	ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun;
+	assert(hc_fun);
+
+	if (handle != NULL)
+		*handle = hc_fun->handle;
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** USB interface implementation used by RH */
+static usb_iface_t usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle,
+	.get_address = usb_iface_get_address
+};
+/*----------------------------------------------------------------------------*/
+/** Get root hub hw resources (I/O registers).
+ *
+ * @param[in] fun Root hub function.
+ * @return Pointer to the resource list used by the root hub.
+ */
+static hw_resource_list_t *get_resource_list(ddf_fun_t *fun)
+{
+	assert(fun);
+	rh_t *rh = fun->driver_data;
+	assert(rh);
+	return &rh->resource_list;
+}
+/*----------------------------------------------------------------------------*/
+/** Interface to provide the root hub driver with hw info */
+static hw_res_ops_t hw_res_iface = {
+	.get_resource_list = get_resource_list,
+	.enable_interrupt = NULL,
+};
+/*----------------------------------------------------------------------------*/
+/** RH function support for uhci_rhd */
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface,
+	.interfaces[HW_RES_DEV_IFACE] = &hw_res_iface
+};
+/*----------------------------------------------------------------------------*/
+/** Initialize hc and rh DDF structures and their respective drivers.
+ *
+ * @param[in] device DDF instance of the device to use.
+ *
+ * This function does all the preparatory work for hc and rh drivers:
+ *  - gets device's hw resources
+ *  - disables UHCI legacy support (PCI config space)
+ *  - attempts to enable interrupts
+ *  - registers interrupt handler
+ */
+int device_setup_uhci(ddf_dev_t *device)
+{
+	assert(device);
+	uhci_t *instance = malloc(sizeof(uhci_t));
+	if (instance == NULL) {
+		usb_log_error("Failed to allocate OHCI driver.\n");
+		return ENOMEM;
+	}
+
+#define CHECK_RET_DEST_FREE_RETURN(ret, message...) \
+if (ret != EOK) { \
+	if (instance->hc_fun) \
+		instance->hc_fun->ops = NULL; \
+		instance->hc_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->hc_fun); \
+	if (instance->rh_fun) {\
+		instance->rh_fun->ops = NULL; \
+		instance->rh_fun->driver_data = NULL; \
+		ddf_fun_destroy(instance->rh_fun); \
+	} \
+	free(instance); \
+	device->driver_data = NULL; \
+	usb_log_error(message); \
+	return ret; \
+} else (void)0
+
+	instance->rh_fun = NULL;
+	instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc");
+	int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n");
+	instance->hc_fun->ops = &hc_ops;
+	instance->hc_fun->driver_data = &instance->hc;
+
+	instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh");
+	ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
+	CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n");
+	instance->rh_fun->ops = &rh_ops;
+	instance->rh_fun->driver_data = &instance->rh;
+
+	uintptr_t reg_base = 0;
+	size_t reg_size = 0;
+	int irq = 0;
+
+	ret = pci_get_my_registers(device, &reg_base, &reg_size, &irq);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to get I/O addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
+	    (void *) reg_base, reg_size, irq);
+
+	ret = pci_disable_legacy(device);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to disable legacy USB: %s.\n", str_error(ret));
+
+	const size_t cmd_count = hc_irq_cmd_count();
+	irq_cmd_t irq_cmds[cmd_count];
+	ret =
+	    hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to generate IRQ commands: %s.\n", str_error(ret));
+
+	irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
+
+        /* Register handler to avoid interrupt lockup */
+        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
+        CHECK_RET_DEST_FREE_RETURN(ret,
+            "Failed to register interrupt handler: %s.\n", str_error(ret));
+
+	bool interrupts = false;
+	ret = pci_enable_interrupts(device);
+	if (ret != EOK) {
+		usb_log_warning("Failed to enable interrupts: %s."
+		    " Falling back to polling.\n", str_error(ret));
+	} else {
+		usb_log_debug("Hw interrupts enabled.\n");
+		interrupts = true;
+	}
+
+	ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to init uhci_hcd: %s.\n", str_error(ret));
+
+	device->driver_data = instance;
+
+#define CHECK_RET_FINI_RETURN(ret, message...) \
+if (ret != EOK) { \
+	hc_fini(&instance->hc); \
+	CHECK_RET_DEST_FREE_RETURN(ret, message); \
+	return ret; \
+} else (void)0
+
+	ret = ddf_fun_bind(instance->hc_fun);
+	CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n",
+	    str_error(ret));
+
+	ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to add UHCI to HC class: %s.\n", str_error(ret));
+
+	ret = rh_init(&instance->rh, instance->rh_fun,
+	    (uintptr_t)instance->hc.registers + 0x10, 4);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to setup UHCI root hub: %s.\n", str_error(ret));
+
+	ret = ddf_fun_bind(instance->rh_fun);
+	CHECK_RET_FINI_RETURN(ret,
+	    "Failed to register UHCI root hub: %s.\n", str_error(ret));
+
+	return EOK;
+#undef CHECK_RET_FINI_RETURN
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/uhci.h
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/uhci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,43 @@
+/*
+ * 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver main structure for both host controller and root-hub.
+ */
+#ifndef DRV_UHCI_UHCI_H
+#define DRV_UHCI_UHCI_H
+#include <ddf/driver.h>
+
+int device_setup_uhci(ddf_dev_t *device);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhci/uhci.ma
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/uhci.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,29 @@
+10 pci/ven=8086&dev=7020
+10 pci/ven=8086&dev=7112
+
+10 pci/ven=8086&dev=27c8
+10 pci/ven=8086&dev=27c9
+10 pci/ven=8086&dev=27ca
+10 pci/ven=8086&dev=27cb
+
+10 pci/ven=8086&dev=2830
+10 pci/ven=8086&dev=2831
+10 pci/ven=8086&dev=2832
+10 pci/ven=8086&dev=2834
+10 pci/ven=8086&dev=2835
+
+10 pci/ven=8086&dev=2934
+10 pci/ven=8086&dev=2935
+10 pci/ven=8086&dev=2936
+10 pci/ven=8086&dev=2937
+10 pci/ven=8086&dev=2938
+10 pci/ven=8086&dev=2939
+
+10 pci/ven=8086&dev=24c2
+10 pci/ven=8086&dev=24c4
+10 pci/ven=8086&dev=24c7
+
+10 pci/ven=8086&dev=2688
+10 pci/ven=8086&dev=2689
+10 pci/ven=8086&dev=268a
+10 pci/ven=8086&dev=268b
Index: uspace/drv/bus/usb/uhci/utils/malloc32.h
===================================================================
--- uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhci/utils/malloc32.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2010 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 drvusbuhci
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_UTILS_MALLOC32_H
+#define DRV_UHCI_UTILS_MALLOC32_H
+
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <mem.h>
+#include <as.h>
+
+#define UHCI_STRCUTURES_ALIGNMENT 16
+#define UHCI_REQUIRED_PAGE_SIZE 4096
+
+
+/** Get physical address translation
+ *
+ * @param[in] addr Virtual address to translate
+ * @return Physical address if exists, NULL otherwise.
+ */
+static inline uintptr_t addr_to_phys(void *addr)
+{
+	if (addr == NULL)
+		return 0;
+
+	uintptr_t result;
+	const int ret = as_get_physical_mapping(addr, &result);
+	if (ret != EOK)
+		return 0;
+	return (result | ((uintptr_t)addr & 0xfff));
+}
+/*----------------------------------------------------------------------------*/
+/** Physical mallocator simulator
+ *
+ * @param[in] size Size of the required memory space
+ * @return Address of the alligned and big enough memory place, NULL on failure.
+ */
+static inline void * malloc32(size_t size) {
+	/* This works only when the host has less than 4GB of memory as
+	 * physical address needs to fit into 32 bits */
+
+	/* If we need more than one page there is no guarantee that the
+	 * memory will be continuous */
+	if (size > PAGE_SIZE)
+		return NULL;
+	/* Calculate alignment to make sure the block won't cross page
+	 * boundary */
+	size_t alignment = UHCI_STRCUTURES_ALIGNMENT;
+	while (alignment < size)
+		alignment *= 2;
+	return memalign(alignment, size);
+}
+/*----------------------------------------------------------------------------*/
+/** Physical mallocator simulator
+ *
+ * @param[in] addr Address of the place allocated by malloc32
+ */
+static inline void free32(void *addr) {
+	if (!addr)
+		return;
+	free(addr);
+}
+/*----------------------------------------------------------------------------*/
+/** Create 4KB page mapping
+ *
+ * @return Address of the mapped page, NULL on failure.
+ */
+static inline void * get_page(void)
+{
+	void *free_address = as_get_mappable_page(UHCI_REQUIRED_PAGE_SIZE);
+	if (free_address == 0)
+		return NULL;
+	void *ret = as_area_create(free_address, UHCI_REQUIRED_PAGE_SIZE,
+		  AS_AREA_READ | AS_AREA_WRITE);
+	if (ret != free_address)
+		return NULL;
+	return ret;
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/Makefile
===================================================================
--- uspace/drv/bus/usb/uhcirh/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhcirh/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2010 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = uhcirh
+
+SOURCES = \
+	main.c \
+	port.c \
+	root_hub.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/uhcirh/main.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhcirh/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,182 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI root hub initialization routines
+ */
+
+#include <ddf/driver.h>
+#include <devman.h>
+#include <device/hw_res.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+#define NAME "uhcirh"
+
+static int hc_get_my_registers(const ddf_dev_t *dev,
+    uintptr_t *io_reg_address, size_t *io_reg_size);
+
+static int uhci_rh_add_device(ddf_dev_t *device);
+
+static driver_ops_t uhci_rh_driver_ops = {
+	.add_device = uhci_rh_add_device,
+};
+
+static driver_t uhci_rh_driver = {
+	.name = NAME,
+	.driver_ops = &uhci_rh_driver_ops
+};
+
+/** Initialize global driver structures (NONE).
+ *
+ * @param[in] argc Nmber of arguments in argv vector (ignored).
+ * @param[in] argv Cmdline argument vector (ignored).
+ * @return Error code.
+ *
+ * Driver debug level is set here.
+ */
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS UHCI root hub driver.\n");
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	return ddf_driver_main(&uhci_rh_driver);
+}
+
+/** Initialize a new ddf driver instance of UHCI root hub.
+ *
+ * @param[in] device DDF instance of the device to initialize.
+ * @return Error code.
+ */
+static int uhci_rh_add_device(ddf_dev_t *device)
+{
+	if (!device)
+		return EINVAL;
+
+	usb_log_debug2("uhci_rh_add_device(handle=%" PRIun ")\n",
+	    device->handle);
+
+	uintptr_t io_regs = 0;
+	size_t io_size = 0;
+	uhci_root_hub_t *rh = NULL;
+	int ret = EOK;
+
+#define CHECK_RET_FREE_RH_RETURN(ret, message...) \
+if (ret != EOK) { \
+	usb_log_error(message); \
+	if (rh) \
+		free(rh); \
+	return ret; \
+} else (void)0
+
+	ret = hc_get_my_registers(device, &io_regs, &io_size);
+	CHECK_RET_FREE_RH_RETURN(ret,
+	    "Failed to get registers from HC: %s.\n", str_error(ret));
+	usb_log_debug("I/O regs at %p (size %zuB).\n",
+	    (void *) io_regs, io_size);
+
+	rh = malloc(sizeof(uhci_root_hub_t));
+	ret = (rh == NULL) ? ENOMEM : EOK;
+	CHECK_RET_FREE_RH_RETURN(ret,
+	    "Failed to allocate rh driver instance.\n");
+
+	ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device);
+	CHECK_RET_FREE_RH_RETURN(ret,
+	    "Failed(%d) to initialize rh driver instance: %s.\n",
+	    ret, str_error(ret));
+
+	device->driver_data = rh;
+	usb_log_info("Controlling root hub '%s' (%" PRIun ").\n",
+	    device->name, device->handle);
+	return EOK;
+}
+
+/** Get address of I/O registers.
+ *
+ * @param[in] dev Device asking for the addresses.
+ * @param[out] io_reg_address Base address of the memory range.
+ * @param[out] io_reg_size Size of the memory range.
+ * @return Error code.
+ */
+int hc_get_my_registers(
+    const ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size)
+{
+	assert(dev);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	hw_resource_list_t hw_resources;
+	const int ret = hw_res_get_resource_list(parent_sess, &hw_resources);
+	if (ret != EOK) {
+		async_hangup(parent_sess);
+		return ret;
+	}
+	
+	uintptr_t io_address = 0;
+	size_t io_size = 0;
+	bool io_found = false;
+	
+	size_t i = 0;
+	for (; i < hw_resources.count; i++) {
+		hw_resource_t *res = &hw_resources.resources[i];
+		if (res->type == IO_RANGE) {
+			io_address = res->res.io_range.address;
+			io_size = res->res.io_range.size;
+			io_found = true;
+		}
+	
+	}
+	async_hangup(parent_sess);
+	
+	if (!io_found)
+		return ENOENT;
+	
+	if (io_reg_address != NULL)
+		*io_reg_address = io_address;
+	
+	if (io_reg_size != NULL)
+		*io_reg_size = io_size;
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/port.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/port.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhcirh/port.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,355 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI root hub port routines
+ */
+#include <libarch/ddi.h>  /* pio_read and pio_write */
+#include <fibril_synch.h> /* async_usleep */
+#include <errno.h>
+#include <str_error.h>
+#include <async.h>
+
+#include <usb/usb.h>    /* usb_address_t */
+#include <usb/dev/hub.h>    /* usb_hc_new_device_wrapper */
+#include <usb/debug.h>
+
+#include "port.h"
+
+static int uhci_port_check(void *port);
+static int uhci_port_reset_enable(int portno, void *arg);
+static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
+static int uhci_port_remove_device(uhci_port_t *port);
+static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
+static void uhci_port_print_status(
+    uhci_port_t *port, const port_status_t value);
+
+/** Register reading helper function.
+ *
+ * @param[in] port Structure to use.
+ * @return Error code. (Always EOK)
+ */
+static inline port_status_t uhci_port_read_status(uhci_port_t *port)
+{
+	assert(port);
+	return pio_read_16(port->address);
+}
+/*----------------------------------------------------------------------------*/
+/** Register writing helper function.
+ *
+ * @param[in] port Structure to use.
+ * @param[in] val New register value.
+ * @return Error code. (Always EOK)
+ */
+static inline void uhci_port_write_status(uhci_port_t *port, port_status_t val)
+{
+	assert(port);
+	pio_write_16(port->address, val);
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize UHCI root hub port instance.
+ *
+ * @param[in] port Memory structure to use.
+ * @param[in] address Address of I/O register.
+ * @param[in] number Port number.
+ * @param[in] usec Polling interval.
+ * @param[in] rh Pointer to ddf instance of the root hub driver.
+ * @return Error code.
+ *
+ * Creates and starts the polling fibril.
+ */
+int uhci_port_init(uhci_port_t *port,
+    port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh)
+{
+	assert(port);
+	char *id_string;
+	asprintf(&id_string, "Port (%p - %u)", port, number);
+	if (id_string == NULL) {
+		return ENOMEM;
+	}
+
+	port->id_string = id_string;
+	port->address = address;
+	port->number = number;
+	port->wait_period_usec = usec;
+	port->attached_device = 0;
+	port->rh = rh;
+
+	int ret =
+	    usb_hc_connection_initialize_from_device(&port->hc_connection, rh);
+	if (ret != EOK) {
+		usb_log_error("%s: failed to initialize connection to HC.",
+		    port->id_string);
+		free(id_string);
+		return ret;
+	}
+
+	port->checker = fibril_create(uhci_port_check, port);
+	if (port->checker == 0) {
+		usb_log_error("%s: failed to create polling fibril.",
+		    port->id_string);
+		free(id_string);
+		return ENOMEM;
+	}
+
+	fibril_add_ready(port->checker);
+	usb_log_debug("%s: Started polling fibril (%" PRIun ").\n",
+	    port->id_string, port->checker);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Cleanup UHCI root hub port instance.
+ *
+ * @param[in] port Memory structure to use.
+ *
+ * Stops the polling fibril.
+ */
+void uhci_port_fini(uhci_port_t *port)
+{
+	assert(port);
+	free(port->id_string);
+	// TODO: Kill fibril here
+	return;
+}
+/*----------------------------------------------------------------------------*/
+/** Periodically checks port status and reports new devices.
+ *
+ * @param[in] port Port structure to use.
+ * @return Error code.
+ */
+int uhci_port_check(void *port)
+{
+	uhci_port_t *instance = port;
+	assert(instance);
+
+	while (1) {
+		async_usleep(instance->wait_period_usec);
+
+		/* Read register value */
+		const port_status_t port_status =
+		    uhci_port_read_status(instance);
+
+		/* Print the value if it's interesting */
+		if (port_status & ~STATUS_ALWAYS_ONE)
+			uhci_port_print_status(instance, port_status);
+
+		if ((port_status & STATUS_CONNECTED_CHANGED) == 0)
+			continue;
+
+		usb_log_debug("%s: Connected change detected: %x.\n",
+		    instance->id_string, port_status);
+
+		/* Remove any old device */
+		if (instance->attached_device) {
+			usb_log_debug2("%s: Removing device.\n",
+			    instance->id_string);
+			uhci_port_remove_device(instance);
+		}
+
+		int ret =
+		    usb_hc_connection_open(&instance->hc_connection);
+		if (ret != EOK) {
+			usb_log_error("%s: Failed to connect to HC.",
+			    instance->id_string);
+			continue;
+		}
+
+		if ((port_status & STATUS_CONNECTED) != 0) {
+			/* New device */
+			const usb_speed_t speed =
+			    ((port_status & STATUS_LOW_SPEED) != 0) ?
+			    USB_SPEED_LOW : USB_SPEED_FULL;
+			uhci_port_new_device(instance, speed);
+		} else {
+			/* Write one to WC bits, to ack changes */
+			uhci_port_write_status(instance, port_status);
+			usb_log_debug("%s: status change ACK.\n",
+			    instance->id_string);
+		}
+
+		ret = usb_hc_connection_close(&instance->hc_connection);
+		if (ret != EOK) {
+			usb_log_error("%s: Failed to disconnect.",
+			    instance->id_string);
+		}
+	}
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Callback for enabling port during adding a new device.
+ *
+ * @param portno Port number (unused).
+ * @param arg Pointer to uhci_port_t of port with the new device.
+ * @return Error code.
+ *
+ * Resets and enables the ub port.
+ */
+int uhci_port_reset_enable(int portno, void *arg)
+{
+	uhci_port_t *port = arg;
+	assert(port);
+
+	usb_log_debug2("%s: new_device_enable_port.\n", port->id_string);
+
+	/*
+	 * Resets from root ports should be nominally 50ms (USB spec 7.1.7.3)
+	 */
+	{
+		usb_log_debug("%s: Reset Signal start.\n", port->id_string);
+		port_status_t port_status = uhci_port_read_status(port);
+		port_status |= STATUS_IN_RESET;
+		uhci_port_write_status(port, port_status);
+		async_usleep(50000);
+		port_status = uhci_port_read_status(port);
+		port_status &= ~STATUS_IN_RESET;
+		uhci_port_write_status(port, port_status);
+		while (uhci_port_read_status(port) & STATUS_IN_RESET);
+	}
+	/* PIO delay, should not be longer than 3ms as the device might
+	 * enter suspend state. */
+	udelay(10);
+	/* Enable the port. */
+	uhci_port_set_enabled(port, true);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Initialize and report connected device.
+ *
+ * @param[in] port Port structure to use.
+ * @param[in] speed Detected speed.
+ * @return Error code.
+ *
+ * Uses libUSB function to do the actual work.
+ */
+int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed)
+{
+	assert(port);
+	assert(usb_hc_connection_is_opened(&port->hc_connection));
+
+	usb_log_debug("%s: Detected new device.\n", port->id_string);
+
+	int ret, count = 0;
+	usb_address_t dev_addr;
+	do {
+		ret = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
+		    speed, uhci_port_reset_enable, port->number, port,
+		    &dev_addr, &port->attached_device, NULL, NULL, NULL);
+	} while (ret != EOK && ++count < 4);
+
+	if (ret != EOK) {
+		usb_log_error("%s: Failed(%d) to add device: %s.\n",
+		    port->id_string, ret, str_error(ret));
+		uhci_port_set_enabled(port, false);
+		return ret;
+	}
+
+	usb_log_info("New device at port %u, address %d (handle %" PRIun ").\n",
+	    port->number, dev_addr, port->attached_device);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Remove device.
+ *
+ * @param[in] port Memory structure to use.
+ * @return Error code.
+ *
+ * Does not work, DDF does not support device removal.
+ * Does not even free used USB address (it would be dangerous if tis driver
+ * is still running).
+ */
+int uhci_port_remove_device(uhci_port_t *port)
+{
+	usb_log_error("%s: Don't know how to remove device %" PRIun ".\n",
+	    port->id_string, port->attached_device);
+	port->attached_device = 0;
+	return ENOTSUP;
+}
+/*----------------------------------------------------------------------------*/
+/** Enable or disable root hub port.
+ *
+ * @param[in] port Port structure to use.
+ * @param[in] enabled Port status to set.
+ * @return Error code. (Always EOK)
+ */
+int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
+{
+	assert(port);
+
+	/* Read register value */
+	port_status_t port_status = uhci_port_read_status(port);
+
+	/* Set enabled bit */
+	if (enabled) {
+		port_status |= STATUS_ENABLED;
+	} else {
+		port_status &= ~STATUS_ENABLED;
+	}
+
+	/* Write new value. */
+	uhci_port_write_status(port, port_status);
+
+	/* Wait for port to become enabled */
+	do {
+		port_status = uhci_port_read_status(port);
+	} while ((port_status & STATUS_CONNECTED) &&
+	    !(port_status & STATUS_ENABLED));
+
+	usb_log_debug("%s: %sabled port.\n",
+		port->id_string, enabled ? "En" : "Dis");
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Print the port status value in a human friendly way
+ *
+ * @param[in] port Port structure to use.
+ * @param[in] value Port register value to print.
+ * @return Error code. (Always EOK)
+ */
+void uhci_port_print_status(uhci_port_t *port, const port_status_t value)
+{
+	assert(port);
+	usb_log_debug2("%s Port status(%#x):%s%s%s%s%s%s%s%s%s%s%s.\n",
+	    port->id_string, value,
+	    (value & STATUS_SUSPEND) ? " SUSPENDED," : "",
+	    (value & STATUS_RESUME) ? " IN RESUME," : "",
+	    (value & STATUS_IN_RESET) ? " IN RESET," : "",
+	    (value & STATUS_LINE_D_MINUS) ? " VD-," : "",
+	    (value & STATUS_LINE_D_PLUS) ? " VD+," : "",
+	    (value & STATUS_LOW_SPEED) ? " LOWSPEED," : "",
+	    (value & STATUS_ENABLED_CHANGED) ? " ENABLED-CHANGE," : "",
+	    (value & STATUS_ENABLED) ? " ENABLED," : "",
+	    (value & STATUS_CONNECTED_CHANGED) ? " CONNECTED-CHANGE," : "",
+	    (value & STATUS_CONNECTED) ? " CONNECTED," : "",
+	    (value & STATUS_ALWAYS_ONE) ? " ALWAYS ONE" : " ERR: NO ALWAYS ONE"
+	);
+}
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/port.h
===================================================================
--- uspace/drv/bus/usb/uhcirh/port.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhcirh/port.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,77 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI root hub port routines
+ */
+#ifndef DRV_UHCI_PORT_H
+#define DRV_UHCI_PORT_H
+
+#include <stdint.h>
+#include <fibril.h>
+#include <ddf/driver.h>
+#include <usb/hc.h> /* usb_hc_connection_t */
+
+typedef uint16_t port_status_t;
+#define STATUS_CONNECTED         (1 << 0)
+#define STATUS_CONNECTED_CHANGED (1 << 1)
+#define STATUS_ENABLED           (1 << 2)
+#define STATUS_ENABLED_CHANGED   (1 << 3)
+#define STATUS_LINE_D_PLUS       (1 << 4)
+#define STATUS_LINE_D_MINUS      (1 << 5)
+#define STATUS_RESUME            (1 << 6)
+#define STATUS_ALWAYS_ONE        (1 << 7)
+
+#define STATUS_LOW_SPEED (1 <<  8)
+#define STATUS_IN_RESET  (1 <<  9)
+#define STATUS_SUSPEND   (1 << 12)
+
+/** UHCI port structure */
+typedef struct uhci_port {
+	const char *id_string;
+	port_status_t *address;
+	unsigned number;
+	unsigned wait_period_usec;
+	usb_hc_connection_t hc_connection;
+	ddf_dev_t *rh;
+	devman_handle_t attached_device;
+	fid_t checker;
+} uhci_port_t;
+
+int uhci_port_init(
+    uhci_port_t *port, port_status_t *address, unsigned number,
+    unsigned usec, ddf_dev_t *rh);
+
+void uhci_port_fini(uhci_port_t *port);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhcirh/root_hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhcirh/root_hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,97 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI root hub driver
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <ddi.h>
+#include <usb/debug.h>
+
+#include "root_hub.h"
+
+/** Initialize UHCI root hub instance.
+ *
+ * @param[in] instance Driver memory structure to use.
+ * @param[in] addr Address of I/O registers.
+ * @param[in] size Size of available I/O space.
+ * @param[in] rh Pointer to DDF instance of the root hub driver.
+ * @return Error code.
+ */
+int uhci_root_hub_init(
+  uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh)
+{
+	assert(instance);
+	assert(rh);
+
+	/* Allow access to root hub port registers */
+	assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);
+	port_status_t *regs;
+	int ret = pio_enable(addr, size, (void**)&regs);
+	if (ret < 0) {
+		usb_log_error(
+		    "Failed(%d) to gain access to port registers at %p: %s.\n",
+		    ret, regs, str_error(ret));
+		return ret;
+	}
+
+	/* Initialize root hub ports */
+	unsigned i = 0;
+	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
+		ret = uhci_port_init(
+		    &instance->ports[i], &regs[i], i, ROOT_HUB_WAIT_USEC, rh);
+		if (ret != EOK) {
+			unsigned j = 0;
+			for (;j < i; ++j)
+				uhci_port_fini(&instance->ports[j]);
+			return ret;
+		}
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Cleanup UHCI root hub instance.
+ *
+ * @param[in] instance Root hub structure to use.
+ */
+void uhci_root_hub_fini(uhci_root_hub_t* instance)
+{
+	assert(instance);
+	unsigned i = 0;
+	for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) {
+		uhci_port_fini(&instance->ports[i]);
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/root_hub.h
===================================================================
--- uspace/drv/bus/usb/uhcirh/root_hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhcirh/root_hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,57 @@
+/*
+ * 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 drvusbuhcirh
+ * @{
+ */
+/** @file
+ * @brief UHCI driver
+ */
+#ifndef DRV_UHCI_ROOT_HUB_H
+#define DRV_UHCI_ROOT_HUB_H
+
+#include <ddf/driver.h>
+
+#include "port.h"
+
+#define UHCI_ROOT_HUB_PORT_COUNT 2
+#define ROOT_HUB_WAIT_USEC 250000 /* 250 miliseconds */
+
+/** UHCI root hub drvier structure */
+typedef struct root_hub {
+	/** Ports provided by the hub */
+	uhci_port_t ports[UHCI_ROOT_HUB_PORT_COUNT];
+} uhci_root_hub_t;
+
+int uhci_root_hub_init(
+    uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh);
+
+void uhci_root_hub_fini(uhci_root_hub_t *instance);
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/uhcirh/uhcirh.ma
===================================================================
--- uspace/drv/bus/usb/uhcirh/uhcirh.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/uhcirh/uhcirh.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 usb&uhci&root-hub
Index: uspace/drv/bus/usb/usbflbk/Makefile
===================================================================
--- uspace/drv/bus/usb/usbflbk/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbflbk/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbflbk
+
+SOURCES = \
+	main.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbflbk/main.c
===================================================================
--- uspace/drv/bus/usb/usbflbk/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbflbk/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011 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 drvusbfallback
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB fallback driver.
+ */
+#include <usb/dev/driver.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+
+#define NAME "usbflbk"
+
+/** Callback when new device is attached and recognized by DDF.
+ *
+ * @param dev Representation of a generic DDF device.
+ * @return Error code.
+ */
+static int usbfallback_add_device(usb_device_t *dev)
+{
+	int rc;
+	const char *fun_name = "ctl";
+
+	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
+	    fun_name);
+	if (ctl_fun == NULL) {
+		usb_log_error("Failed to create control function.\n");
+		return ENOMEM;
+	}
+	rc = ddf_fun_bind(ctl_fun);
+	if (rc != EOK) {
+		usb_log_error("Failed to bind control function: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	usb_log_info("Pretending to control %s `%s'" \
+	    " (node `%s', handle %" PRIun ").\n",
+	    dev->interface_no < 0 ? "device" : "interface",
+	    dev->ddf_dev->name, fun_name, dev->ddf_dev->handle);
+
+	return EOK;
+}
+
+/** USB fallback driver ops. */
+static usb_driver_ops_t usbfallback_driver_ops = {
+	.add_device = usbfallback_add_device,
+};
+
+/** USB fallback driver. */
+static usb_driver_t usbfallback_driver = {
+	.name = NAME,
+	.ops = &usbfallback_driver_ops,
+	.endpoints = NULL
+};
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&usbfallback_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbflbk/usbflbk.ma
===================================================================
--- uspace/drv/bus/usb/usbflbk/usbflbk.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbflbk/usbflbk.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,2 @@
+10 usb&fallback
+10 usb&interface&fallback
Index: uspace/drv/bus/usb/usbhid/Makefile
===================================================================
--- uspace/drv/bus/usb/usbhid/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2010-2011 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I. \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbhid
+
+SUBDRIVER_SOURCES = \
+	kbd/conv.c \
+	kbd/kbddev.c \
+	kbd/kbdrepeat.c \
+	mouse/mousedev.c \
+	multimedia/multimedia.c \
+	multimedia/keymap.c
+
+SOURCES = \
+	main.c \
+	usbhid.c \
+	subdrivers.c \
+	generic/hiddev.c \
+	$(SUBDRIVER_SOURCES)
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID driver API.
+ */
+
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <errno.h>
+#include <str_error.h>
+#include <bool.h>
+
+#include <usbhid_iface.h>
+
+#include "hiddev.h"
+#include "usbhid.h"
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.flags = 0
+};
+
+const char *HID_GENERIC_FUN_NAME = "hid";
+const char *HID_GENERIC_CLASS_NAME = "hid";
+
+/*----------------------------------------------------------------------------*/
+
+static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun);
+
+static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
+    size_t size, size_t *act_size, int *event_nr, unsigned int flags);
+
+static int usb_generic_hid_client_connected(ddf_fun_t *fun);
+
+static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun);
+
+static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
+    size_t size, size_t *actual_size);
+
+/*----------------------------------------------------------------------------*/
+
+static usbhid_iface_t usb_generic_iface = {
+	.get_event = usb_generic_hid_get_event,
+	.get_event_length = usb_generic_hid_get_event_length,
+	.get_report_descriptor_length = usb_generic_get_report_descriptor_length,
+	.get_report_descriptor = usb_generic_get_report_descriptor
+};
+
+static ddf_dev_ops_t usb_generic_hid_ops = {
+	.interfaces[USBHID_DEV_IFACE] = &usb_generic_iface,
+	.open = usb_generic_hid_client_connected
+};
+
+/*----------------------------------------------------------------------------*/
+
+static size_t usb_generic_hid_get_event_length(ddf_fun_t *fun)
+{
+	usb_log_debug2("Generic HID: Get event length (fun: %p, "
+	    "fun->driver_data: %p.\n", fun, fun->driver_data);
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		return 0;
+	}
+
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
+	    hid_dev, hid_dev->max_input_report_size);
+	
+	return hid_dev->max_input_report_size;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_get_event(ddf_fun_t *fun, uint8_t *buffer, 
+    size_t size, size_t *act_size, int *event_nr, unsigned int flags)
+{
+	usb_log_debug2("Generic HID: Get event.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL || buffer == NULL
+	    || act_size == NULL || event_nr == NULL) {
+		usb_log_debug("No function");
+		return EINVAL;
+	}
+
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	if (hid_dev->input_report_size > size) {
+		usb_log_debug("input_report_size > size (%zu, %zu)\n", 
+		    hid_dev->input_report_size, size);
+		return EINVAL;	// TODO: other error code
+	}
+	
+	/*! @todo This should probably be somehow atomic. */
+	memcpy(buffer, hid_dev->input_report, 
+	    hid_dev->input_report_size);
+	*act_size = hid_dev->input_report_size;
+	*event_nr = usb_hid_report_number(hid_dev);
+	
+	usb_log_debug2("OK\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static size_t usb_generic_get_report_descriptor_length(ddf_fun_t *fun)
+{
+	usb_log_debug("Generic HID: Get report descriptor length.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		usb_log_debug("No function");
+		return EINVAL;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	usb_log_debug2("hid_dev->report_desc_size = %zu\n", 
+	    hid_dev->report_desc_size);
+	
+	return hid_dev->report_desc_size;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_get_report_descriptor(ddf_fun_t *fun, uint8_t *desc, 
+    size_t size, size_t *actual_size)
+{
+	usb_log_debug2("Generic HID: Get report descriptor.\n");
+	
+	if (fun == NULL || fun->driver_data == NULL) {
+		usb_log_debug("No function");
+		return EINVAL;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
+	
+	if (hid_dev->report_desc_size > size) {
+		return EINVAL;
+	}
+	
+	memcpy(desc, hid_dev->report_desc, hid_dev->report_desc_size);
+	*actual_size = hid_dev->report_desc_size;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_client_connected(ddf_fun_t *fun)
+{
+	usb_log_debug("Generic HID: Client connected.\n");
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)
+{	
+	/* Create the exposed function. */
+	/** @todo Generate numbers for the devices? */
+	usb_log_debug("Creating DDF function %s...\n", HID_GENERIC_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_GENERIC_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	fun->ops = &usb_generic_hid_ops;
+	fun->driver_data = hid_dev;
+
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
+{
+	if (hid_dev == NULL) {
+		return EINVAL;
+	}
+	
+	return usb_generic_hid_create_function(hid_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev, void *data)
+{
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/generic/hiddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/generic/hiddev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID driver API.
+ */
+
+#ifndef USB_HID_HIDDDEV_H_
+#define USB_HID_HIDDDEV_H_
+
+#include <usb/dev/driver.h>
+
+struct usb_hid_dev;
+
+usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
+
+const char *HID_GENERIC_FUN_NAME;
+const char *HID_GENERIC_CLASS_NAME;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_generic_hid_init(struct usb_hid_dev *hid_dev, void **data);
+
+bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev, void *data);
+
+#endif // USB_HID_HIDDDEV_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/conv.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/conv.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/kbd/conv.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB scancode parser.
+ */
+
+#include <io/keycode.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include "conv.h"
+
+/**
+ * Mapping between USB HID key codes (from HID Usage Tables) and corresponding
+ * HelenOS key codes.
+ */
+static int scanmap_simple[255] = {
+
+//	[0x29] = KC_BACKTICK,
+
+//	[0x02] = KC_1,
+//	[0x03] = KC_2,
+	[0x04] = KC_A,
+	[0x05] = KC_B,
+	[0x06] = KC_C,
+	[0x07] = KC_D,
+	[0x08] = KC_E,
+	[0x09] = KC_F,
+	[0x0a] = KC_G,
+	[0x0b] = KC_H,
+	[0x0c] = KC_I,
+	[0x0d] = KC_J,
+	[0x0e] = KC_K,
+	[0x0f] = KC_L,
+	[0x10] = KC_M,
+	[0x11] = KC_N,
+	[0x12] = KC_O,
+	[0x13] = KC_P,
+	[0x14] = KC_Q,
+	[0x15] = KC_R,
+	[0x16] = KC_S,
+	[0x17] = KC_T,
+	[0x18] = KC_U,
+	[0x19] = KC_V,
+	[0x1a] = KC_W,
+	[0x1b] = KC_X,
+	[0x1c] = KC_Y,
+	[0x1d] = KC_Z,
+
+	[0x1e] = KC_1,
+	[0x1f] = KC_2,
+	[0x20] = KC_3,
+	[0x21] = KC_4,
+	[0x22] = KC_5,
+	[0x23] = KC_6,
+	[0x24] = KC_7,
+	[0x25] = KC_8,
+	[0x26] = KC_9,
+	[0x27] = KC_0,
+	
+	[0x28] = KC_ENTER,
+	[0x29] = KC_ESCAPE,
+	[0x2a] = KC_BACKSPACE,
+	[0x2b] = KC_TAB,
+	[0x2c] = KC_SPACE,
+
+	[0x2d] = KC_MINUS,  // same as DASH? (- or _)
+	[0x2e] = KC_EQUALS,
+	[0x2f] = KC_LBRACKET,
+	[0x30] = KC_RBRACKET,
+	[0x31] = KC_BACKSLASH,
+	//[0x32] = KC_,	// TODO: HASH??? maybe same as 0x31 - backslash
+	[0x32] = KC_BACKSLASH,
+	[0x33] = KC_SEMICOLON,
+	[0x34] = KC_QUOTE,  // same as APOSTROPHE? (')
+	[0x35] = KC_BACKTICK,  // same as GRAVE ACCENT?? (`)
+	[0x36] = KC_COMMA,
+	[0x37] = KC_PERIOD,
+	[0x38] = KC_SLASH,
+
+	[0x39] = KC_CAPS_LOCK,
+	
+	[0x3a] = KC_F1,
+	[0x3b] = KC_F2,
+	[0x3c] = KC_F3,
+	[0x3d] = KC_F4,
+	[0x3e] = KC_F5,
+	[0x3f] = KC_F6,
+	[0x40] = KC_F7,
+	[0x41] = KC_F8,
+	[0x42] = KC_F9,
+	[0x43] = KC_F10,
+	[0x44] = KC_F11,
+	[0x45] = KC_F12,
+	
+	[0x46] = KC_PRTSCR,
+	[0x47] = KC_SCROLL_LOCK,
+	[0x48] = KC_PAUSE,
+	[0x49] = KC_INSERT,
+	[0x4a] = KC_HOME,
+	[0x4b] = KC_PAGE_UP,
+	[0x4c] = KC_DELETE,
+	[0x4d] = KC_END,
+	[0x4e] = KC_PAGE_DOWN,
+	[0x4f] = KC_RIGHT,
+	[0x50] = KC_LEFT,
+	[0x51] = KC_DOWN,
+	[0x52] = KC_UP,
+	
+	//[0x64] = // some funny key
+	
+	[0xe0] = KC_LCTRL,
+	[0xe1] = KC_LSHIFT,
+	[0xe2] = KC_LALT,
+	//[0xe3] = KC_L	// TODO: left GUI
+	[0xe4] = KC_RCTRL,
+	[0xe5] = KC_RSHIFT,
+	[0xe6] = KC_RALT,
+	//[0xe7] = KC_R	// TODO: right GUI
+	
+	[0x53] = KC_NUM_LOCK,
+	[0x54] = KC_NSLASH,
+	[0x55] = KC_NTIMES,
+	[0x56] = KC_NMINUS,
+	[0x57] = KC_NPLUS,
+	[0x58] = KC_NENTER,
+	[0x59] = KC_N1,
+	[0x5a] = KC_N2,
+	[0x5b] = KC_N3,
+	[0x5c] = KC_N4,
+	[0x5d] = KC_N5,
+	[0x5e] = KC_N6,
+	[0x5f] = KC_N7,
+	[0x60] = KC_N8,
+	[0x61] = KC_N9,
+	[0x62] = KC_N0,
+	[0x63] = KC_NPERIOD
+	
+};
+
+/**
+ * Translate USB HID key codes (from HID Usage Tables) to generic key codes
+ * recognized by HelenOS.
+ *
+ * @param scancode USB HID key code (from HID Usage Tables).
+ * 
+ * @retval HelenOS key code corresponding to the given USB HID key code.
+ */
+unsigned int usbhid_parse_scancode(int scancode)
+{
+	unsigned int key;
+	int *map = scanmap_simple;
+	size_t map_length = sizeof(scanmap_simple) / sizeof(int);
+
+	if ((scancode < 0) || ((size_t) scancode >= map_length))
+		return -1;
+
+	key = map[scancode];
+	
+	return key;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/conv.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/conv.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/kbd/conv.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB scancode parser.
+ */
+
+#ifndef USB_HID_CONV_H_
+#define USB_HID_CONV_H_
+
+unsigned int usbhid_parse_scancode(int scancode);
+
+#endif /* USB_HID_CONV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,865 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID keyboard device structure and API.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+
+#include <io/keycode.h>
+#include <io/console.h>
+#include <ipc/kbdev.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <fibril.h>
+#include <fibril_synch.h>
+
+#include <ddf/log.h>
+
+#include <usb/usb.h>
+#include <usb/dev/dp.h>
+#include <usb/dev/request.h>
+#include <usb/hid/hid.h>
+#include <usb/dev/pipes.h>
+#include <usb/debug.h>
+#include <usb/hid/hidparser.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/usages/core.h>
+#include <usb/hid/request.h>
+#include <usb/hid/hidreport.h>
+#include <usb/hid/usages/led.h>
+
+#include <usb/dev/driver.h>
+
+#include "kbddev.h"
+
+#include "conv.h"
+#include "kbdrepeat.h"
+
+#include "../usbhid.h"
+
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
+
+/*----------------------------------------------------------------------------*/
+
+static const unsigned DEFAULT_ACTIVE_MODS = KM_NUM_LOCK;
+
+static const uint8_t ERROR_ROLLOVER = 1;
+
+/** Default idle rate for keyboards. */
+static const uint8_t IDLE_RATE = 0;
+
+/** Delay before a pressed key starts auto-repeating. */
+static const unsigned int DEFAULT_DELAY_BEFORE_FIRST_REPEAT = 500 * 1000;
+
+/** Delay between two repeats of a pressed key when auto-repeating. */
+static const unsigned int DEFAULT_REPEAT_DELAY = 50 * 1000;
+
+/*----------------------------------------------------------------------------*/
+
+/** Keyboard polling endpoint description for boot protocol class. */
+usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_KEYBOARD,
+	.flags = 0
+};
+
+const char *HID_KBD_FUN_NAME = "keyboard";
+const char *HID_KBD_CATEGORY_NAME = "keyboard";
+
+static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev);
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE = 63
+};
+
+static const uint8_t USB_KBD_BOOT_REPORT_DESCRIPTOR[
+    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE] = {
+        0x05, 0x01,  // Usage Page (Generic Desktop),
+        0x09, 0x06,  // Usage (Keyboard),
+        0xA1, 0x01,  // Collection (Application),
+        0x75, 0x01,  //   Report Size (1),
+        0x95, 0x08,  //   Report Count (8),       
+        0x05, 0x07,  //   Usage Page (Key Codes);
+        0x19, 0xE0,  //   Usage Minimum (224),
+        0x29, 0xE7,  //   Usage Maximum (231),
+        0x15, 0x00,  //   Logical Minimum (0),
+        0x25, 0x01,  //   Logical Maximum (1),
+        0x81, 0x02,  //   Input (Data, Variable, Absolute),   ; Modifier byte
+	0x95, 0x01,  //   Report Count (1),
+        0x75, 0x08,  //   Report Size (8),
+        0x81, 0x01,  //   Input (Constant),                   ; Reserved byte
+        0x95, 0x05,  //   Report Count (5),
+        0x75, 0x01,  //   Report Size (1),
+        0x05, 0x08,  //   Usage Page (Page# for LEDs),
+        0x19, 0x01,  //   Usage Minimum (1),
+        0x29, 0x05,  //   Usage Maxmimum (5),
+        0x91, 0x02,  //   Output (Data, Variable, Absolute),  ; LED report
+        0x95, 0x01,  //   Report Count (1),
+        0x75, 0x03,  //   Report Size (3),
+        0x91, 0x01,  //   Output (Constant),              ; LED report padding
+        0x95, 0x06,  //   Report Count (6),
+        0x75, 0x08,  //   Report Size (8),
+        0x15, 0x00,  //   Logical Minimum (0),
+        0x25, 0xff,  //   Logical Maximum (255),
+        0x05, 0x07,  //   Usage Page (Key Codes),
+        0x19, 0x00,  //   Usage Minimum (0),
+        0x29, 0xff,  //   Usage Maximum (255),
+        0x81, 0x00,  //   Input (Data, Array),            ; Key arrays (6 bytes)
+        0xC0           // End Collection
+
+};
+
+/*----------------------------------------------------------------------------*/
+
+typedef enum usb_kbd_flags {
+	USB_KBD_STATUS_UNINITIALIZED = 0,
+	USB_KBD_STATUS_INITIALIZED = 1,
+	USB_KBD_STATUS_TO_DESTROY = -1
+} usb_kbd_flags;
+
+/*----------------------------------------------------------------------------*/
+/* IPC method handler                                                         */
+/*----------------------------------------------------------------------------*/
+
+static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+
+/**
+ * Default handler for IPC methods not handled by DDF.
+ *
+ * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
+ * assumes the caller is the console and thus it stores IPC phone to it for 
+ * later use by the driver to notify about key events.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+static void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	int callback;
+	
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)fun->driver_data;
+	if (kbd_dev == NULL) {
+		usb_log_debug("default_connection_handler: "
+		    "Missing parameter.\n");
+		async_answer_0(icallid, EINVAL);
+		return;
+	}
+
+	switch (method) {
+	case IPC_M_CONNECT_TO_ME:
+		callback = IPC_GET_ARG5(*icall);
+
+		if (kbd_dev->console_phone != -1) {
+			usb_log_debug("default_connection_handler: "
+			    "console phone already set\n");
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		kbd_dev->console_phone = callback;
+		
+		usb_log_debug("default_connection_handler: OK\n");
+		async_answer_0(icallid, EOK);
+		break;
+	case KBDEV_SET_IND:
+		kbd_dev->mods = IPC_GET_ARG1(*icall);
+		usb_kbd_set_led(kbd_dev->hid_dev, kbd_dev);
+		async_answer_0(icallid, EOK);
+		break;
+	default:
+		usb_log_debug("default_connection_handler: Wrong function.\n");
+		async_answer_0(icallid, EINVAL);
+		break;
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/* Key processing functions                                                   */
+/*----------------------------------------------------------------------------*/
+/**
+ * Handles turning of LED lights on and off.
+ *
+ * As with most other keyboards, the LED indicators in USB keyboards are
+ * driven by software. When state of some modifier changes, the input server
+ * will call us and tell us to update the LED state and what the new state
+ * should be.
+ *
+ * This functions sets the LED lights according to current settings of modifiers
+ * kept in the keyboard device structure.
+ *
+ * @param kbd_dev Keyboard device structure.
+ */
+static void usb_kbd_set_led(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev) 
+{
+	if (kbd_dev->output_size == 0) {
+		return;
+	}
+
+	/* Reset the LED data. */
+	memset(kbd_dev->led_data, 0, kbd_dev->led_output_size * sizeof(int32_t));
+	usb_log_debug("Creating output report:\n");
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, kbd_dev->led_path, 
+	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+	    USB_HID_REPORT_TYPE_OUTPUT);
+	
+	while (field != NULL) {
+		
+		if ((field->usage == USB_HID_LED_NUM_LOCK) 
+		    && (kbd_dev->mods & KM_NUM_LOCK)){
+			field->value = 1;
+		}
+
+		if ((field->usage == USB_HID_LED_CAPS_LOCK) 
+		    && (kbd_dev->mods & KM_CAPS_LOCK)){
+			field->value = 1;
+		}
+
+		if ((field->usage == USB_HID_LED_SCROLL_LOCK) 
+		    && (kbd_dev->mods & KM_SCROLL_LOCK)){
+			field->value = 1;
+		}
+		
+		field = usb_hid_report_get_sibling(hid_dev->report, field,
+		    kbd_dev->led_path,  
+	    	USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+			USB_HID_REPORT_TYPE_OUTPUT);
+	}
+	
+	// TODO: what about the Report ID?
+	int rc = usb_hid_report_output_translate(hid_dev->report, 0,
+	    kbd_dev->output_buffer, kbd_dev->output_size);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error translating LED output to output report"
+		    ".\n");
+		return;
+	}
+	
+	usb_log_debug("Output report buffer: %s\n", 
+	    usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size, 
+	        0));
+	
+	usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
+	    kbd_dev->output_buffer, kbd_dev->output_size);
+}
+
+/*----------------------------------------------------------------------------*/
+/** Send key event.
+ *
+ * @param kbd_dev Keyboard device structure.
+ * @param type Type of the event (press / release). Recognized values:
+ *             KEY_PRESS, KEY_RELEASE
+ * @param key Key code
+ */
+void usb_kbd_push_ev(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev, int type, 
+    unsigned int key)
+{
+	usb_log_debug2("Sending kbdev event %d/%d to the console\n", type, key);
+	if (kbd_dev->console_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
+	
+	async_obsolete_msg_2(kbd_dev->console_phone, KBDEV_EVENT, type, key);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static inline int usb_kbd_is_lock(unsigned int key_code) 
+{
+	return (key_code == KC_NUM_LOCK
+	    || key_code == KC_SCROLL_LOCK
+	    || key_code == KC_CAPS_LOCK);
+}
+
+static size_t find_in_array_int32(int32_t val, int32_t *arr, size_t arr_size)
+{
+	for (size_t i = 0; i < arr_size; i++) {
+		if (arr[i] == val) {
+			return i;
+		}
+	}
+
+	return (size_t) -1;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Checks if some keys were pressed or released and generates key events.
+ *
+ * An event is created only when key is pressed or released. Besides handling
+ * the events (usb_kbd_push_ev()), the auto-repeat fibril is notified about
+ * key presses and releases (see usb_kbd_repeat_start() and 
+ * usb_kbd_repeat_stop()).
+ *
+ * @param kbd_dev Keyboard device structure.
+ * @param key_codes Parsed keyboard report - codes of currently pressed keys 
+ *                  according to HID Usage Tables.
+ * @param count Number of key codes in report (size of the report).
+ *
+ * @sa usb_kbd_push_ev(), usb_kbd_repeat_start(), usb_kbd_repeat_stop()
+ */
+static void usb_kbd_check_key_changes(usb_hid_dev_t *hid_dev, 
+    usb_kbd_t *kbd_dev)
+{
+	unsigned int key;
+	size_t i;
+	
+	/*
+	 * First of all, check if the kbd have reported phantom state.
+	 *
+	 * As there is no way to distinguish keys from modifiers, we do not have
+	 * a way to check that 'all keys report Error Rollover'. We thus check
+	 * if there is at least one such error and in such case we ignore the
+	 * whole input report.
+	 */
+	i = find_in_array_int32(ERROR_ROLLOVER, kbd_dev->keys,
+	    kbd_dev->key_count);
+	if (i != (size_t) -1) {
+		usb_log_debug("Detected phantom state.\n");
+		return;
+	}
+	
+	/*
+	 * Key releases
+	 */
+	for (i = 0; i < kbd_dev->key_count; i++) {
+		int32_t old_key = kbd_dev->keys_old[i];
+		/* Find the old key among currently pressed keys. */
+		size_t pos = find_in_array_int32(old_key, kbd_dev->keys,
+		    kbd_dev->key_count);
+		/* If the key was not found, we need to signal release. */
+		if (pos == (size_t) -1) {
+			key = usbhid_parse_scancode(old_key);
+			if (!usb_kbd_is_lock(key)) {
+				usb_kbd_repeat_stop(kbd_dev, key);
+			}
+			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_RELEASE, key);
+			usb_log_debug2("Key released: %u "
+			    "(USB code %" PRIu32 ")\n", key, old_key);
+		}
+	}
+	
+	/*
+	 * Key presses
+	 */
+	for (i = 0; i < kbd_dev->key_count; ++i) {
+		int32_t new_key = kbd_dev->keys[i];
+		/* Find the new key among already pressed keys. */
+		size_t pos = find_in_array_int32(new_key, kbd_dev->keys_old,
+		    kbd_dev->key_count);
+		/* If the key was not found, we need to signal press. */
+		if (pos == (size_t) -1) {
+			key = usbhid_parse_scancode(kbd_dev->keys[i]);
+			if (!usb_kbd_is_lock(key)) {
+				usb_kbd_repeat_start(kbd_dev, key);
+			}
+			usb_kbd_push_ev(hid_dev, kbd_dev, KEY_PRESS, key);
+			usb_log_debug2("Key pressed: %u "
+			    "(USB code %" PRIu32 ")\n", key, new_key);
+		}
+	}
+	
+	memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
+	
+	char key_buffer[512];
+	ddf_dump_buffer(key_buffer, 512,
+	    kbd_dev->keys_old, 4, kbd_dev->key_count, 0);
+	usb_log_debug2("Stored keys %s.\n", key_buffer);
+}
+
+/*----------------------------------------------------------------------------*/
+/* General kbd functions                                                      */
+/*----------------------------------------------------------------------------*/
+/**
+ * Processes data received from the device in form of report.
+ *
+ * This function uses the HID report parser to translate the data received from
+ * the device into generic USB HID key codes and into generic modifiers bitmap.
+ * The parser then calls the given callback (usb_kbd_process_keycodes()).
+ *
+ * @note Currently, only the boot protocol is supported.
+ *
+ * @param kbd_dev Keyboard device structure (must be initialized).
+ * @param buffer Data from the keyboard (i.e. the report).
+ * @param actual_size Size of the data from keyboard (report size) in bytes.
+ *
+ * @sa usb_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(),
+ *     usb_hid_parse_report().
+ */
+static void usb_kbd_process_data(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
+{
+	assert(hid_dev->report != NULL);
+	assert(hid_dev != NULL);
+	assert(kbd_dev != NULL);
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+
+	usb_hid_report_path_set_report_id (path, hid_dev->report_id);
+	
+	// fill in the currently pressed keys
+	
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, 
+	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    USB_HID_REPORT_TYPE_INPUT);
+	unsigned i = 0;
+	
+	while (field != NULL) {
+		usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n", 
+		    field, field->value, field->usage);
+		
+		assert(i < kbd_dev->key_count);
+		
+		// save the key usage
+		if (field->value != 0) {
+			kbd_dev->keys[i] = field->usage;
+		}
+		else {
+			kbd_dev->keys[i] = 0;
+		}
+		usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
+		
+		++i;
+		field = usb_hid_report_get_sibling(hid_dev->report, field, path, 
+		    USB_HID_PATH_COMPARE_END 
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}
+	
+	usb_hid_report_path_free(path);
+	
+	usb_kbd_check_key_changes(hid_dev, kbd_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+/* HID/KBD structure manipulation                                             */
+/*----------------------------------------------------------------------------*/
+
+static void usb_kbd_mark_unusable(usb_kbd_t *kbd_dev)
+{
+	kbd_dev->initialized = USB_KBD_STATUS_TO_DESTROY;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * Creates a new USB/HID keyboard structure.
+ *
+ * The structure returned by this function is not initialized. Use 
+ * usb_kbd_init() to initialize it prior to polling.
+ *
+ * @return New uninitialized structure for representing a USB/HID keyboard or
+ *         NULL if not successful (memory error).
+ */
+static usb_kbd_t *usb_kbd_new(void)
+{
+	usb_kbd_t *kbd_dev = 
+	    (usb_kbd_t *)calloc(1, sizeof(usb_kbd_t));
+
+	if (kbd_dev == NULL) {
+		usb_log_fatal("No memory!\n");
+		return NULL;
+	}
+	
+	kbd_dev->console_phone = -1;
+	kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
+	
+	return kbd_dev;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_kbd_create_function(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
+{
+	assert(hid_dev != NULL);
+	assert(hid_dev->usb_dev != NULL);
+	assert(kbd_dev != NULL);
+	
+	/* Create the exposed function. */
+	usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_KBD_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/*
+	 * Store the initialized HID device and HID ops
+	 * to the DDF function.
+	 */
+	fun->ops = &kbd_dev->ops;
+	fun->driver_data = kbd_dev;
+
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("%s function created. Handle: %" PRIun "\n",
+	    HID_KBD_FUN_NAME, fun->handle);
+	
+	usb_log_debug("Adding DDF function to category %s...\n", 
+	    HID_KBD_CLASS_NAME);
+	rc = ddf_fun_add_to_category(fun, HID_KBD_CATEGORY_NAME);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to category %s: %s.\n",
+		    HID_KBD_CLASS_NAME, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/* API functions                                                              */
+/*----------------------------------------------------------------------------*/
+/**
+ * Initialization of the USB/HID keyboard structure.
+ *
+ * This functions initializes required structures from the device's descriptors.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ *
+ * @param kbd_dev Keyboard device structure to be initialized.
+ * @param dev DDF device structure of the keyboard.
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if some parameter is not given.
+ * @return Other value inherited from function usbhid_dev_init().
+ */
+int usb_kbd_init(usb_hid_dev_t *hid_dev, void **data)
+{
+	usb_log_debug("Initializing HID/KBD structure...\n");
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	usb_kbd_t *kbd_dev = usb_kbd_new();
+	if (kbd_dev == NULL) {
+		usb_log_error("Error while creating USB/HID KBD device "
+		    "structure.\n");
+		return ENOMEM;  // TODO: some other code??
+	}
+
+	/* Store link to HID device */
+	kbd_dev->hid_dev = hid_dev;
+	
+	/*
+	 * TODO: make more general
+	 */
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
+	
+	usb_hid_report_path_set_report_id(path, 0);
+	
+	kbd_dev->key_count = usb_hid_report_size(
+	    hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT); 
+	usb_hid_report_path_free(path);
+	
+	usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
+	
+	kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
+	
+	if (kbd_dev->keys == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
+	kbd_dev->keys_old = 
+		(int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
+	
+	if (kbd_dev->keys_old == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev->keys);
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Output report
+	 */
+	kbd_dev->output_size = 0;
+	kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report, 
+	    &kbd_dev->output_size, 0);
+	if (kbd_dev->output_buffer == NULL) {
+		usb_log_warning("Error creating output report buffer.\n");
+		free(kbd_dev->keys);
+		return ENOMEM;
+	}
+	
+	usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
+	
+	kbd_dev->led_path = usb_hid_report_path();
+	usb_hid_report_path_append_item(
+	    kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
+	
+	kbd_dev->led_output_size = usb_hid_report_size(hid_dev->report, 
+	    0, USB_HID_REPORT_TYPE_OUTPUT);
+	
+	usb_log_debug("Output report size (in items): %zu\n", 
+	    kbd_dev->led_output_size);
+	
+	kbd_dev->led_data = (int32_t *)calloc(
+	    kbd_dev->led_output_size, sizeof(int32_t));
+	
+	if (kbd_dev->led_data == NULL) {
+		usb_log_warning("Error creating buffer for LED output report."
+		    "\n");
+		free(kbd_dev->keys);
+		usb_hid_report_output_free(kbd_dev->output_buffer);
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Modifiers and locks
+	 */
+	kbd_dev->modifiers = 0;
+	kbd_dev->mods = DEFAULT_ACTIVE_MODS;
+	kbd_dev->lock_keys = 0;
+	
+	/*
+	 * Autorepeat
+	 */
+	kbd_dev->repeat.key_new = 0;
+	kbd_dev->repeat.key_repeated = 0;
+	kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
+	kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
+	
+	kbd_dev->repeat_mtx = (fibril_mutex_t *)(
+	    malloc(sizeof(fibril_mutex_t)));
+	if (kbd_dev->repeat_mtx == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(kbd_dev->keys);
+		usb_hid_report_output_free(kbd_dev->output_buffer);
+		free(kbd_dev);
+		return ENOMEM;
+	}
+	
+	fibril_mutex_initialize(kbd_dev->repeat_mtx);
+	
+	// save the KBD device structure into the HID device structure
+	*data = kbd_dev;
+	
+	// set handler for incoming calls
+	kbd_dev->ops.default_handler = default_connection_handler;
+	
+	/*
+	 * Set LEDs according to initial setup.
+	 * Set Idle rate
+	 */
+	usb_kbd_set_led(hid_dev, kbd_dev);
+	
+	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, IDLE_RATE);
+	
+	/*
+	 * Create new fibril for auto-repeat
+	 */
+	fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
+	if (fid == 0) {
+		usb_log_error("Failed to start fibril for KBD auto-repeat");
+		return ENOMEM;
+	}
+	fibril_add_ready(fid);
+	
+	kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
+	usb_log_debug("HID/KBD device structure initialized.\n");
+	
+	usb_log_debug("Creating KBD function...\n");
+	int rc = usb_kbd_create_function(hid_dev, kbd_dev);
+	if (rc != EOK) {
+		usb_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, void *data)
+{
+	if (hid_dev == NULL/* || buffer == NULL*/ || data == NULL) {
+		// do not continue polling (???)
+		return false;
+	}
+	
+	usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
+	assert(kbd_dev != NULL);
+	
+	// TODO: add return value from this function
+	usb_kbd_process_data(hid_dev, kbd_dev);
+	
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev)
+{
+	return (kbd_dev->initialized == USB_KBD_STATUS_INITIALIZED);
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev)
+{
+	return (kbd_dev->initialized == USB_KBD_STATUS_TO_DESTROY);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Properly destroys the USB/HID keyboard structure.
+ *
+ * @param kbd_dev Pointer to the structure to be destroyed.
+ */
+void usb_kbd_free(usb_kbd_t **kbd_dev)
+{
+	if (kbd_dev == NULL || *kbd_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_obsolete_hangup((*kbd_dev)->console_phone);
+	
+	if ((*kbd_dev)->repeat_mtx != NULL) {
+		//assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
+		// FIXME - the fibril_mutex_is_locked may not cause
+		// fibril scheduling
+		while (fibril_mutex_is_locked((*kbd_dev)->repeat_mtx)) {}
+		free((*kbd_dev)->repeat_mtx);
+	}
+	
+	// free all buffers
+	if ((*kbd_dev)->keys != NULL) {
+		free((*kbd_dev)->keys);
+	}
+	if ((*kbd_dev)->keys_old != NULL) {
+		free((*kbd_dev)->keys_old);
+	}
+	if ((*kbd_dev)->led_data != NULL) {
+		free((*kbd_dev)->led_data);
+	}
+	if ((*kbd_dev)->led_path != NULL) {
+		usb_hid_report_path_free((*kbd_dev)->led_path);
+	}
+	if ((*kbd_dev)->output_buffer != NULL) {
+		usb_hid_report_output_free((*kbd_dev)->output_buffer);
+	}
+
+	free(*kbd_dev);
+	*kbd_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_kbd_deinit(usb_hid_dev_t *hid_dev, void *data)
+{
+	if (hid_dev == NULL) {
+		return;
+	}
+	
+	if (data != NULL) {
+		usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
+		if (usb_kbd_is_initialized(kbd_dev)) {
+			usb_kbd_mark_unusable(kbd_dev);
+		} else {
+			usb_kbd_free(&kbd_dev);
+		}
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
+{
+	int rc = usb_hid_parse_report_descriptor(hid_dev->report, 
+	    USB_KBD_BOOT_REPORT_DESCRIPTOR, 
+	    USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to parse boot report descriptor: %s\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
+	
+	if (rc != EOK) {
+		usb_log_warning("Failed to set boot protocol to the device: "
+		    "%s\n", str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/kbddev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/kbd/kbddev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID keyboard device structure and API.
+ */
+
+#ifndef USB_HID_KBDDEV_H_
+#define USB_HID_KBDDEV_H_
+
+#include <stdint.h>
+
+#include <fibril_synch.h>
+
+#include <usb/hid/hid.h>
+#include <usb/hid/hidparser.h>
+#include <ddf/driver.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+
+#include "kbdrepeat.h"
+
+struct usb_hid_dev;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * USB/HID keyboard device type.
+ *
+ * Holds a reference to generic USB/HID device structure and keyboard-specific
+ * data, such as currently pressed keys, modifiers and lock keys.
+ *
+ * Also holds a IPC phone to the console (since there is now no other way to 
+ * communicate with it).
+ *
+ * @note Storing active lock keys in this structure results in their setting
+ *       being device-specific.
+ */
+typedef struct usb_kbd_t {
+	/** Link to HID device structure */
+	struct usb_hid_dev *hid_dev;
+
+	/** Previously pressed keys (not translated to key codes). */
+	int32_t *keys_old;
+	/** Currently pressed keys (not translated to key codes). */
+	int32_t *keys;
+	/** Count of stored keys (i.e. number of keys in the report). */
+	size_t key_count;
+	/** Currently pressed modifiers (bitmap). */
+	uint8_t modifiers;
+	
+	/** Currently active modifiers including locks. Sent to the console. */
+	unsigned mods;
+	
+	/** Currently active lock keys. */
+	unsigned lock_keys;
+	
+	/** IPC phone to the console device (for sending key events). */
+	int console_phone;
+	
+	/** @todo What is this actually? */
+	ddf_dev_ops_t ops;
+	
+	/** Information for auto-repeat of keys. */
+	usb_kbd_repeat_t repeat;
+	
+	/** Mutex for accessing the information about auto-repeat. */
+	fibril_mutex_t *repeat_mtx;
+	
+	uint8_t *output_buffer;
+	
+	size_t output_size;
+	
+	size_t led_output_size;
+	
+	usb_hid_report_path_t *led_path;
+	
+	int32_t *led_data;
+	
+	/** State of the structure (for checking before use). 
+	 * 
+	 * 0 - not initialized
+	 * 1 - initialized
+	 * -1 - ready for destroying
+	 */
+	int initialized;
+} usb_kbd_t;
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
+
+const char *HID_KBD_FUN_NAME;
+const char *HID_KBD_CLASS_NAME;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_init(struct usb_hid_dev *hid_dev, void **data);
+
+bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, void *data);
+
+int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
+
+int usb_kbd_is_ready_to_destroy(const usb_kbd_t *kbd_dev);
+
+void usb_kbd_free(usb_kbd_t **kbd_dev);
+
+void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
+    int type, unsigned int key);
+
+void usb_kbd_deinit(struct usb_hid_dev *hid_dev, void *data);
+
+int usb_kbd_set_boot_protocol(struct usb_hid_dev *hid_dev);
+
+#endif /* USB_HID_KBDDEV_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID keyboard autorepeat facilities
+ */
+
+#include <fibril_synch.h>
+#include <io/keycode.h>
+#include <io/console.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+
+#include "kbdrepeat.h"
+#include "kbddev.h"
+
+
+/** Delay between auto-repeat state checks when no key is being repeated. */
+static unsigned int CHECK_DELAY = 10000;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Main loop handling the auto-repeat of keys.
+ *
+ * This functions periodically checks if there is some key to be auto-repeated.
+ *
+ * If a new key is to be repeated, it uses the delay before first repeat stored
+ * in the keyboard structure to wait until the key has to start repeating.
+ *
+ * If the same key is still pressed, it uses the delay between repeats stored
+ * in the keyboard structure to wait until the key should be repeated.
+ * 
+ * If the currently repeated key is not pressed any more (
+ * usb_kbd_repeat_stop() was called), it stops repeating it and starts 
+ * checking again.
+ *
+ * @note For accessing the keyboard device auto-repeat information a fibril
+ *       mutex (repeat_mtx) from the @a kbd structure is used.
+ * 
+ * @param kbd Keyboard device structure.
+ */
+static void usb_kbd_repeat_loop(usb_kbd_t *kbd)
+{
+	unsigned int delay = 0;
+	
+	usb_log_debug("Starting autorepeat loop.\n");
+
+	while (true) {
+		// check if the kbd structure is usable
+		if (!usb_kbd_is_initialized(kbd)) {
+			if (usb_kbd_is_ready_to_destroy(kbd)) {
+				usb_kbd_free(&kbd);
+				assert(kbd == NULL);
+			}
+			return;
+		}
+		
+		fibril_mutex_lock(kbd->repeat_mtx);
+
+		if (kbd->repeat.key_new > 0) {
+			if (kbd->repeat.key_new == kbd->repeat.key_repeated) {
+				usb_log_debug2("Repeating key: %u.\n", 
+				    kbd->repeat.key_repeated);
+				// ugly hack with the NULL
+				usb_kbd_push_ev(NULL, kbd, KEY_PRESS, 
+				    kbd->repeat.key_repeated);
+				delay = kbd->repeat.delay_between;
+			} else {
+				usb_log_debug2("New key to repeat: %u.\n",
+				    kbd->repeat.key_new);
+				kbd->repeat.key_repeated = kbd->repeat.key_new;
+				delay = kbd->repeat.delay_before;
+			}
+		} else {
+			if (kbd->repeat.key_repeated > 0) {
+				usb_log_debug2("Stopping to repeat key: %u.\n",
+				    kbd->repeat.key_repeated);
+				kbd->repeat.key_repeated = 0;
+			}
+			delay = CHECK_DELAY;
+		}
+		fibril_mutex_unlock(kbd->repeat_mtx);
+		
+		async_usleep(delay);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Main routine to be executed by a fibril for handling auto-repeat.
+ *
+ * Starts the loop for checking changes in auto-repeat.
+ * 
+ * @param arg User-specified argument. Expects pointer to the keyboard device
+ *            structure representing the keyboard.
+ *
+ * @retval EOK if the routine has finished.
+ * @retval EINVAL if no argument is supplied.
+ */
+int usb_kbd_repeat_fibril(void *arg)
+{
+	usb_log_debug("Autorepeat fibril spawned.\n");
+	
+	if (arg == NULL) {
+		usb_log_error("No device!\n");
+		return EINVAL;
+	}
+	
+	usb_kbd_t *kbd = (usb_kbd_t *)arg;
+	
+	usb_kbd_repeat_loop(kbd);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Start repeating particular key.
+ *
+ * @note Only one key is repeated at any time, so calling this function 
+ *       effectively cancels auto-repeat of the current repeated key (if any)
+ *       and 'schedules' another key for auto-repeat.
+ *
+ * @param kbd Keyboard device structure.
+ * @param key Key to start repeating.
+ */
+void usb_kbd_repeat_start(usb_kbd_t *kbd, unsigned int key)
+{
+	fibril_mutex_lock(kbd->repeat_mtx);
+	kbd->repeat.key_new = key;
+	fibril_mutex_unlock(kbd->repeat_mtx);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Stop repeating particular key.
+ *
+ * @note Only one key is repeated at any time, but this function may be called
+ *       even with key that is not currently repeated (in that case nothing 
+ *       happens).
+ *
+ * @param kbd Keyboard device structure.
+ * @param key Key to stop repeating.
+ */
+void usb_kbd_repeat_stop(usb_kbd_t *kbd, unsigned int key)
+{
+	fibril_mutex_lock(kbd->repeat_mtx);
+	if (key == kbd->repeat.key_new) {
+		kbd->repeat.key_new = 0;
+	}
+	fibril_mutex_unlock(kbd->repeat_mtx);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID keyboard autorepeat facilities
+ */
+
+#ifndef USB_HID_KBDREPEAT_H_
+#define USB_HID_KBDREPEAT_H_
+
+struct usb_kbd_t;
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Structure for keeping information needed for auto-repeat of keys.
+ */
+typedef struct {
+	/** Last pressed key. */
+	unsigned int key_new;
+	/** Key to be repeated. */
+	unsigned int key_repeated;
+	/** Delay before first repeat in microseconds. */
+	unsigned int delay_before;
+	/** Delay between repeats in microseconds. */
+	unsigned int delay_between;
+} usb_kbd_repeat_t;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_kbd_repeat_fibril(void *arg);
+
+void usb_kbd_repeat_start(struct usb_kbd_t *kbd, unsigned int key);
+
+void usb_kbd_repeat_stop(struct usb_kbd_t *kbd, unsigned int key);
+
+#endif /* USB_HID_KBDREPEAT_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/main.c
===================================================================
--- uspace/drv/bus/usb/usbhid/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB HID driver.
+ */
+
+#include <ddf/driver.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/dev/driver.h>
+#include <usb/dev/poll.h>
+
+#include "usbhid.h"
+
+/*----------------------------------------------------------------------------*/
+
+#define NAME "usbhid"
+
+/**
+ * Function for adding a new device of type USB/HID/keyboard.
+ *
+ * This functions initializes required structures from the device's descriptors
+ * and starts new fibril for polling the keyboard for events and another one for
+ * handling auto-repeat of keys.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ * @note Currently supports only boot-protocol keyboards.
+ *
+ * @param dev Device to add.
+ *
+ * @retval EOK if successful.
+ * @retval ENOMEM if there
+ * @return Other error code inherited from one of functions usb_kbd_init(),
+ *         ddf_fun_bind() and ddf_fun_add_to_class().
+ */
+static int usb_hid_try_add_device(usb_device_t *dev)
+{
+	assert(dev != NULL);
+	
+	/* 
+	 * Initialize device (get and process descriptors, get address, etc.)
+	 */
+	usb_log_debug("Initializing USB/HID device...\n");
+	
+	usb_hid_dev_t *hid_dev = usb_hid_new();
+	if (hid_dev == NULL) {
+		usb_log_error("Error while creating USB/HID device "
+		    "structure.\n");
+		return ENOMEM;
+	}
+	
+	int rc = usb_hid_init(hid_dev, dev);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize USB/HID device.\n");
+		usb_hid_free(&hid_dev);
+		return rc;
+	}	
+	
+	usb_log_debug("USB/HID device structure initialized.\n");
+	
+	/*
+	 * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
+	 *    do nej.
+	 * 2) do tych ops do .interfaces[DEV_IFACE_USBHID (asi)] priradi 
+	 *    vyplnenu strukturu usbhid_iface_t.
+	 * 3) klientska aplikacia - musi si rucne vytvorit telefon
+	 *    (devman_device_connect() - cesta k zariadeniu (/hw/pci0/...) az 
+	 *    k tej fcii.
+	 *    pouzit usb/classes/hid/iface.h - prvy int je telefon
+	 */
+	
+	/* Start automated polling function.
+	 * This will create a separate fibril that will query the device
+	 * for the data continuously 
+	 */
+       rc = usb_device_auto_poll(dev,
+	   /* Index of the polling pipe. */
+	   hid_dev->poll_pipe_index,
+	   /* Callback when data arrives. */
+	   usb_hid_polling_callback,
+	   /* How much data to request. */
+	   dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
+	   /* Callback when the polling ends. */
+	   usb_hid_polling_ended_callback,
+	   /* Custom argument. */
+	   hid_dev);
+	
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to start polling fibril for `%s'.\n",
+		    dev->ddf_dev->name);
+		return rc;
+	}
+
+	/*
+	 * Hurrah, device is initialized.
+	 */
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Callback for passing a new device to the driver.
+ *
+ * @note Currently, only boot-protocol keyboards are supported by this driver.
+ *
+ * @param dev Structure representing the new device.
+ *
+ * @retval EOK if successful. 
+ * @retval EREFUSED if the device is not supported.
+ */
+static int usb_hid_add_device(usb_device_t *dev)
+{
+	usb_log_debug("usb_hid_add_device()\n");
+	
+	if (dev == NULL) {
+		usb_log_warning("Wrong parameter given for add_device().\n");
+		return EINVAL;
+	}
+	
+	if (dev->interface_no < 0) {
+		usb_log_warning("Device is not a supported HID device.\n");
+		usb_log_error("Failed to add HID device: endpoints not found."
+		    "\n");
+		return ENOTSUP;
+	}
+	
+	int rc = usb_hid_try_add_device(dev);
+	
+	if (rc != EOK) {
+		usb_log_warning("Device is not a supported HID device.\n");
+		usb_log_error("Failed to add HID device: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
+
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/* Currently, the framework supports only device adding. Once the framework
+ * supports unplug, more callbacks will be added. */
+static usb_driver_ops_t usb_hid_driver_ops = {
+        .add_device = usb_hid_add_device,
+};
+
+
+/* The driver itself. */
+static usb_driver_t usb_hid_driver = {
+        .name = NAME,
+        .ops = &usb_hid_driver_ops,
+        .endpoints = usb_hid_endpoints
+};
+
+/*----------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS USB HID driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&usb_hid_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak, 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB Mouse driver API.
+ */
+
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/hid.h>
+#include <usb/hid/request.h>
+#include <usb/hid/usages/core.h>
+#include <errno.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <str_error.h>
+#include <ipc/mouseev.h>
+#include <io/console.h>
+
+#include <ipc/kbdev.h>
+#include <io/keycode.h>
+
+#include "mousedev.h"
+#include "../usbhid.h"
+
+/** Number of simulated arrow-key presses for singel wheel step. */
+#define ARROWS_PER_SINGLE_WHEEL 3
+
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
+
+#define NAME "mouse"
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_MOUSE,
+	.flags = 0
+};
+
+const char *HID_MOUSE_FUN_NAME = "mouse";
+const char *HID_MOUSE_WHEEL_FUN_NAME = "mouse-wheel";
+const char *HID_MOUSE_CATEGORY = "mouse";
+const char *HID_MOUSE_WHEEL_CATEGORY = "keyboard";
+
+/** Default idle rate for mouses. */
+static const uint8_t IDLE_RATE = 0;
+static const size_t USB_MOUSE_BUTTON_COUNT = 3;
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE = 63
+};
+
+static const uint8_t USB_MOUSE_BOOT_REPORT_DESCRIPTOR[
+    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE] = {
+	0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
+	0x09, 0x02,                    // USAGE (Mouse)
+	0xa1, 0x01,                    // COLLECTION (Application)
+	0x09, 0x01,                    //   USAGE (Pointer)
+	0xa1, 0x00,                    //   COLLECTION (Physical)
+	0x95, 0x03,                    //     REPORT_COUNT (3)
+	0x75, 0x01,                    //     REPORT_SIZE (1)
+	0x05, 0x09,                    //     USAGE_PAGE (Button)
+	0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
+	0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
+	0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
+	0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
+	0x81, 0x02,                    //     INPUT (Data,Var,Abs)
+	0x95, 0x01,                    //     REPORT_COUNT (1)
+	0x75, 0x05,                    //     REPORT_SIZE (5)
+	0x81, 0x01,                    //     INPUT (Cnst)
+	0x75, 0x08,                    //     REPORT_SIZE (8)
+	0x95, 0x02,                    //     REPORT_COUNT (2)
+	0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
+	0x09, 0x30,                    //     USAGE (X)
+	0x09, 0x31,                    //     USAGE (Y)
+	0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
+	0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
+	0x81, 0x06,                    //     INPUT (Data,Var,Rel)
+	0xc0,                          //   END_COLLECTION
+	0xc0                           // END_COLLECTION
+};
+
+/*----------------------------------------------------------------------------*/
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+static void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	
+	usb_mouse_t *mouse_dev = (usb_mouse_t *)fun->driver_data;
+	
+	if (mouse_dev == NULL) {
+		usb_log_debug("default_connection_handler: Missing "
+		    "parameters.\n");
+		async_answer_0(icallid, EINVAL);
+		return;
+	}
+	
+	usb_log_debug("default_connection_handler: fun->name: %s\n",
+	              fun->name);
+	usb_log_debug("default_connection_handler: mouse_phone: %d, wheel "
+	    "phone: %d\n", mouse_dev->mouse_phone, mouse_dev->wheel_phone);
+	
+	int *phone = (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) 
+		     ? &mouse_dev->mouse_phone : &mouse_dev->wheel_phone;
+	
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (*phone != -1) {
+			usb_log_debug("default_connection_handler: Console "
+			    "phone to mouse already set.\n");
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		*phone = callback;
+		usb_log_debug("Console phone to mouse set ok (%d).\n", *phone);
+		async_answer_0(icallid, EOK);
+		return;
+	}
+
+	usb_log_debug("default_connection_handler: Invalid function.\n");
+	async_answer_0(icallid, EINVAL);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static usb_mouse_t *usb_mouse_new(void)
+{
+	usb_mouse_t *mouse = calloc(1, sizeof(usb_mouse_t));
+	if (mouse == NULL) {
+		return NULL;
+	}
+	mouse->mouse_phone = -1;
+	mouse->wheel_phone = -1;
+	
+	return mouse;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_mouse_free(usb_mouse_t **mouse_dev)
+{
+	assert(mouse_dev != NULL && *mouse_dev != NULL);
+	
+	// hangup phone to the console
+	if ((*mouse_dev)->mouse_phone >= 0) {
+		async_obsolete_hangup((*mouse_dev)->mouse_phone);
+	}
+	
+	if ((*mouse_dev)->wheel_phone >= 0) {
+		async_obsolete_hangup((*mouse_dev)->wheel_phone);
+	}
+	
+	free(*mouse_dev);
+	*mouse_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_mouse_send_wheel(const usb_mouse_t *mouse_dev, int wheel)
+{
+	unsigned int key = (wheel > 0) ? KC_UP : KC_DOWN;
+
+	if (mouse_dev->wheel_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, wheel roll discarded.\n");
+		return;
+	}
+	
+	int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
+	int i;
+	
+	for (i = 0; i < count; i++) {
+		/* Send arrow press and release. */
+		usb_log_debug2("Sending key %d to the console\n", key);
+		async_obsolete_msg_4(mouse_dev->wheel_phone, KBDEV_EVENT,
+		    KEY_PRESS, key, 0, 0);
+		async_obsolete_msg_4(mouse_dev->wheel_phone, KBDEV_EVENT,
+		    KEY_RELEASE, key, 0, 0);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int get_mouse_axis_move_value(uint8_t rid, usb_hid_report_t *report,
+    int32_t usage)
+{
+	int result = 0;
+
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_GENERIC_DESKTOP,
+	    usage);
+
+	usb_hid_report_path_set_report_id(path, rid);
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    report, NULL, path, USB_HID_PATH_COMPARE_END,
+	    USB_HID_REPORT_TYPE_INPUT);
+
+	if (field != NULL) {
+		result = field->value;
+	}
+
+	usb_hid_report_path_free(path);
+
+	return result;
+}
+
+static bool usb_mouse_process_report(usb_hid_dev_t *hid_dev,
+    usb_mouse_t *mouse_dev)
+{
+	assert(mouse_dev != NULL);
+	
+	if (mouse_dev->mouse_phone < 0) {
+		usb_log_warning(NAME " No console phone.\n");
+		return true;
+	}
+
+	int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
+	    hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
+	int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
+	    hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
+	int wheel = get_mouse_axis_move_value(hid_dev->report_id,
+	    hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
+
+	if ((shift_x != 0) || (shift_y != 0)) {
+		async_obsolete_req_2_0(mouse_dev->mouse_phone,
+		    MOUSEEV_MOVE_EVENT, shift_x, shift_y);
+	}
+
+	if (wheel != 0) {
+		usb_mouse_send_wheel(mouse_dev, wheel);
+	}
+	
+	/*
+	 * Buttons
+	 */
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
+	usb_hid_report_path_set_report_id(path, hid_dev->report_id);
+	
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
+	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    USB_HID_REPORT_TYPE_INPUT);
+
+	while (field != NULL) {
+		usb_log_debug2(NAME " VALUE(%X) USAGE(%X)\n", field->value,
+		    field->usage);
+		
+		if (mouse_dev->buttons[field->usage - field->usage_minimum] == 0
+		    && field->value != 0) {
+			async_obsolete_req_2_0(mouse_dev->mouse_phone,
+			    MOUSEEV_BUTTON_EVENT, field->usage, 1);
+			mouse_dev->buttons[field->usage - field->usage_minimum]
+			    = field->value;
+		} else if (mouse_dev->buttons[field->usage - field->usage_minimum] != 0
+		    && field->value == 0) {
+			async_obsolete_req_2_0(mouse_dev->mouse_phone,
+			   MOUSEEV_BUTTON_EVENT, field->usage, 0);
+			mouse_dev->buttons[field->usage - field->usage_minimum] =
+			   field->value;
+		}
+		
+		field = usb_hid_report_get_sibling(
+		    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}
+	
+	usb_hid_report_path_free(path);
+
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_mouse_create_function(usb_hid_dev_t *hid_dev, usb_mouse_t *mouse)
+{
+	assert(hid_dev != NULL);
+	assert(mouse != NULL);
+	
+	/* Create the exposed function. */
+	usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_MOUSE_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	fun->ops = &mouse->ops;
+	fun->driver_data = mouse;
+
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("Adding DDF function to category %s...\n", 
+	    HID_MOUSE_CATEGORY);
+	rc = ddf_fun_add_to_category(fun, HID_MOUSE_CATEGORY);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to category %s: %s.\n",
+		    HID_MOUSE_CATEGORY, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	/*
+	 * Special function for acting as keyboard (wheel)
+	 */
+	usb_log_debug("Creating DDF function %s...\n", 
+	              HID_MOUSE_WHEEL_FUN_NAME);
+	fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    HID_MOUSE_WHEEL_FUN_NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/*
+	 * Store the initialized HID device and HID ops
+	 * to the DDF function.
+	 */
+	fun->ops = &mouse->ops;
+	fun->driver_data = mouse;
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("Adding DDF function to category %s...\n", 
+	    HID_MOUSE_WHEEL_CATEGORY);
+	rc = ddf_fun_add_to_category(fun, HID_MOUSE_WHEEL_CATEGORY);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to category %s: %s.\n",
+		    HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_init(usb_hid_dev_t *hid_dev, void **data)
+{
+	usb_log_debug("Initializing HID/Mouse structure...\n");
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Failed to init keyboard structure: no structure"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	usb_mouse_t *mouse_dev = usb_mouse_new();
+	if (mouse_dev == NULL) {
+		usb_log_error("Error while creating USB/HID Mouse device "
+		    "structure.\n");
+		return ENOMEM;
+	}
+	
+	mouse_dev->buttons = (int32_t *)calloc(USB_MOUSE_BUTTON_COUNT, 
+	    sizeof(int32_t));
+	
+	if (mouse_dev->buttons == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(mouse_dev);
+		return ENOMEM;
+	}
+	
+	// save the Mouse device structure into the HID device structure
+	*data = mouse_dev;
+	
+	// set handler for incoming calls
+	mouse_dev->ops.default_handler = default_connection_handler;
+	
+	// TODO: how to know if the device supports the request???
+	usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, IDLE_RATE);
+	
+	int rc = usb_mouse_create_function(hid_dev, mouse_dev);
+	if (rc != EOK) {
+		usb_mouse_free(&mouse_dev);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_mouse_polling_callback(usb_hid_dev_t *hid_dev, void *data)
+{
+	if (hid_dev == NULL || data == NULL) {
+		usb_log_error("Missing argument to the mouse polling callback."
+		    "\n");
+		return false;
+	}
+	
+	usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
+		
+	return usb_mouse_process_report(hid_dev, mouse_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_mouse_deinit(usb_hid_dev_t *hid_dev, void *data)
+{
+	if (data != NULL) {
+		usb_mouse_free((usb_mouse_t **)&data);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
+{
+	int rc = usb_hid_parse_report_descriptor(hid_dev->report, 
+	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR, 
+	    USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to parse boot report descriptor: %s\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
+	    hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
+	
+	if (rc != EOK) {
+		usb_log_warning("Failed to set boot protocol to the device: "
+		    "%s\n", str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/mouse/mousedev.h
===================================================================
--- uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/mouse/mousedev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB Mouse driver API.
+ */
+
+#ifndef USB_HID_MOUSEDEV_H_
+#define USB_HID_MOUSEDEV_H_
+
+#include <usb/dev/driver.h>
+
+struct usb_hid_dev;
+
+/*----------------------------------------------------------------------------*/
+
+/** Container for USB mouse device. */
+typedef struct {
+	/** IPC phone to console (consumer). */
+	int mouse_phone;
+	int wheel_phone;
+	
+	int32_t *buttons;
+	
+	ddf_dev_ops_t ops;
+} usb_mouse_t;
+
+/*----------------------------------------------------------------------------*/
+
+usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description;
+
+const char *HID_MOUSE_FUN_NAME;
+const char *HID_MOUSE_CATEGORY;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_mouse_init(struct usb_hid_dev *hid_dev, void **data);
+
+bool usb_mouse_polling_callback(struct usb_hid_dev *hid_dev, void *data);
+
+void usb_mouse_deinit(struct usb_hid_dev *hid_dev, void *data);
+
+int usb_mouse_set_boot_protocol(struct usb_hid_dev *hid_dev);
+
+/*----------------------------------------------------------------------------*/
+
+#endif // USB_HID_MOUSEDEV_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/multimedia/keymap.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/keymap.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/multimedia/keymap.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * UUSB multimedia key to keycode mapping.
+ */
+
+#include <io/keycode.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include "keymap.h"
+
+/**
+ * Mapping between USB HID multimedia usages (from HID Usage Tables) and 
+ * corresponding HelenOS key codes.
+ *
+ * Currently only Usages used by Logitech UltraX keyboard are present. All other
+ * should result in 0.
+ */
+static int usb_hid_keymap_consumer[0x29c] = {
+	[0xb5] = 0,       /* Scan Next Track */
+	[0xb6] = 0,       /* Scan Previous Track */
+	[0xb7] = 0,       /* Stop */
+	[0xb8] = 0,       /* Eject */
+	[0xcd] = 0/*KC_F2*/,   /* Play/Pause */
+	[0xe2] = 0/*KC_F3*/,   /* Mute */
+	[0xe9] = 0/*KC_F5*/,   /* Volume Increment */
+	[0xea] = 0/*KC_F4*/,   /* Volume Decrement */
+	[0x183] = 0/*KC_F1*/,      /* AL Consumer Control Configuration */
+	[0x18a] = 0,      /* AL Email Reader */
+	[0x192] = 0,      /* AL Calculator */
+	[0x221] = 0,      /* AC Search */
+	[0x223] = 0/*KC_F6*/,      /* AC Home */
+	[0x224] = 0,      /* AC Back */
+	[0x225] = 0,      /* AC Forward */
+	[0x226] = 0,      /* AC Stop */
+	[0x227] = 0,  /* AC Refresh */
+	[0x22a] = 0   /* AC Bookmarks */
+};
+
+/**
+ * Translates USB HID Usages from the Consumer Page into HelenOS keycodes.
+ *
+ * @param usage USB HID Consumer Page Usage number.
+ * 
+ * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
+ */
+unsigned int usb_multimedia_map_usage(int usage)
+{
+	unsigned int key;
+	int *map = usb_hid_keymap_consumer;
+	size_t map_length = sizeof(usb_hid_keymap_consumer) / sizeof(int);
+
+	if ((usage < 0) || ((size_t)usage >= map_length))
+		return -1;
+
+	/*! @todo What if the usage is not in the table? */
+	key = map[usage];
+	
+	return key;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/multimedia/keymap.h
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/keymap.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/multimedia/keymap.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB multimedia key to keycode mapping.
+ */
+
+#ifndef USB_HID_MULTIMEDIA_KEYMAP_H_
+#define USB_HID_MULTIMEDIA_KEYMAP_H_
+
+unsigned int usb_multimedia_map_usage(int usage);
+
+#endif /* USB_HID_MULTIMEDIA_KEYMAP_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak, 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB Keyboard multimedia keys subdriver.
+ */
+
+
+#include "multimedia.h"
+#include "../usbhid.h"
+#include "keymap.h"
+
+#include <usb/hid/hidparser.h>
+#include <usb/debug.h>
+#include <usb/hid/usages/core.h>
+#include <usb/hid/usages/consumer.h>
+
+#include <errno.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <str_error.h>
+
+#include <ipc/kbdev.h>
+#include <io/console.h>
+
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
+
+#define NAME "multimedia-keys"
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Logitech UltraX device type.
+ */
+typedef struct usb_multimedia_t {
+	/** Previously pressed keys (not translated to key codes). */
+	//int32_t *keys_old;
+	/** Currently pressed keys (not translated to key codes). */
+	//int32_t *keys;
+	/** Count of stored keys (i.e. number of keys in the report). */
+	//size_t key_count;	
+	/** IPC phone to the console device (for sending key events). */
+	int console_phone;
+} usb_multimedia_t;
+
+
+/*----------------------------------------------------------------------------*/
+/** 
+ * Default handler for IPC methods not handled by DDF.
+ *
+ * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
+ * assumes the caller is the console and thus it stores IPC phone to it for 
+ * later use by the driver to notify about key events.
+ *
+ * @param fun Device function handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+static void default_connection_handler(ddf_fun_t *fun,
+    ipc_callid_t icallid, ipc_call_t *icall)
+{
+	usb_log_debug(NAME " default_connection_handler()\n");
+	
+	sysarg_t method = IPC_GET_IMETHOD(*icall);
+	
+	usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
+	
+	if (multim_dev == NULL) {
+		async_answer_0(icallid, EINVAL);
+		return;
+	}
+
+	if (method == IPC_M_CONNECT_TO_ME) {
+		int callback = IPC_GET_ARG5(*icall);
+
+		if (multim_dev->console_phone != -1) {
+			async_answer_0(icallid, ELIMIT);
+			return;
+		}
+
+		multim_dev->console_phone = callback;
+		usb_log_debug(NAME " Saved phone to console: %d\n", callback);
+		async_answer_0(icallid, EOK);
+		return;
+	}
+	
+	async_answer_0(icallid, EINVAL);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static ddf_dev_ops_t multimedia_ops = {
+	.default_handler = default_connection_handler
+};
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Processes key events.
+ *
+ * @note This function was copied from AT keyboard driver and modified to suit
+ *       USB keyboard.
+ *
+ * @note Lock keys are not sent to the console, as they are completely handled
+ *       in the driver. It may, however, be required later that the driver
+ *       sends also these keys to application (otherwise it cannot use those
+ *       keys at all).
+ * 
+ * @param hid_dev 
+ * @param lgtch_dev 
+ * @param type Type of the event (press / release). Recognized values: 
+ *             KEY_PRESS, KEY_RELEASE
+ * @param key Key code of the key according to HID Usage Tables.
+ */
+static void usb_multimedia_push_ev(usb_hid_dev_t *hid_dev, 
+    usb_multimedia_t *multim_dev, int type, unsigned int key)
+{
+	assert(hid_dev != NULL);
+	assert(multim_dev != NULL);
+	
+	kbd_event_t ev;
+	
+	ev.type = type;
+	ev.key = key;
+	ev.mods = 0;
+	ev.c = 0;
+
+	usb_log_debug2(NAME " Sending key %d to the console\n", ev.key);
+	if (multim_dev->console_phone < 0) {
+		usb_log_warning(
+		    "Connection to console not ready, key discarded.\n");
+		return;
+	}
+	
+	async_obsolete_msg_4(multim_dev->console_phone, KBDEV_EVENT, ev.type, ev.key, 
+	    ev.mods, ev.c);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_multimedia_free(usb_multimedia_t **multim_dev)
+{
+	if (multim_dev == NULL || *multim_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_obsolete_hangup((*multim_dev)->console_phone);
+
+	free(*multim_dev);
+	*multim_dev = NULL;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_multimedia_create_function(usb_hid_dev_t *hid_dev, 
+    usb_multimedia_t *multim_dev)
+{
+	/* Create the exposed function. */
+	ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed, 
+	    NAME);
+	if (fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	fun->ops = &multimedia_ops;
+	fun->driver_data = multim_dev;   // TODO: maybe change to hid_dev->data
+	
+	int rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	usb_log_debug("%s function created (handle: %" PRIun ").\n",
+	    NAME, fun->handle);
+	
+	rc = ddf_fun_add_to_category(fun, "keyboard");
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to category 'keyboard': %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
+{
+	if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
+		return EINVAL; /*! @todo Other return code? */
+	}
+	
+	usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
+	
+	usb_multimedia_t *multim_dev = (usb_multimedia_t *)malloc(
+	    sizeof(usb_multimedia_t));
+	if (multim_dev == NULL) {
+		return ENOMEM;
+	}
+	
+	multim_dev->console_phone = -1;
+	
+	/*! @todo Autorepeat */
+	
+	// save the KBD device structure into the HID device structure
+	*data = multim_dev;
+	
+	usb_log_debug(NAME " HID/multimedia device structure initialized.\n");
+	
+	int rc = usb_multimedia_create_function(hid_dev, multim_dev);
+	if (rc != EOK) {
+		usb_multimedia_free(&multim_dev);
+		return rc;
+	}
+	
+	usb_log_debug(NAME " HID/multimedia structure initialized.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
+{
+	if (hid_dev == NULL) {
+		return;
+	}
+	
+	if (data != NULL) {
+		usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
+		usb_multimedia_free(&multim_dev);
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
+{
+	// TODO: checks
+	if (hid_dev == NULL || data == NULL) {
+		return false;
+	}
+
+	usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
+
+	usb_hid_report_path_set_report_id(path, hid_dev->report_id);
+
+	usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+	    hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END 
+	    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    USB_HID_REPORT_TYPE_INPUT);
+
+	/*! @todo Is this iterating OK if done multiple times? 
+	 *  @todo The parsing is not OK
+	 */
+	while (field != NULL) {
+		if(field->value != 0) {
+			usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
+			    field->value, field->usage);
+			unsigned int key = 
+			    usb_multimedia_map_usage(field->usage);
+			const char *key_str = 
+			    usbhid_multimedia_usage_to_str(field->usage);
+			usb_log_info("Pressed key: %s\n", key_str);
+			usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS, 
+			                       key);
+		}
+		
+		field = usb_hid_report_get_sibling(
+		    hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
+		    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+		    USB_HID_REPORT_TYPE_INPUT);
+	}	
+
+	usb_hid_report_path_free(path);
+	
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.h
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB Keyboard multimedia keys subdriver.
+ */
+
+#ifndef USB_HID_MULTIMEDIA_H_
+#define USB_HID_MULTIMEDIA_H_
+
+#include <usb/dev/driver.h>
+
+struct usb_hid_dev;
+
+/*----------------------------------------------------------------------------*/
+
+int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data);
+
+void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data);
+
+bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data);
+
+/*----------------------------------------------------------------------------*/
+
+#endif // USB_HID_MULTIMEDIA_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/subdrivers.c
===================================================================
--- uspace/drv/bus/usb/usbhid/subdrivers.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/subdrivers.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID subdriver mappings.
+ */
+
+#include "subdrivers.h"
+#include <usb/hid/usages/core.h>
+#include <usb/hid/hidpath.h>
+
+#include "multimedia/multimedia.h"
+#include "mouse/mousedev.h"
+#include "generic/hiddev.h"
+
+static usb_hid_subdriver_usage_t path_kbd[] = {
+	{USB_HIDUT_PAGE_GENERIC_DESKTOP, 
+	 USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD}, 
+	{0, 0}
+};
+
+static usb_hid_subdriver_usage_t path_mouse[] = {
+	{USB_HIDUT_PAGE_GENERIC_DESKTOP, USB_HIDUT_USAGE_GENERIC_DESKTOP_MOUSE},
+	{0, 0}
+};
+
+static usb_hid_subdriver_usage_t multim_key_path[] = {
+	{USB_HIDUT_PAGE_CONSUMER, USB_HIDUT_USAGE_CONSUMER_CONSUMER_CONTROL},
+	{0, 0}
+};
+
+const usb_hid_subdriver_mapping_t usb_hid_subdrivers[] = {
+	{
+		path_kbd,
+		0,
+		USB_HID_PATH_COMPARE_BEGIN,
+		-1,
+		-1,
+		{
+			.init = usb_kbd_init,
+			.deinit = usb_kbd_deinit,
+			.poll = usb_kbd_polling_callback,
+			.poll_end = NULL
+		},
+		
+	},
+	{
+		multim_key_path,
+		1,
+		USB_HID_PATH_COMPARE_BEGIN,
+		-1,
+		-1,
+		{
+			.init = usb_multimedia_init,
+			.deinit = usb_multimedia_deinit,
+			.poll = usb_multimedia_polling_callback,
+			.poll_end = NULL
+		}
+	},
+	{
+		path_mouse,
+		0,
+		USB_HID_PATH_COMPARE_BEGIN,
+		-1,
+		-1,
+		{
+			.init = usb_mouse_init,
+			.deinit = usb_mouse_deinit,
+			.poll = usb_mouse_polling_callback,
+			.poll_end = NULL
+		}
+	},
+	{NULL, -1, 0, -1, -1, {NULL, NULL, NULL, NULL, NULL}}
+};
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/subdrivers.h
===================================================================
--- uspace/drv/bus/usb/usbhid/subdrivers.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/subdrivers.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID subdriver mappings.
+ */
+
+#ifndef USB_HID_SUBDRIVERS_H_
+#define USB_HID_SUBDRIVERS_H_
+
+#include "usbhid.h"
+#include "kbd/kbddev.h"
+
+/*----------------------------------------------------------------------------*/
+
+typedef struct usb_hid_subdriver_usage {
+	int usage_page;
+	int usage;
+} usb_hid_subdriver_usage_t;
+
+/*----------------------------------------------------------------------------*/
+
+/** Structure representing the mapping between device requirements and the 
+ *  subdriver supposed to handle this device.
+ *
+ * By filling in this structure and adding it to the usb_hid_subdrivers array,
+ * a new subdriver mapping will be created and used by the HID driver when it
+ * searches for appropriate subdrivers for a device.
+ */
+typedef struct usb_hid_subdriver_mapping {
+	/** Usage path that the device's Input reports must contain. 
+	 *
+	 * It is an array of pairs <usage_page, usage>, terminated by a <0, 0>
+	 * pair. If you do not wish to specify the device in this way, set this
+	 * to NULL.
+	 */
+	const usb_hid_subdriver_usage_t *usage_path;
+	
+	/** Report ID for which the path should apply. */
+	int report_id;
+	
+	/** Compare type for the Usage path. */
+	int compare;
+	
+	/** Vendor ID (set to -1 if not specified). */
+	int vendor_id;
+	
+	/** Product ID (set to -1 if not specified). */
+	int product_id;
+	
+	/** Subdriver for controlling this device. */
+	usb_hid_subdriver_t subdriver;
+} usb_hid_subdriver_mapping_t;
+
+/*----------------------------------------------------------------------------*/
+
+extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
+
+/*----------------------------------------------------------------------------*/
+
+#endif /* USB_HID_SUBDRIVERS_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/usbhid.c
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/usbhid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID driver API.
+ */
+
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/hid.h>
+#include <usb/hid/hidparser.h>
+#include <usb/hid/hidreport.h>
+#include <usb/hid/request.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include "usbhid.h"
+
+#include "kbd/kbddev.h"
+#include "generic/hiddev.h"
+#include "mouse/mousedev.h"
+#include "subdrivers.h"
+
+/*----------------------------------------------------------------------------*/
+
+/* Array of endpoints expected on the device, NULL terminated. */
+usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {
+	&usb_hid_kbd_poll_endpoint_description,
+	&usb_hid_mouse_poll_endpoint_description,
+	&usb_hid_generic_poll_endpoint_description,
+	NULL
+};
+
+static const int USB_HID_MAX_SUBDRIVERS = 10;
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	assert(hid_dev->subdriver_count >= 0);
+	
+	// set the init callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_kbd_init;
+	
+	// set the polling callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
+	    usb_kbd_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_kbd_deinit;
+	
+	// set subdriver count
+	++hid_dev->subdriver_count;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	assert(hid_dev->subdriver_count >= 0);
+	
+	// set the init callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_mouse_init;
+	
+	// set the polling callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
+	    usb_mouse_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_mouse_deinit;
+	
+	// set subdriver count
+	++hid_dev->subdriver_count;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	assert(hid_dev->subdriver_count >= 0);
+	
+	// set the init callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].init =
+	    usb_generic_hid_init;
+	
+	// set the polling callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll = 
+	    usb_generic_hid_polling_callback;
+	
+	// set the polling ended callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
+	
+	// set the deinit callback
+	hid_dev->subdrivers[hid_dev->subdriver_count].deinit = NULL;
+	
+	// set subdriver count
+	++hid_dev->subdriver_count;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_mapping_t *mapping)
+{
+	assert(hid_dev != NULL);
+	assert(hid_dev->usb_dev != NULL);
+	
+	return (hid_dev->usb_dev->descriptors.device.vendor_id 
+	    == mapping->vendor_id
+	    && hid_dev->usb_dev->descriptors.device.product_id 
+	    == mapping->product_id);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_mapping_t *mapping)
+{
+	assert(hid_dev != NULL);
+	assert(mapping != NULL);
+	
+	usb_hid_report_path_t *usage_path = usb_hid_report_path();
+	if (usage_path == NULL) {
+		usb_log_debug("Failed to create usage path.\n");
+		return false;
+	}
+	int i = 0;
+	while (mapping->usage_path[i].usage != 0 
+	    || mapping->usage_path[i].usage_page != 0) {
+		if (usb_hid_report_path_append_item(usage_path, 
+		    mapping->usage_path[i].usage_page, 
+		    mapping->usage_path[i].usage) != EOK) {
+			usb_log_debug("Failed to append to usage path.\n");
+			usb_hid_report_path_free(usage_path);
+			return false;
+		}
+		++i;
+	}
+	
+	assert(hid_dev->report != NULL);
+	
+	usb_log_debug("Compare flags: %d\n", mapping->compare);
+	
+	bool matches = false;
+	uint8_t report_id = mapping->report_id;
+
+	do {
+		usb_log_debug("Trying report id %u\n", report_id);
+		
+		if (report_id != 0) {
+			usb_hid_report_path_set_report_id(usage_path,
+				report_id);
+		}
+
+		usb_hid_report_field_t *field = usb_hid_report_get_sibling(
+		    hid_dev->report,
+		    NULL, usage_path, mapping->compare, 
+		    USB_HID_REPORT_TYPE_INPUT);
+		
+		usb_log_debug("Field: %p\n", field);
+
+		if (field != NULL) {
+			matches = true;
+			break;
+		}
+		
+		report_id = usb_hid_get_next_report_id(
+		    hid_dev->report, report_id,
+		    USB_HID_REPORT_TYPE_INPUT);
+	} while (!matches && report_id != 0);
+	
+	usb_hid_report_path_free(usage_path);
+	
+	return matches;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 
+    const usb_hid_subdriver_t **subdrivers, int count)
+{
+	int i;
+	
+	if (count <= 0) {
+		hid_dev->subdriver_count = 0;
+		hid_dev->subdrivers = NULL;
+		return EOK;
+	}
+	
+	// add one generic HID subdriver per device
+	
+	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) * 
+	    sizeof(usb_hid_subdriver_t));
+	if (hid_dev->subdrivers == NULL) {
+		return ENOMEM;
+	}
+	
+	for (i = 0; i < count; ++i) {
+		hid_dev->subdrivers[i].init = subdrivers[i]->init;
+		hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
+		hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
+		hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
+	}
+	
+	hid_dev->subdrivers[count].init = usb_generic_hid_init;
+	hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback;
+	hid_dev->subdrivers[count].deinit = NULL;
+	hid_dev->subdrivers[count].poll_end = NULL;
+	
+	hid_dev->subdriver_count = count + 1;
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL);
+	
+	const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
+	
+	int i = 0, count = 0;
+	const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
+
+	bool ids_matched;
+	bool matched;
+	
+	while (count < USB_HID_MAX_SUBDRIVERS &&
+	    (mapping->usage_path != NULL
+	    || mapping->vendor_id >= 0 || mapping->product_id >= 0)) {
+		// check the vendor & product ID
+		if (mapping->vendor_id >= 0 && mapping->product_id < 0) {
+			usb_log_warning("Missing Product ID for Vendor ID %d\n",
+			    mapping->vendor_id);
+			return EINVAL;
+		}
+		if (mapping->product_id >= 0 && mapping->vendor_id < 0) {
+			usb_log_warning("Missing Vendor ID for Product ID %d\n",
+			    mapping->product_id);
+			return EINVAL;
+		}
+		
+		ids_matched = false;
+		matched = false;
+		
+		if (mapping->vendor_id >= 0) {
+			assert(mapping->product_id >= 0);
+			usb_log_debug("Comparing device against vendor ID %u"
+			    " and product ID %u.\n", mapping->vendor_id,
+			    mapping->product_id);
+			if (usb_hid_ids_match(hid_dev, mapping)) {
+				usb_log_debug("IDs matched.\n");
+				ids_matched = true;
+			}
+		}
+		
+		if (mapping->usage_path != NULL) {
+			usb_log_debug("Comparing device against usage path.\n");
+			if (usb_hid_path_matches(hid_dev, mapping)) {
+				// does not matter if IDs were matched
+				matched = true;
+			}
+		} else {
+			// matched only if IDs were matched and there is no path
+			matched = ids_matched;
+		}
+		
+		if (matched) {
+			usb_log_debug("Subdriver matched.\n");
+			subdrivers[count++] = &mapping->subdriver;
+		}
+		
+		mapping = &usb_hid_subdrivers[++i];
+	}
+	
+	// we have all subdrivers determined, save them into the hid device
+	return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
+{
+	assert(hid_dev != NULL && dev != NULL);
+	
+	int rc = EOK;
+	
+	if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
+		usb_log_debug("Found keyboard endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
+	} else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
+		usb_log_debug("Found mouse endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
+	} else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
+		usb_log_debug("Found generic HID endpoint.\n");
+		// save the pipe index
+		hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
+	} else {
+		usb_log_error("None of supported endpoints found - probably"
+		    " not a supported device.\n");
+		rc = ENOTSUP;
+	}
+	
+	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
+{
+	assert(hid_dev != NULL && hid_dev->report != NULL);
+	
+	uint8_t report_id = 0;
+	size_t size;
+	
+	size_t max_size = 0;
+	
+	do {
+		usb_log_debug("Getting size of the report.\n");
+		size = usb_hid_report_byte_size(hid_dev->report, report_id, 
+		    USB_HID_REPORT_TYPE_INPUT);
+		usb_log_debug("Report ID: %u, size: %zu\n", report_id, size);
+		max_size = (size > max_size) ? size : max_size;
+		usb_log_debug("Getting next report ID\n");
+		report_id = usb_hid_get_next_report_id(hid_dev->report, 
+		    report_id, USB_HID_REPORT_TYPE_INPUT);
+	} while (report_id != 0);
+	
+	usb_log_debug("Max size of input report: %zu\n", max_size);
+	
+	hid_dev->max_input_report_size = max_size;
+	assert(hid_dev->input_report == NULL);
+	
+	hid_dev->input_report = malloc(max_size);
+	if (hid_dev->input_report == NULL) {
+		return ENOMEM;
+	}
+	memset(hid_dev->input_report, 0, max_size);
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+usb_hid_dev_t *usb_hid_new(void)
+{
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)calloc(1,
+	    sizeof(usb_hid_dev_t));
+	
+	if (hid_dev == NULL) {
+		usb_log_fatal("No memory!\n");
+		return NULL;
+	}
+	
+	hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
+	    usb_hid_report_t)));
+	if (hid_dev->report == NULL) {
+		usb_log_fatal("No memory!\n");
+		free(hid_dev);
+		return NULL;
+	}
+	
+	hid_dev->poll_pipe_index = -1;
+	
+	return hid_dev;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
+{
+	int rc, i;
+	
+	usb_log_debug("Initializing HID structure...\n");
+	
+	if (hid_dev == NULL) {
+		usb_log_error("Failed to init HID structure: no structure given"
+		    ".\n");
+		return EINVAL;
+	}
+	
+	if (dev == NULL) {
+		usb_log_error("Failed to init HID structure: no USB device"
+		    " given.\n");
+		return EINVAL;
+	}
+	
+	/* The USB device should already be initialized, save it in structure */
+	hid_dev->usb_dev = dev;
+	
+	rc = usb_hid_check_pipes(hid_dev, dev);
+	if (rc != EOK) {
+		return rc;
+	}
+		
+	/* Get the report descriptor and parse it. */
+	rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 
+	    hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
+	
+	bool fallback = false;
+	
+	if (rc == EOK) {
+		// try to find subdrivers that may want to handle this device
+		rc = usb_hid_find_subdrivers(hid_dev);
+		if (rc != EOK || hid_dev->subdriver_count == 0) {
+			// try to fall back to the boot protocol if available
+			usb_log_info("No subdrivers found to handle this"
+			    " device.\n");
+			fallback = true;
+			assert(hid_dev->subdrivers == NULL);
+			assert(hid_dev->subdriver_count == 0);
+		}
+	} else {
+		usb_log_error("Failed to parse Report descriptor.\n");
+		// try to fall back to the boot protocol if available
+		fallback = true;
+	}
+	
+	if (fallback) {
+		// fall back to boot protocol
+		switch (hid_dev->poll_pipe_index) {
+		case USB_HID_KBD_POLL_EP_NO:
+			usb_log_info("Falling back to kbd boot protocol.\n");
+			rc = usb_kbd_set_boot_protocol(hid_dev);
+			if (rc == EOK) {
+				rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
+			}
+			break;
+		case USB_HID_MOUSE_POLL_EP_NO:
+			usb_log_info("Falling back to mouse boot protocol.\n");
+			rc = usb_mouse_set_boot_protocol(hid_dev);
+			if (rc == EOK) {
+				rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
+			}
+			break;
+		default:
+			assert(hid_dev->poll_pipe_index 
+			    == USB_HID_GENERIC_POLL_EP_NO);
+			
+			usb_log_info("Falling back to generic HID driver.\n");
+			rc = usb_hid_set_generic_hid_subdriver(hid_dev);
+		}
+	}
+	
+	if (rc != EOK) {
+		usb_log_error("No subdriver for handling this device could be"
+		    " initialized: %s.\n", str_error(rc));
+		usb_log_debug("Subdriver count: %d\n", 
+		    hid_dev->subdriver_count);
+		
+	} else {
+		bool ok = false;
+		
+		usb_log_debug("Subdriver count: %d\n", 
+		    hid_dev->subdriver_count);
+		
+		for (i = 0; i < hid_dev->subdriver_count; ++i) {
+			if (hid_dev->subdrivers[i].init != NULL) {
+				usb_log_debug("Initializing subdriver %d.\n",i);
+				rc = hid_dev->subdrivers[i].init(hid_dev,
+				    &hid_dev->subdrivers[i].data);
+				if (rc != EOK) {
+					usb_log_warning("Failed to initialize"
+					    " HID subdriver structure.\n");
+				} else {
+					// at least one subdriver initialized
+					ok = true;
+				}
+			} else {
+				ok = true;
+			}
+		}
+		
+		rc = (ok) ? EOK : -1;	// what error to report
+	}
+	
+	
+	if (rc == EOK) {
+		// save max input report size and allocate space for the report
+		rc = usb_hid_init_report(hid_dev);
+		if (rc != EOK) {
+			usb_log_error("Failed to initialize input report buffer"
+			    ".\n");
+		}
+	}
+	
+	
+	return rc;
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
+    size_t buffer_size, void *arg)
+{
+	int i;
+	
+	if (dev == NULL || arg == NULL || buffer == NULL) {
+		usb_log_error("Missing arguments to polling callback.\n");
+		return false;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
+	
+	assert(hid_dev->input_report != NULL);
+	usb_log_debug("New data [%zu/%zu]: %s\n", buffer_size,
+	    hid_dev->max_input_report_size,
+	    usb_debug_str_buffer(buffer, buffer_size, 0));
+
+	if (hid_dev->max_input_report_size >= buffer_size) {
+		/*! @todo This should probably be atomic. */
+		memcpy(hid_dev->input_report, buffer, buffer_size);
+		hid_dev->input_report_size = buffer_size;
+		usb_hid_new_report(hid_dev);
+	}
+	
+	// parse the input report
+	
+	int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size, 
+	    &hid_dev->report_id);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error in usb_hid_parse_report():"
+		    "%s\n", str_error(rc));
+	}	
+	
+	bool cont = false;
+	
+	// continue if at least one of the subdrivers want to continue
+	for (i = 0; i < hid_dev->subdriver_count; ++i) {
+		if (hid_dev->subdrivers[i].poll != NULL
+		    && hid_dev->subdrivers[i].poll(hid_dev, 
+		        hid_dev->subdrivers[i].data)) {
+			cont = true;
+		}
+	}
+	
+	return cont;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, 
+     void *arg)
+{
+	int i; 
+	
+	if (dev == NULL || arg == NULL) {
+		return;
+	}
+	
+	usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
+	
+	for (i = 0; i < hid_dev->subdriver_count; ++i) {
+		if (hid_dev->subdrivers[i].poll_end != NULL) {
+			hid_dev->subdrivers[i].poll_end(hid_dev,
+			    hid_dev->subdrivers[i].data, reason);
+		}
+	}
+	
+	usb_hid_free(&hid_dev);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_hid_new_report(usb_hid_dev_t *hid_dev)
+{
+	++hid_dev->report_nr;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_hid_report_number(usb_hid_dev_t *hid_dev)
+{
+	return hid_dev->report_nr;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usb_hid_free(usb_hid_dev_t **hid_dev)
+{
+	int i;
+	
+	if (hid_dev == NULL || *hid_dev == NULL) {
+		return;
+	}
+	
+	usb_log_debug("Subdrivers: %p, subdriver count: %d\n", 
+	    (*hid_dev)->subdrivers, (*hid_dev)->subdriver_count);
+	
+	assert((*hid_dev)->subdrivers != NULL 
+	    || (*hid_dev)->subdriver_count == 0);
+	
+	for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
+		if ((*hid_dev)->subdrivers[i].deinit != NULL) {
+			(*hid_dev)->subdrivers[i].deinit(*hid_dev,
+			    (*hid_dev)->subdrivers[i].data);
+		}
+	}
+	
+	// free the subdrivers info
+	if ((*hid_dev)->subdrivers != NULL) {
+		free((*hid_dev)->subdrivers);
+	}
+
+	// destroy the parser
+	if ((*hid_dev)->report != NULL) {
+		usb_hid_free_report((*hid_dev)->report);
+	}
+
+	if ((*hid_dev)->report_desc != NULL) {
+		free((*hid_dev)->report_desc);
+	}
+
+	free(*hid_dev);
+	*hid_dev = NULL;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/usbhid.h
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/usbhid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * USB HID driver API.
+ */
+
+#ifndef USB_HID_USBHID_H_
+#define USB_HID_USBHID_H_
+
+#include <stdint.h>
+
+#include <usb/hid/hidparser.h>
+#include <ddf/driver.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+#include <usb/hid/hid.h>
+#include <bool.h>
+
+typedef struct usb_hid_dev usb_hid_dev_t;
+typedef struct usb_hid_subdriver usb_hid_subdriver_t;
+
+/** Subdriver initialization callback.
+ *
+ * @param dev Backing USB HID device.
+ * @param data Custom subdriver data (pointer where to store them).
+ * @return Error code.
+ */
+typedef int (*usb_hid_driver_init_t)(usb_hid_dev_t *dev, void **data);
+
+/** Subdriver deinitialization callback.
+ *
+ * @param dev Backing USB HID device.
+ * @param data Custom subdriver data.
+ */
+typedef void (*usb_hid_driver_deinit_t)(usb_hid_dev_t *dev, void *data);
+
+/** Subdriver callback on data from device.
+ *
+ * @param dev Backing USB HID device.
+ * @param data Custom subdriver data.
+ * @return Whether to continue polling (typically true always).
+ */
+typedef bool (*usb_hid_driver_poll_t)(usb_hid_dev_t *dev, void *data);
+
+/** Subdriver callback after communication with the device ceased.
+ *
+ * @param dev Backing USB HID device.
+ * @param data Custom subdriver data.
+ * @param ended_due_to_errors Whether communication ended due to errors in
+ *	communication (true) or deliberately by driver (false).
+ */
+typedef void (*usb_hid_driver_poll_ended_t)(usb_hid_dev_t *dev, void *data,
+    bool ended_due_to_errors);
+
+struct usb_hid_subdriver {
+	/** Function to be called when initializing HID device. */
+	usb_hid_driver_init_t init;
+	/** Function to be called when destroying the HID device structure. */
+	usb_hid_driver_deinit_t deinit;
+	/** Function to be called when data arrives from the device. */
+	usb_hid_driver_poll_t poll;
+	/** Function to be called when polling ends. */
+	usb_hid_driver_poll_ended_t poll_end;
+	/** Arbitrary data needed by the subdriver. */
+	void *data;
+};
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Structure for holding general HID device data.
+ */
+struct usb_hid_dev {
+	/** Structure holding generic USB device information. */
+	usb_device_t *usb_dev;
+	
+	/** Index of the polling pipe in usb_hid_endpoints array. */
+	int poll_pipe_index;
+	
+	/** Subdrivers. */
+	usb_hid_subdriver_t *subdrivers;
+	
+	/** Number of subdrivers. */
+	int subdriver_count;
+	
+	/** Report descriptor. */
+	uint8_t *report_desc;
+
+	/** Report descriptor size. */
+	size_t report_desc_size;
+	
+	/** HID Report parser. */
+	usb_hid_report_t *report;
+	
+	uint8_t report_id;
+	
+	uint8_t *input_report;
+	
+	size_t input_report_size;
+	size_t max_input_report_size;
+	
+	int report_nr;
+};
+
+/*----------------------------------------------------------------------------*/
+
+enum {
+	USB_HID_KBD_POLL_EP_NO = 0,
+	USB_HID_MOUSE_POLL_EP_NO = 1,
+	USB_HID_GENERIC_POLL_EP_NO = 2,
+	USB_HID_POLL_EP_COUNT = 3
+};
+
+usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1];
+
+/*----------------------------------------------------------------------------*/
+
+usb_hid_dev_t *usb_hid_new(void);
+
+int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
+
+bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
+    size_t buffer_size, void *arg);
+
+void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, 
+     void *arg);
+
+void usb_hid_new_report(usb_hid_dev_t *hid_dev);
+
+int usb_hid_report_number(usb_hid_dev_t *hid_dev);
+
+void usb_hid_free(usb_hid_dev_t **hid_dev);
+
+#endif /* USB_HID_USBHID_H_ */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhid/usbhid.ma
===================================================================
--- uspace/drv/bus/usb/usbhid/usbhid.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhid/usbhid.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,3 @@
+100 usb&interface&class=HID&subclass=0x01&protocol=0x01
+1000 usb&interface&class=HID&subclass=0x01&protocol=0x02
+100 usb&interface&class=HID
Index: uspace/drv/bus/usb/usbhub/Makefile
===================================================================
--- uspace/drv/bus/usb/usbhub/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbhub
+
+SOURCES = \
+	main.c \
+	utils.c \
+	usbhub.c \
+	ports.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbhub/main.c
===================================================================
--- uspace/drv/bus/usb/usbhub/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,96 @@
+/*
+ * 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 drvusbhub
+ * @{
+ */
+
+#include <ddf/driver.h>
+#include <errno.h>
+#include <async.h>
+#include <stdio.h>
+
+#include <usb/dev/driver.h>
+#include <usb/classes/classes.h>
+
+#include "usbhub.h"
+#include "usbhub_private.h"
+
+/** Hub status-change endpoint description.
+ *
+ * For more information see section 11.15.1 of USB 1.1 specification.
+ */
+static usb_endpoint_description_t hub_status_change_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HUB,
+	.interface_subclass = 0,
+	.interface_protocol = 0,
+	.flags = 0
+};
+
+/**
+ * usb hub driver operations
+ *
+ * The most important one is add_device, which is set to usb_hub_add_device.
+ */
+static usb_driver_ops_t usb_hub_driver_ops = {
+	.add_device = usb_hub_add_device
+};
+
+/**
+ * hub endpoints, excluding control endpoint
+ */
+static usb_endpoint_description_t *usb_hub_endpoints[] = {
+	&hub_status_change_endpoint_description,
+	NULL
+};
+
+/**
+ * static usb hub driver information
+ */
+static usb_driver_t usb_hub_driver = {
+	.name = NAME,
+	.ops = &usb_hub_driver_ops,
+	.endpoints = usb_hub_endpoints
+};
+
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS USB hub driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&usb_hub_driver);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/bus/usb/usbhub/port_status.h
===================================================================
--- uspace/drv/bus/usb/usbhub/port_status.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/port_status.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 drvusbhub
+ * @{
+ */
+
+#ifndef HUB_PORT_STATUS_H
+#define	HUB_PORT_STATUS_H
+
+#include <bool.h>
+#include <sys/types.h>
+#include <usb/dev/request.h>
+#include "usbhub_private.h"
+
+/**
+ * structure holding port status and changes flags.
+ * should not be accessed directly, use supplied getter/setter methods.
+ *
+ * For more information refer to table 11-15 in
+ * "Universal Serial Bus Specification Revision 1.1"
+ *
+ */
+typedef uint32_t usb_port_status_t;
+
+/**
+ * structure holding hub status and changes flags.
+ * should not be accessed directly, use supplied getter/setter methods.
+ *
+ * For more information refer to table 11.16.2.5 in
+ * "Universal Serial Bus Specification Revision 1.1"
+ *
+ */
+typedef uint32_t usb_hub_status_t;
+
+/**
+ * set values in request to be it a port status request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_port_status_request(
+    usb_device_request_setup_packet_t *request, uint16_t port) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
+	request->request = USB_HUB_REQUEST_GET_STATUS;
+	request->value = 0;
+	request->length = 4;
+}
+
+/**
+ * set values in request to be it a port status request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_hub_status_request(
+    usb_device_request_setup_packet_t *request) {
+	request->index = 0;
+	request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;
+	request->request = USB_HUB_REQUEST_GET_STATUS;
+	request->value = 0;
+	request->length = 4;
+}
+
+/**
+ * create request for usb hub port status
+ * @param port
+ * @return
+ */
+static inline usb_device_request_setup_packet_t *
+usb_hub_create_port_status_request(uint16_t port) {
+	usb_device_request_setup_packet_t *result =
+	    malloc(sizeof (usb_device_request_setup_packet_t));
+	usb_hub_set_port_status_request(result, port);
+	return result;
+}
+
+/**
+ * set the device request to be a port feature enable request
+ * @param request
+ * @param port
+ * @param feature_selector
+ */
+static inline void usb_hub_set_enable_port_feature_request(
+    usb_device_request_setup_packet_t *request, uint16_t port,
+    uint16_t feature_selector) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = feature_selector;
+	request->length = 0;
+}
+
+/**
+ * set the device request to be a port feature clear request
+ * @param request
+ * @param port
+ * @param feature_selector
+ */
+static inline void usb_hub_set_disable_port_feature_request(
+    usb_device_request_setup_packet_t *request, uint16_t port,
+    uint16_t feature_selector
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
+	request->value = feature_selector;
+	request->length = 0;
+}
+
+/**
+ * set the device request to be a port enable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_enable_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_C_PORT_ENABLE;
+	request->length = 0;
+}
+
+/**
+ * enable specified port
+ * @param port
+ * @return
+ */
+static inline usb_device_request_setup_packet_t *
+usb_hub_create_enable_port_request(uint16_t port) {
+	usb_device_request_setup_packet_t *result =
+	    malloc(sizeof (usb_device_request_setup_packet_t));
+	usb_hub_set_enable_port_request(result, port);
+	return result;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_disable_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_C_PORT_SUSPEND;
+	request->length = 0;
+}
+
+/**
+ * disable specified port
+ * @param port
+ * @return
+ */
+static inline usb_device_request_setup_packet_t *
+usb_hub_create_disable_port_request(uint16_t port) {
+	usb_device_request_setup_packet_t *result =
+	    malloc(sizeof (usb_device_request_setup_packet_t));
+	usb_hub_set_disable_port_request(result, port);
+	return result;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_reset_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_PORT_RESET;
+	request->length = 0;
+}
+
+/**
+ * disable specified port
+ * @param port
+ * @return
+ */
+static inline usb_device_request_setup_packet_t *
+usb_hub_create_reset_port_request(uint16_t port) {
+	usb_device_request_setup_packet_t *result =
+	    malloc(sizeof (usb_device_request_setup_packet_t));
+	usb_hub_set_reset_port_request(result, port);
+	return result;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_set_power_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_SET_FEATURE;
+	request->value = USB_HUB_FEATURE_PORT_POWER;
+	request->length = 0;
+}
+
+/**
+ * set the device request to be a port disable request
+ * @param request
+ * @param port
+ */
+static inline void usb_hub_unset_power_port_request(
+    usb_device_request_setup_packet_t *request, uint16_t port
+    ) {
+	request->index = port;
+	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
+	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
+	request->value = USB_HUB_FEATURE_PORT_POWER;
+	request->length = 0;
+}
+
+/**
+ * get i`th bit of port status
+ * 
+ * @param status
+ * @param idx
+ * @return
+ */
+static inline bool usb_port_is_status(usb_port_status_t status, int idx) {
+	return (status & (1 << idx)) != 0;
+}
+
+/**
+ * set i`th bit of port status
+ * 
+ * @param status
+ * @param idx
+ * @param value
+ */
+static inline void usb_port_status_set_bit(
+    usb_port_status_t * status, int idx, bool value) {
+	(*status) = value ?
+	    ((*status) | (1 << (idx))) :
+	    ((*status)&(~(1 << (idx))));
+}
+
+/**
+ * get i`th bit of hub status
+ * 
+ * @param status
+ * @param idx
+ * @return
+ */
+static inline bool usb_hub_is_status(usb_hub_status_t status, int idx) {
+	return (status & (1 << idx)) != 0;
+}
+
+/**
+ * set i`th bit of hub status
+ * 
+ * @param status
+ * @param idx
+ * @param value
+ */
+static inline void usb_hub_status_set_bit(
+    usb_hub_status_t *status, int idx, bool value) {
+	(*status) = value ?
+	    ((*status) | (1 << (idx))) :
+	    ((*status)&(~(1 << (idx))));
+}
+
+/**
+ * low speed device on the port indicator
+ * 
+ * @param status
+ * @return true if low speed device is attached
+ */
+static inline bool usb_port_low_speed(usb_port_status_t status) {
+	return usb_port_is_status(status, 9);
+}
+
+/**
+ * set low speed device connected bit in port status
+ * 
+ * @param status
+ * @param low_speed value of the bit
+ */
+static inline void usb_port_set_low_speed(usb_port_status_t *status, bool low_speed) {
+	usb_port_status_set_bit(status, 9, low_speed);
+}
+
+//high speed device attached
+
+/**
+ * high speed device on the port indicator
+ *
+ * @param status
+ * @return true if high speed device is on port
+ */
+static inline bool usb_port_high_speed(usb_port_status_t status) {
+	return usb_port_is_status(status, 10);
+}
+
+/**
+ * set high speed device bit in port status
+ *
+ * @param status
+ * @param high_speed value of the bit
+ */
+static inline void usb_port_set_high_speed(usb_port_status_t *status, bool high_speed) {
+	usb_port_status_set_bit(status, 10, high_speed);
+}
+
+/**
+ * speed getter for port status
+ *
+ * @param status
+ * @return speed of usb device (for more see usb specification)
+ */
+static inline usb_speed_t usb_port_speed(usb_port_status_t status) {
+	if (usb_port_low_speed(status))
+		return USB_SPEED_LOW;
+	if (usb_port_high_speed(status))
+		return USB_SPEED_HIGH;
+	return USB_SPEED_FULL;
+}
+
+
+
+#endif	/* HUB_PORT_STATUS_H */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/ports.c
===================================================================
--- uspace/drv/bus/usb/usbhub/ports.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/ports.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2011 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 drvusbhub
+ * @{
+ */
+/** @file
+ * Hub ports functions.
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <str_error.h>
+#include <inttypes.h>
+#include <fibril_synch.h>
+
+#include <usb/debug.h>
+
+#include "ports.h"
+#include "usbhub.h"
+#include "usbhub_private.h"
+#include "port_status.h"
+
+/** Information for fibril for device discovery. */
+struct add_device_phase1 {
+	usb_hub_info_t *hub;
+	size_t port;
+	usb_speed_t speed;
+};
+
+/**
+ * count of port status changes that are not explicitly handled by
+ * any function here and must be cleared by hand
+ */
+static const unsigned int non_handled_changes_count = 2;
+
+/**
+ * port status changes that are not explicitly handled by
+ * any function here and must be cleared by hand
+ */
+static const int non_handled_changes[] = {
+	USB_HUB_FEATURE_C_PORT_ENABLE,
+	USB_HUB_FEATURE_C_PORT_SUSPEND
+};
+
+static void usb_hub_removed_device(
+    usb_hub_info_t *hub, uint16_t port);
+
+static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
+    uint16_t port, uint32_t status);
+
+static void usb_hub_port_over_current(usb_hub_info_t *hub,
+    uint16_t port, uint32_t status);
+
+static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
+    usb_port_status_t *status);
+
+static int enable_port_callback(int port_no, void *arg);
+
+static int add_device_phase1_worker_fibril(void *arg);
+
+static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
+    usb_speed_t speed);
+
+/**
+ * Process interrupts on given hub port
+ *
+ * Accepts connection, over current and port reset change.
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
+    uint16_t port) {
+	usb_log_debug("Interrupt at port %zu\n", (size_t) port);
+	//determine type of change
+	//usb_pipe_t *pipe = hub->control_pipe;
+
+	int opResult;
+
+	usb_port_status_t status;
+	opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);
+	if (opResult != EOK) {
+		usb_log_error("Failed to get port %zu status: %s.\n",
+		    (size_t) port, str_error(opResult));
+		return;
+	}
+	//connection change
+	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {
+		bool device_connected = usb_port_is_status(status,
+		    USB_HUB_FEATURE_PORT_CONNECTION);
+		usb_log_debug("Connection change on port %zu: %s.\n",
+		    (size_t) port,
+		    device_connected ? "device attached" : "device removed");
+
+		if (device_connected) {
+			opResult = create_add_device_fibril(hub, port,
+			    usb_port_speed(status));
+			if (opResult != EOK) {
+				usb_log_error(
+				    "Cannot handle change on port %zu: %s.\n",
+				    (size_t) port, str_error(opResult));
+			}
+		} else {
+			usb_hub_removed_device(hub, port);
+		}
+	}
+	//over current
+	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {
+		//check if it was not auto-resolved
+		usb_log_debug("Overcurrent change on port\n");
+		usb_hub_port_over_current(hub, port, status);
+	}
+	//port reset
+	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {
+		usb_hub_port_reset_completed(hub, port, status);
+	}
+	usb_log_debug("Port %d status 0x%08" PRIx32 "\n", (int) port, status);
+
+	usb_port_status_set_bit(
+	    &status, USB_HUB_FEATURE_C_PORT_CONNECTION, false);
+	usb_port_status_set_bit(
+	    &status, USB_HUB_FEATURE_C_PORT_RESET, false);
+	usb_port_status_set_bit(
+	    &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT, false);
+
+	//clearing not yet handled changes	
+	unsigned int feature_idx;
+	for (feature_idx = 0;
+	    feature_idx < non_handled_changes_count;
+	    ++feature_idx) {
+		unsigned int bit_idx = non_handled_changes[feature_idx];
+		if (status & (1 << bit_idx)) {
+			usb_log_info(
+			    "There was not yet handled change on port %d: %d"
+			    ";clearing it\n",
+			    port, bit_idx);
+			int opResult = usb_hub_clear_port_feature(
+			    hub->control_pipe,
+			    port, bit_idx);
+			if (opResult != EOK) {
+				usb_log_warning(
+				    "Could not clear port flag %d: %s\n",
+				    bit_idx, str_error(opResult)
+				    );
+			}
+			usb_port_status_set_bit(
+			    &status, bit_idx, false);
+		}
+	}
+	if (status >> 16) {
+		usb_log_info("There is still some unhandled change %X\n",
+		    status);
+	}
+}
+
+/**
+ * routine called when a device on port has been removed
+ *
+ * If the device on port had default address, it releases default address.
+ * Otherwise does not do anything, because DDF does not allow to remove device
+ * from it`s device tree.
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+static void usb_hub_removed_device(
+    usb_hub_info_t *hub, uint16_t port) {
+
+	int opResult = usb_hub_clear_port_feature(hub->control_pipe,
+	    port, USB_HUB_FEATURE_C_PORT_CONNECTION);
+	if (opResult != EOK) {
+		usb_log_warning("Could not clear port-change-connection flag\n");
+	}
+	/** \TODO remove device from device manager - not yet implemented in
+	 * devide manager
+	 */
+
+	//close address
+
+	usb_hub_port_t *the_port = hub->ports + port;
+
+	fibril_mutex_lock(&hub->port_mutex);
+
+	if (the_port->attached_device.address >= 0) {
+		usb_log_warning("Device unplug on `%s' (port %zu): " \
+		    "not implemented.\n", hub->usb_device->ddf_dev->name,
+		    (size_t) port);
+		the_port->attached_device.address = -1;
+		the_port->attached_device.handle = 0;
+	} else {
+		usb_log_warning("Device removed before being registered.\n");
+
+		/*
+		 * Device was removed before port reset completed.
+		 * We will announce a failed port reset to unblock the
+		 * port reset callback from new device wrapper.
+		 */
+		fibril_mutex_lock(&the_port->reset_mutex);
+		the_port->reset_completed = true;
+		the_port->reset_okay = false;
+		fibril_condvar_broadcast(&the_port->reset_cv);
+		fibril_mutex_unlock(&the_port->reset_mutex);
+	}
+
+	fibril_mutex_unlock(&hub->port_mutex);
+}
+
+/**
+ * Process port reset change
+ *
+ * After this change port should be enabled, unless some problem occured.
+ * This functions triggers second phase of enabling new device.
+ * @param hub
+ * @param port
+ * @param status
+ */
+static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
+    uint16_t port, uint32_t status) {
+	usb_log_debug("Port %zu reset complete.\n", (size_t) port);
+	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {
+		/* Finalize device adding. */
+		usb_hub_port_t *the_port = hub->ports + port;
+		fibril_mutex_lock(&the_port->reset_mutex);
+		the_port->reset_completed = true;
+		the_port->reset_okay = true;
+		fibril_condvar_broadcast(&the_port->reset_cv);
+		fibril_mutex_unlock(&the_port->reset_mutex);
+	} else {
+		usb_log_warning(
+		    "Port %zu reset complete but port not enabled.\n",
+		    (size_t) port);
+	}
+	/* Clear the port reset change. */
+	int rc = usb_hub_clear_port_feature(hub->control_pipe,
+	    port, USB_HUB_FEATURE_C_PORT_RESET);
+	if (rc != EOK) {
+		usb_log_error("Failed to clear port %d reset feature: %s.\n",
+		    port, str_error(rc));
+	}
+}
+
+/**
+ * Process over current condition on port.
+ *
+ * Turn off the power on the port.
+ *
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+static void usb_hub_port_over_current(usb_hub_info_t *hub,
+    uint16_t port, uint32_t status) {
+	int opResult;
+	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)) {
+		opResult = usb_hub_clear_port_feature(hub->control_pipe,
+		    port, USB_HUB_FEATURE_PORT_POWER);
+		if (opResult != EOK) {
+			usb_log_error("Cannot power off port %d; %s\n",
+			    port, str_error(opResult));
+		}
+	} else {
+		opResult = usb_hub_set_port_feature(hub->control_pipe,
+		    port, USB_HUB_FEATURE_PORT_POWER);
+		if (opResult != EOK) {
+			usb_log_error("Cannot power on port %d; %s\n",
+			    port, str_error(opResult));
+		}
+	}
+}
+
+/** Retrieve port status.
+ *
+ * @param[in] ctrl_pipe Control pipe to use.
+ * @param[in] port Port number (starting at 1).
+ * @param[out] status Where to store the port status.
+ * @return Error code.
+ */
+static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
+    usb_port_status_t *status) {
+	size_t recv_size;
+	usb_device_request_setup_packet_t request;
+	usb_port_status_t status_tmp;
+
+	usb_hub_set_port_status_request(&request, port);
+	int rc = usb_pipe_control_read(ctrl_pipe,
+	    &request, sizeof (usb_device_request_setup_packet_t),
+	    &status_tmp, sizeof (status_tmp), &recv_size);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (recv_size != sizeof (status_tmp)) {
+		return ELIMIT;
+	}
+
+	if (status != NULL) {
+		*status = status_tmp;
+	}
+
+	return EOK;
+}
+
+/** Callback for enabling a specific port.
+ *
+ * We wait on a CV until port is reseted.
+ * That is announced via change on interrupt pipe.
+ *
+ * @param port_no Port number (starting at 1).
+ * @param arg Custom argument, points to @c usb_hub_info_t.
+ * @return Error code.
+ */
+static int enable_port_callback(int port_no, void *arg) {
+	usb_hub_info_t *hub = arg;
+	int rc;
+	usb_device_request_setup_packet_t request;
+	usb_hub_port_t *my_port = hub->ports + port_no;
+
+	usb_hub_set_reset_port_request(&request, port_no);
+	rc = usb_pipe_control_write(hub->control_pipe,
+	    &request, sizeof (request), NULL, 0);
+	if (rc != EOK) {
+		usb_log_warning("Port reset failed: %s.\n", str_error(rc));
+		return rc;
+	}
+
+	/*
+	 * Wait until reset completes.
+	 */
+	fibril_mutex_lock(&my_port->reset_mutex);
+	while (!my_port->reset_completed) {
+		fibril_condvar_wait(&my_port->reset_cv, &my_port->reset_mutex);
+	}
+	fibril_mutex_unlock(&my_port->reset_mutex);
+
+	if (my_port->reset_okay) {
+		return EOK;
+	} else {
+		return ESTALL;
+	}
+}
+
+/** Fibril for adding a new device.
+ *
+ * Separate fibril is needed because the port reset completion is announced
+ * via interrupt pipe and thus we cannot block here.
+ *
+ * @param arg Pointer to struct add_device_phase1.
+ * @return 0 Always.
+ */
+static int add_device_phase1_worker_fibril(void *arg) {
+	struct add_device_phase1 *data
+	    = (struct add_device_phase1 *) arg;
+
+	usb_address_t new_address;
+	devman_handle_t child_handle;
+
+	int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
+	    &data->hub->connection, data->speed,
+	    enable_port_callback, (int) data->port, data->hub,
+	    &new_address, &child_handle,
+	    NULL, NULL, NULL);
+
+	if (rc != EOK) {
+		usb_log_error("Failed registering device on port %zu: %s.\n",
+		    data->port, str_error(rc));
+		goto leave;
+	}
+
+	fibril_mutex_lock(&data->hub->port_mutex);
+	data->hub->ports[data->port].attached_device.handle = child_handle;
+	data->hub->ports[data->port].attached_device.address = new_address;
+	fibril_mutex_unlock(&data->hub->port_mutex);
+
+	usb_log_info("Detected new device on `%s' (port %zu), "
+	    "address %d (handle %" PRIun ").\n",
+	    data->hub->usb_device->ddf_dev->name, data->port,
+	    new_address, child_handle);
+
+leave:
+	free(arg);
+
+	fibril_mutex_lock(&data->hub->pending_ops_mutex);
+	assert(data->hub->pending_ops_count > 0);
+	data->hub->pending_ops_count--;
+	fibril_condvar_signal(&data->hub->pending_ops_cv);
+	fibril_mutex_unlock(&data->hub->pending_ops_mutex);
+
+
+	return EOK;
+}
+
+/** Start device adding when connection change is detected.
+ *
+ * This fires a new fibril to complete the device addition.
+ *
+ * @param hub Hub where the change occured.
+ * @param port Port index (starting at 1).
+ * @param speed Speed of the device.
+ * @return Error code.
+ */
+static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
+    usb_speed_t speed) {
+	struct add_device_phase1 *data
+	    = malloc(sizeof (struct add_device_phase1));
+	if (data == NULL) {
+		return ENOMEM;
+	}
+	data->hub = hub;
+	data->port = port;
+	data->speed = speed;
+
+	usb_hub_port_t *the_port = hub->ports + port;
+
+	fibril_mutex_lock(&the_port->reset_mutex);
+	the_port->reset_completed = false;
+	fibril_mutex_unlock(&the_port->reset_mutex);
+
+	int rc = usb_hub_clear_port_feature(hub->control_pipe, port,
+	    USB_HUB_FEATURE_C_PORT_CONNECTION);
+	if (rc != EOK) {
+		free(data);
+		usb_log_warning("Failed to clear port change flag: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
+	if (fibril == 0) {
+		free(data);
+		return ENOMEM;
+	}
+	fibril_mutex_lock(&hub->pending_ops_mutex);
+	hub->pending_ops_count++;
+	fibril_mutex_unlock(&hub->pending_ops_mutex);
+	fibril_add_ready(fibril);
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/ports.h
===================================================================
--- uspace/drv/bus/usb/usbhub/ports.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/ports.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011 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 drvusbhub
+ * @{
+ */
+/** @file
+ * Hub ports related functions.
+ */
+#ifndef DRV_USBHUB_PORTS_H
+#define DRV_USBHUB_PORTS_H
+
+#include <usb/dev/driver.h>
+#include <usb/dev/hub.h>
+
+typedef struct usb_hub_info_t usb_hub_info_t;
+
+/** Information about single port on a hub. */
+typedef struct {
+	/** Mutex needed by CV for checking port reset. */
+	fibril_mutex_t reset_mutex;
+	/** CV for waiting to port reset completion. */
+	fibril_condvar_t reset_cv;
+	/** Whether port reset is completed.
+	 * Guarded by @c reset_mutex.
+	 */
+	bool reset_completed;
+	/** Whether to announce the port reset as successful. */
+	bool reset_okay;
+
+	/** Information about attached device. */
+	usb_hc_attached_device_t attached_device;
+} usb_hub_port_t;
+
+/** Initialize hub port information.
+ *
+ * @param port Port to be initialized.
+ */
+static inline void usb_hub_port_init(usb_hub_port_t *port) {
+	port->attached_device.address = -1;
+	port->attached_device.handle = 0;
+	fibril_mutex_initialize(&port->reset_mutex);
+	fibril_condvar_initialize(&port->reset_cv);
+}
+
+
+void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
+	uint16_t port);
+
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * @brief usb hub main functionality
+ */
+
+#include <ddf/driver.h>
+#include <bool.h>
+#include <errno.h>
+#include <str_error.h>
+#include <inttypes.h>
+
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/descriptor.h>
+#include <usb/dev/recognise.h>
+#include <usb/dev/request.h>
+#include <usb/classes/hub.h>
+#include <usb/dev/poll.h>
+#include <stdio.h>
+
+#include "usbhub.h"
+#include "usbhub_private.h"
+#include "port_status.h"
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/classes/classes.h>
+
+
+static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev);
+
+static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info);
+
+static int usb_hub_set_configuration(usb_hub_info_t *hub_info);
+
+static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info);
+
+static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
+    usb_hub_status_t status);
+
+static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
+    usb_hub_status_t status);
+
+static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info);
+
+static void usb_hub_polling_terminated_callback(usb_device_t *device,
+    bool was_error, void *data);
+
+
+//*********************************************
+//
+//  hub driver code, initialization
+//
+//*********************************************
+
+/**
+ * Initialize hub device driver fibril
+ *
+ * Creates hub representation and fibril that periodically checks hub`s status.
+ * Hub representation is passed to the fibril.
+ * @param usb_dev generic usb device information
+ * @return error code
+ */
+int usb_hub_add_device(usb_device_t *usb_dev) {
+	if (!usb_dev) return EINVAL;
+	usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev);
+	//create hc connection
+	usb_log_debug("Initializing USB wire abstraction.\n");
+	int opResult = usb_hc_connection_initialize_from_device(
+	    &hub_info->connection,
+	    hub_info->usb_device->ddf_dev);
+	if (opResult != EOK) {
+		usb_log_error("Could not initialize connection to device, "
+		    " %s\n",
+		    str_error(opResult));
+		free(hub_info);
+		return opResult;
+	}
+
+	//set hub configuration
+	opResult = usb_hub_set_configuration(hub_info);
+	if (opResult != EOK) {
+		usb_log_error("Could not set hub configuration, %s\n",
+		    str_error(opResult));
+		free(hub_info);
+		return opResult;
+	}
+	//get port count and create attached_devs
+	opResult = usb_hub_process_hub_specific_info(hub_info);
+	if (opResult != EOK) {
+		usb_log_error("Could process hub specific info, %s\n",
+		    str_error(opResult));
+		free(hub_info);
+		return opResult;
+	}
+
+	usb_log_debug("Creating 'hub' function in DDF.\n");
+	ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
+	    fun_exposed, "hub");
+	assert(hub_fun != NULL);
+	hub_fun->ops = NULL;
+
+	opResult = ddf_fun_bind(hub_fun);
+	assert(opResult == EOK);
+	opResult = ddf_fun_add_to_category(hub_fun, "hub");
+	assert(opResult == EOK);
+
+	opResult = usb_hub_start_hub_fibril(hub_info);
+	if (opResult != EOK)
+		free(hub_info);
+	return opResult;
+}
+
+/** Callback for polling hub for changes.
+ *
+ * @param dev Device where the change occured.
+ * @param change_bitmap Bitmap of changed ports.
+ * @param change_bitmap_size Size of the bitmap in bytes.
+ * @param arg Custom argument, points to @c usb_hub_info_t.
+ * @return Whether to continue polling.
+ */
+bool hub_port_changes_callback(usb_device_t *dev,
+    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
+	usb_log_debug("hub_port_changes_callback\n");
+	usb_hub_info_t *hub = (usb_hub_info_t *) arg;
+
+	/* FIXME: check that we received enough bytes. */
+	if (change_bitmap_size == 0) {
+		goto leave;
+	}
+
+	bool change;
+	change = ((uint8_t*) change_bitmap)[0] & 1;
+	if (change) {
+		usb_hub_process_global_interrupt(hub);
+	}
+
+	size_t port;
+	for (port = 1; port < hub->port_count + 1; port++) {
+		bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
+		if (change) {
+			usb_hub_process_port_interrupt(hub, port);
+		}
+	}
+leave:
+	/* FIXME: proper interval. */
+	async_usleep(1000 * 250);
+
+	return true;
+}
+
+
+//*********************************************
+//
+//  support functions
+//
+//*********************************************
+
+/**
+ * create usb_hub_info_t structure
+ *
+ * Does only basic copying of known information into new structure.
+ * @param usb_dev usb device structure
+ * @return basic usb_hub_info_t structure
+ */
+static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev) {
+	usb_hub_info_t * result = malloc(sizeof (usb_hub_info_t));
+	if (!result) return NULL;
+	result->usb_device = usb_dev;
+	result->status_change_pipe = usb_dev->pipes[0].pipe;
+	result->control_pipe = &usb_dev->ctrl_pipe;
+	result->is_default_address_used = false;
+
+	result->ports = NULL;
+	result->port_count = (size_t) - 1;
+	fibril_mutex_initialize(&result->port_mutex);
+
+	fibril_mutex_initialize(&result->pending_ops_mutex);
+	fibril_condvar_initialize(&result->pending_ops_cv);
+	result->pending_ops_count = 0;
+	return result;
+}
+
+/**
+ * Load hub-specific information into hub_info structure and process if needed
+ *
+ * Particularly read port count and initialize structure holding port
+ * information. If there are non-removable devices, start initializing them.
+ * This function is hub-specific and should be run only after the hub is
+ * configured using usb_hub_set_configuration function.
+ * @param hub_info hub representation
+ * @return error code
+ */
+int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
+{
+	// get hub descriptor
+	usb_log_debug("Retrieving descriptor\n");
+	uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
+	int opResult;
+
+	size_t received_size;
+	opResult = usb_request_get_descriptor(hub_info->control_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
+	    USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
+
+	if (opResult != EOK) {
+		usb_log_error("Failed to receive hub descriptor: %s.\n",
+		    str_error(opResult));
+		return opResult;
+	}
+	usb_log_debug2("Parsing descriptor\n");
+	usb_hub_descriptor_t descriptor;
+	opResult = usb_deserialize_hub_desriptor(
+	        serialized_descriptor, received_size, &descriptor);
+	if (opResult != EOK) {
+		usb_log_error("Could not parse descriptor: %s\n",
+		    str_error(opResult));
+		return opResult;
+	}
+	usb_log_debug("Setting port count to %d.\n", descriptor.ports_count);
+	hub_info->port_count = descriptor.ports_count;
+
+	hub_info->ports =
+	    malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1));
+	if (!hub_info->ports) {
+		return ENOMEM;
+	}
+
+	size_t port;
+	for (port = 0; port < hub_info->port_count + 1; ++port) {
+		usb_hub_port_init(&hub_info->ports[port]);
+	}
+
+	const bool is_power_switched =
+	    !(descriptor.hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
+	if (is_power_switched) {
+		usb_log_debug("Hub power switched\n");
+		const bool per_port_power = descriptor.hub_characteristics
+		    & HUB_CHAR_POWER_PER_PORT_FLAG;
+
+		for (port = 1; port <= hub_info->port_count; ++port) {
+			usb_log_debug("Powering port %zu.\n", port);
+			opResult = usb_hub_set_port_feature(
+			    hub_info->control_pipe,
+			    port, USB_HUB_FEATURE_PORT_POWER);
+			if (opResult != EOK) {
+				usb_log_error("Cannot power on port %zu: %s.\n",
+				    port, str_error(opResult));
+			} else {
+				if (!per_port_power) {
+					usb_log_debug(
+					    "Ganged power switching mode, "
+					    "one port is enough.\n");
+					break;
+				}
+			}
+		}
+
+	} else {
+		usb_log_debug("Power not switched, not going to be powered\n");
+	}
+	return EOK;
+}
+
+/**
+ * Set configuration of hub
+ *
+ * Check whether there is at least one configuration and sets the first one.
+ * This function should be run prior to running any hub-specific action.
+ * @param hub_info hub representation
+ * @return error code
+ */
+static int usb_hub_set_configuration(usb_hub_info_t *hub_info) {
+	//device descriptor
+	usb_standard_device_descriptor_t *std_descriptor
+	    = &hub_info->usb_device->descriptors.device;
+	usb_log_debug("Hub has %d configurations\n",
+	    std_descriptor->configuration_count);
+	if (std_descriptor->configuration_count < 1) {
+		usb_log_error("There are no configurations available\n");
+		return EINVAL;
+	}
+
+	usb_standard_configuration_descriptor_t *config_descriptor
+	    = (usb_standard_configuration_descriptor_t *)
+	    hub_info->usb_device->descriptors.configuration;
+
+	/* Set configuration. */
+	int opResult = usb_request_set_configuration(
+	    &hub_info->usb_device->ctrl_pipe,
+	    config_descriptor->configuration_number);
+
+	if (opResult != EOK) {
+		usb_log_error("Failed to set hub configuration: %s.\n",
+		    str_error(opResult));
+		return opResult;
+	}
+	usb_log_debug("\tUsed configuration %d\n",
+	    config_descriptor->configuration_number);
+
+	return EOK;
+}
+
+/**
+ * create and start fibril with hub control loop
+ *
+ * Before the fibril is started, the control pipe and host controller
+ * connection of the hub is open.
+ *
+ * @param hub_info hub representing structure
+ * @return error code
+ */
+static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info) {
+	int rc;
+
+	rc = usb_device_auto_poll(hub_info->usb_device, 0,
+	    hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
+	    usb_hub_polling_terminated_callback, hub_info);
+	if (rc != EOK) {
+		usb_log_error("Failed to create polling fibril: %s.\n",
+		    str_error(rc));
+		free(hub_info);
+		return rc;
+	}
+
+	usb_log_info("Controlling hub `%s' (%zu ports).\n",
+	    hub_info->usb_device->ddf_dev->name, hub_info->port_count);
+	return EOK;
+}
+
+//*********************************************
+//
+//  change handling functions
+//
+//*********************************************
+
+/**
+ * process hub over current change
+ *
+ * This means either to power off the hub or power it on.
+ * @param hub_info hub instance
+ * @param status hub status bitmask
+ * @return error code
+ */
+static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
+    usb_hub_status_t status) {
+	int opResult;
+	if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) {
+		//poweroff all ports
+		unsigned int port;
+		for (port = 1; port <= hub_info->port_count; ++port) {
+			opResult = usb_hub_clear_port_feature(
+			    hub_info->control_pipe, port,
+			    USB_HUB_FEATURE_PORT_POWER);
+			if (opResult != EOK) {
+				usb_log_warning(
+				    "Cannot power off port %d;  %s\n",
+				    port, str_error(opResult));
+			}
+		}
+	} else {
+		//power all ports
+		unsigned int port;
+		for (port = 1; port <= hub_info->port_count; ++port) {
+			opResult = usb_hub_set_port_feature(
+			    hub_info->control_pipe, port,
+			    USB_HUB_FEATURE_PORT_POWER);
+			if (opResult != EOK) {
+				usb_log_warning(
+				    "Cannot power off port %d;  %s\n",
+				    port, str_error(opResult));
+			}
+		}
+	}
+	return opResult;
+}
+
+/**
+ * process hub local power change
+ *
+ * This change is ignored.
+ * @param hub_info hub instance
+ * @param status hub status bitmask
+ * @return error code
+ */
+static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
+    usb_hub_status_t status) {
+	int opResult = EOK;
+	opResult = usb_hub_clear_feature(hub_info->control_pipe,
+	    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
+	if (opResult != EOK) {
+		usb_log_error("Cannnot clear hub power change flag: "
+		    "%s\n",
+		    str_error(opResult));
+	}
+	return opResult;
+}
+
+/**
+ * process hub interrupts
+ *
+ * The change can be either in the over-current condition or
+ * local-power change.
+ * @param hub_info hub instance
+ */
+static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) {
+	usb_log_debug("Global interrupt on a hub\n");
+	usb_pipe_t *pipe = hub_info->control_pipe;
+	int opResult;
+
+	usb_port_status_t status;
+	size_t rcvd_size;
+	usb_device_request_setup_packet_t request;
+	//int opResult;
+	usb_hub_set_hub_status_request(&request);
+	//endpoint 0
+
+	opResult = usb_pipe_control_read(
+	    pipe,
+	    &request, sizeof (usb_device_request_setup_packet_t),
+	    &status, 4, &rcvd_size
+	    );
+	if (opResult != EOK) {
+		usb_log_error("Could not get hub status: %s\n",
+		    str_error(opResult));
+		return;
+	}
+	if (rcvd_size != sizeof (usb_port_status_t)) {
+		usb_log_error("Received status has incorrect size\n");
+		return;
+	}
+	//port reset
+	if (
+	    usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
+		usb_process_hub_over_current(hub_info, status);
+	}
+	if (
+	    usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
+		usb_process_hub_local_power_change(hub_info, status);
+	}
+}
+
+/**
+ * callback called from hub polling fibril when the fibril terminates
+ *
+ * Should perform a cleanup - deletes hub_info.
+ * @param device usb device afected
+ * @param was_error indicates that the fibril is stoped due to an error
+ * @param data pointer to usb_hub_info_t structure
+ */
+static void usb_hub_polling_terminated_callback(usb_device_t *device,
+    bool was_error, void *data) {
+	usb_hub_info_t * hub = data;
+	assert(hub);
+
+	fibril_mutex_lock(&hub->pending_ops_mutex);
+
+	/* The device is dead. However there might be some pending operations
+	 * that we need to wait for.
+	 * One of them is device adding in progress.
+	 * The respective fibril is probably waiting for status change
+	 * in port reset (port enable) callback.
+	 * Such change would never come (otherwise we would not be here).
+	 * Thus, we would flush all pending port resets.
+	 */
+	if (hub->pending_ops_count > 0) {
+		fibril_mutex_lock(&hub->port_mutex);
+		size_t port;
+		for (port = 0; port < hub->port_count; port++) {
+			usb_hub_port_t *the_port = hub->ports + port;
+			fibril_mutex_lock(&the_port->reset_mutex);
+			the_port->reset_completed = true;
+			the_port->reset_okay = false;
+			fibril_condvar_broadcast(&the_port->reset_cv);
+			fibril_mutex_unlock(&the_port->reset_mutex);
+		}
+		fibril_mutex_unlock(&hub->port_mutex);
+	}
+	/* And now wait for them. */
+	while (hub->pending_ops_count > 0) {
+		fibril_condvar_wait(&hub->pending_ops_cv,
+		    &hub->pending_ops_mutex);
+	}
+	fibril_mutex_unlock(&hub->pending_ops_mutex);
+
+	usb_device_destroy(hub->usb_device);
+
+	free(hub->ports);
+	free(hub);
+}
+
+
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/usbhub.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/usbhub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,114 @@
+/*
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * @brief Hub driver.
+ */
+#ifndef DRV_USBHUB_USBHUB_H
+#define DRV_USBHUB_USBHUB_H
+
+#include <ipc/devman.h>
+#include <ddf/driver.h>
+
+#include <usb/dev/hub.h>
+#include <usb/classes/hub.h>
+
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+
+#include <fibril_synch.h>
+
+#define NAME "usbhub"
+
+#include "ports.h"
+
+/** Information about attached hub. */
+struct usb_hub_info_t {
+	/** Number of ports. */
+	size_t port_count;
+
+	/** attached device handles, for each port one */
+	usb_hub_port_t *ports;
+
+	fibril_mutex_t port_mutex;
+
+	/** connection to hcd */
+	usb_hc_connection_t connection;
+
+	/** default address is used indicator
+	 *
+	 * If default address is requested by this device, it cannot
+	 * be requested by the same hub again, otherwise a deadlock will occur.
+	 */
+	bool is_default_address_used;
+
+	/** convenience pointer to status change pipe
+	 *
+	 * Status change pipe is initialized in usb_device structure. This is
+	 * pointer into this structure, so that it does not have to be
+	 * searched again and again for the 'right pipe'.
+	 */
+	usb_pipe_t * status_change_pipe;
+
+	/** convenience pointer to control pipe
+	 *
+	 * Control pipe is initialized in usb_device structure. This is
+	 * pointer into this structure, so that it does not have to be
+	 * searched again and again for the 'right pipe'.
+	 */
+	usb_pipe_t * control_pipe;
+
+	/** generic usb device data*/
+	usb_device_t * usb_device;
+
+	/** Number of pending operations on the mutex to prevent shooting
+	 * ourselves in the foot.
+	 * When the hub is disconnected but we are in the middle of some
+	 * operation, we cannot destroy this structure right away because
+	 * the pending operation might use it.
+	 */
+	size_t pending_ops_count;
+	/** Guard for pending_ops_count. */
+	fibril_mutex_t pending_ops_mutex;
+	/** Condition variable for pending_ops_count. */
+	fibril_condvar_t pending_ops_cv;
+
+};
+
+int usb_hub_add_device(usb_device_t *usb_dev);
+
+bool hub_port_changes_callback(usb_device_t *dev,
+    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/usbhub.ma
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/usbhub.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,2 @@
+10 usb&hub
+10 usb&class=hub
Index: uspace/drv/bus/usb/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * @brief Hub driver private definitions
+ */
+
+#ifndef USBHUB_PRIVATE_H
+#define	USBHUB_PRIVATE_H
+
+#include "usbhub.h"
+
+#include <adt/list.h>
+#include <bool.h>
+#include <ddf/driver.h>
+#include <fibril_synch.h>
+
+#include <usb/classes/hub.h>
+#include <usb/usb.h>
+#include <usb/debug.h>
+#include <usb/dev/request.h>
+
+//************
+//
+// convenience define for malloc
+//
+//************
+
+
+usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
+
+/**
+ * Set the device request to be a get hub descriptor request.
+ * @warning the size is allways set to USB_HUB_MAX_DESCRIPTOR_SIZE
+ * @param request
+ * @param addr
+ */
+static inline void usb_hub_set_descriptor_request(
+    usb_device_request_setup_packet_t * request
+    ) {
+	request->index = 0;
+	request->request_type = USB_HUB_REQ_TYPE_GET_DESCRIPTOR;
+	request->request = USB_HUB_REQUEST_GET_DESCRIPTOR;
+	request->value_high = USB_DESCTYPE_HUB;
+	request->value_low = 0;
+	request->length = USB_HUB_MAX_DESCRIPTOR_SIZE;
+}
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param hc Host controller telephone
+ * @param address Hub address
+ * @param port_index Port
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_clear_port_feature(usb_pipe_t *pipe,
+    int port_index,
+    usb_hub_class_feature_t feature) {
+
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
+		.request = USB_DEVREQ_CLEAR_FEATURE,
+		.length = 0,
+		.index = port_index
+	};
+	clear_request.value = feature;
+	return usb_pipe_control_write(pipe, &clear_request,
+	    sizeof (clear_request), NULL, 0);
+}
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param hc Host controller telephone
+ * @param address Hub address
+ * @param port_index Port
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,
+    int port_index,
+    usb_hub_class_feature_t feature) {
+
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
+		.request = USB_DEVREQ_SET_FEATURE,
+		.length = 0,
+		.index = port_index
+	};
+	clear_request.value = feature;
+	return usb_pipe_control_write(pipe, &clear_request,
+	    sizeof (clear_request), NULL, 0);
+}
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param pipe pipe to hub control endpoint
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_clear_feature(usb_pipe_t *pipe,
+    usb_hub_class_feature_t feature) {
+
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
+		.request = USB_DEVREQ_CLEAR_FEATURE,
+		.length = 0,
+		.index = 0
+	};
+	clear_request.value = feature;
+	return usb_pipe_control_write(pipe, &clear_request,
+	    sizeof (clear_request), NULL, 0);
+}
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param pipe pipe to hub control endpoint
+ * @param feature Feature selector
+ * @return Operation result
+ */
+static inline int usb_hub_set_feature(usb_pipe_t *pipe,
+    usb_hub_class_feature_t feature) {
+
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
+		.request = USB_DEVREQ_SET_FEATURE,
+		.length = 0,
+		.index = 0
+	};
+	clear_request.value = feature;
+	return usb_pipe_control_write(pipe, &clear_request,
+	    sizeof (clear_request), NULL, 0);
+}
+
+
+void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t * descriptor);
+
+void usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor,
+    void * serialized_descriptor);
+
+int usb_deserialize_hub_desriptor(
+    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor);
+
+
+#endif	/* USBHUB_PRIVATE_H */
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/utils.c
===================================================================
--- uspace/drv/bus/usb/usbhub/utils.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbhub/utils.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * @brief various utilities
+ */
+#include <ddf/driver.h>
+#include <bool.h>
+#include <errno.h>
+
+#include <usbhc_iface.h>
+#include <usb/descriptor.h>
+#include <usb/classes/hub.h>
+
+#include "usbhub.h"
+#include "usbhub_private.h"
+#include "port_status.h"
+
+
+size_t USB_HUB_MAX_DESCRIPTOR_SIZE = 71;
+
+//*********************************************
+//
+//  various utils
+//
+//*********************************************
+
+//hub descriptor utils
+
+/**
+ * create uint8_t array with serialized descriptor
+ *
+ * @param descriptor
+ * @return newly created serializd descriptor pointer
+ */
+void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t *descriptor) {
+	//base size
+	size_t size = 7;
+	//variable size according to port count
+	size_t var_size = (descriptor->ports_count + 7) / 8;
+	size += 2 * var_size;
+	uint8_t * result = malloc(size);
+	//size
+	if (result)
+		usb_serialize_hub_descriptor(descriptor, result);
+	return result;
+}
+
+/**
+ * serialize descriptor into given buffer
+ *
+ * The buffer size is not checked.
+ * @param descriptor
+ * @param serialized_descriptor
+ */
+void usb_serialize_hub_descriptor(usb_hub_descriptor_t *descriptor,
+    void * serialized_descriptor) {
+	//base size
+	uint8_t * sdescriptor = serialized_descriptor;
+	size_t size = 7;
+	//variable size according to port count
+	size_t var_size = (descriptor->ports_count + 7) / 8;
+	size += 2 * var_size;
+	//size
+	sdescriptor[0] = size;
+	//descriptor type
+	sdescriptor[1] = USB_DESCTYPE_HUB;
+	sdescriptor[2] = descriptor->ports_count;
+	/// @fixme handling of endianness??
+	sdescriptor[3] = descriptor->hub_characteristics / 256;
+	sdescriptor[4] = descriptor->hub_characteristics % 256;
+	sdescriptor[5] = descriptor->pwr_on_2_good_time;
+	sdescriptor[6] = descriptor->current_requirement;
+
+	size_t i;
+	for (i = 0; i < var_size; ++i) {
+		sdescriptor[7 + i] = descriptor->devices_removable[i];
+	}
+	for (i = 0; i < var_size; ++i) {
+		sdescriptor[7 + var_size + i] = 255;
+	}
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Deserialize descriptor into given pointer
+ *
+ * @param serialized_descriptor
+ * @param descriptor
+ * @return
+ */
+int usb_deserialize_hub_desriptor(
+    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor)
+{
+	uint8_t * sdescriptor = serialized_descriptor;
+
+	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
+		usb_log_error("Trying to deserialize wrong descriptor %x\n",
+		    sdescriptor[1]);
+		return EINVAL;
+	}
+	if (size < 7) {
+		usb_log_error("Serialized descriptor too small.\n");
+		return EOVERFLOW;
+	}
+
+	descriptor->ports_count = sdescriptor[2];
+	descriptor->hub_characteristics = sdescriptor[3] + 256 * sdescriptor[4];
+	descriptor->pwr_on_2_good_time = sdescriptor[5];
+	descriptor->current_requirement = sdescriptor[6];
+	const size_t var_size = (descriptor->ports_count + 7) / 8;
+	//descriptor->devices_removable = (uint8_t*) malloc(var_size);
+
+	if (size < (7 + var_size)) {
+		usb_log_error("Serialized descriptor too small.\n");
+		return EOVERFLOW;
+	}
+	size_t i = 0;
+	for (; i < var_size; ++i) {
+		descriptor->devices_removable[i] = sdescriptor[7 + i];
+	}
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/Makefile
===================================================================
--- uspace/drv/bus/usb/usbmast/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a \
+	$(LIBSCSI_PREFIX)/libscsi.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include \
+	-I$(LIBSCSI_PREFIX)/include
+
+BINARY = usbmast
+
+SOURCES = \
+	bo_trans.c \
+	cmdw.c \
+	main.c \
+	scsi_ms.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbmast/bo_trans.c
===================================================================
--- uspace/drv/bus/usb/usbmast/bo_trans.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/bo_trans.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2011 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 drvusbmast
+ * @{
+ */
+/**
+ * @file
+ * USB mass storage bulk-only transport.
+ */
+#include <bool.h>
+#include <errno.h>
+#include <str_error.h>
+#include <usb/debug.h>
+#include <usb/dev/request.h>
+
+#include "bo_trans.h"
+#include "cmdw.h"
+#include "usbmast.h"
+
+bool usb_mast_verbose = false;
+
+#define MASTLOG(format, ...) \
+	do { \
+		if (usb_mast_verbose) { \
+			usb_log_debug2("USB cl08: " format, ##__VA_ARGS__); \
+		} \
+	} while (false)
+
+/** Send command via bulk-only transport.
+ *
+ * @param mfun		Mass storage function
+ * @param tag		Command block wrapper tag (automatically compared
+ *			with answer)
+ * @param cmd		SCSI command
+ *
+ * @return		Error code
+ */
+int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, scsi_cmd_t *cmd)
+{
+	int rc;
+	int retval = EOK;
+	size_t act_size;
+	usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
+	usb_pipe_t *bulk_out_pipe = mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe;
+	usb_direction_t ddir;
+	void *dbuf;
+	size_t dbuf_size;
+
+	if (cmd->data_out != NULL && cmd->data_in == NULL) {
+		ddir = USB_DIRECTION_OUT;
+		dbuf = (void *)cmd->data_out;
+		dbuf_size = cmd->data_out_size;
+	} else if (cmd->data_out == NULL && cmd->data_in != NULL) {
+		ddir = USB_DIRECTION_IN;
+		dbuf = cmd->data_in;
+		dbuf_size = cmd->data_in_size;
+	} else {
+		assert(false);
+	}
+
+	/* Prepare CBW - command block wrapper */
+	usb_massstor_cbw_t cbw;
+	usb_massstor_cbw_prepare(&cbw, tag, dbuf_size, ddir, mfun->lun,
+	    cmd->cdb_size, cmd->cdb);
+
+	/* Send the CBW. */
+	MASTLOG("Sending CBW.\n");
+	rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
+	MASTLOG("CBW '%s' sent: %s.\n",
+	    usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
+	    str_error(rc));
+	if (rc != EOK)
+		return EIO;
+
+	MASTLOG("Transferring data.\n");
+	if (ddir == USB_DIRECTION_IN) {
+		/* Recieve data from the device. */
+		rc = usb_pipe_read(bulk_in_pipe, dbuf, dbuf_size, &act_size);
+		MASTLOG("Received %zu bytes (%s): %s.\n", act_size,
+		    usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0),
+		    str_error(rc));
+	} else {
+		/* Send data to the device. */
+		rc = usb_pipe_write(bulk_out_pipe, dbuf, dbuf_size);
+		MASTLOG("Sent %zu bytes (%s): %s.\n", act_size,
+		    usb_debug_str_buffer((uint8_t *) dbuf, act_size, 0),
+		    str_error(rc));
+	}
+
+	if (rc == ESTALL) {
+		/* Clear stall condition and continue below to read CSW. */
+		if (ddir == USB_DIRECTION_IN) {
+			usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
+			    mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
+		} else {
+			usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
+			    mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
+		}
+        } else if (rc != EOK) {
+		return EIO;
+	}
+
+	/* Read CSW. */
+	usb_massstor_csw_t csw;
+	size_t csw_size;
+	MASTLOG("Reading CSW.\n");
+	rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
+	MASTLOG("CSW '%s' received (%zu bytes): %s.\n",
+	    usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
+	    str_error(rc));
+	if (rc != EOK) {
+		MASTLOG("rc != EOK\n");
+		return EIO;
+	}
+
+	if (csw_size != sizeof(csw)) {
+		MASTLOG("csw_size != sizeof(csw)\n");
+		return EIO;
+	}
+
+	if (csw.dCSWTag != tag) {
+		MASTLOG("csw.dCSWTag != tag\n");
+		return EIO;
+	}
+
+	/*
+	 * Determine the actual return value from the CSW.
+	 */
+	switch (csw.dCSWStatus) {
+	case cbs_passed:
+		cmd->status = CMDS_GOOD;
+		break;
+	case cbs_failed:
+		MASTLOG("Command failed\n");
+		cmd->status = CMDS_FAILED;
+		break;
+	case cbs_phase_error:
+		MASTLOG("Phase error\n");
+		retval = EIO;
+		break;
+	default:
+		retval = EIO;
+		break;
+	}
+
+	size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
+	if (residue > dbuf_size) {
+		MASTLOG("residue > dbuf_size\n");
+		return EIO;
+	}
+
+	/*
+	 * When the device has less data to send than requested (or cannot
+	 * receive moredata), it can either stall the pipe or send garbage
+	 * (ignore data) and indicate that via the residue field in CSW.
+	 * That means dbuf_size - residue is the authoritative size of data
+	 * received (sent).
+	 */
+
+	if (ddir == USB_DIRECTION_IN)
+		cmd->rcvd_size = dbuf_size - residue;
+
+	return retval;
+}
+
+/** Perform bulk-only mass storage reset.
+ *
+ * @param mfun		Mass storage function
+ * @return		Error code
+ */
+int usb_massstor_reset(usbmast_dev_t *mdev)
+{
+	return usb_control_request_set(&mdev->usb_dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
+	    0xFF, 0, mdev->usb_dev->interface_no, NULL, 0);
+}
+
+/** Perform complete reset recovery of bulk-only mass storage.
+ *
+ * Notice that no error is reported because if this fails, the error
+ * would reappear on next transaction somehow.
+ *
+ * @param mfun		Mass storage function
+ */
+void usb_massstor_reset_recovery(usbmast_dev_t *mdev)
+{
+	/* We would ignore errors here because if this fails
+	 * we are doomed anyway and any following transaction would fail.
+	 */
+	usb_massstor_reset(mdev);
+	usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
+	    mdev->usb_dev->pipes[BULK_IN_EP].pipe);
+	usb_pipe_clear_halt(&mdev->usb_dev->ctrl_pipe,
+	    mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
+}
+
+/** Get max LUN of a mass storage device.
+ *
+ * @see usb_masstor_get_lun_count
+ *
+ * @warning Error from this command does not necessarily indicate malfunction
+ * of the device. Device does not need to support this request.
+ * You shall rather use usb_masstor_get_lun_count.
+ *
+ * @param mfun		Mass storage function
+ * @return		Error code of maximum LUN (index, not count)
+ */
+int usb_massstor_get_max_lun(usbmast_dev_t *mdev)
+{
+	uint8_t max_lun;
+	size_t data_recv_len;
+	int rc = usb_control_request_get(&mdev->usb_dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
+	    0xFE, 0, mdev->usb_dev->interface_no, &max_lun, 1, &data_recv_len);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (data_recv_len != 1) {
+		return EEMPTY;
+	}
+	return (int) max_lun;
+}
+
+/** Get number of LUNs supported by mass storage device.
+ *
+ * @warning This function hides any error during the request
+ * (typically that shall not be a problem).
+ *
+ * @param mfun		Mass storage function
+ * @return		Number of LUNs
+ */
+size_t usb_masstor_get_lun_count(usbmast_dev_t *mdev)
+{
+	int max_lun = usb_massstor_get_max_lun(mdev);
+	if (max_lun < 0) {
+		max_lun = 1;
+	} else {
+		max_lun++;
+	}
+
+	return (size_t) max_lun;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/bo_trans.h
===================================================================
--- uspace/drv/bus/usb/usbmast/bo_trans.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/bo_trans.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2011 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 drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage bulk-only transport.
+ */
+
+#ifndef BO_TRANS_H_
+#define BO_TRANS_H_
+
+#include <scsi/spc.h>
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/driver.h>
+#include "usbmast.h"
+
+#define BULK_IN_EP 0
+#define BULK_OUT_EP 1
+
+typedef enum cmd_status {
+	CMDS_GOOD,
+	CMDS_FAILED
+} cmd_status_t;
+
+/** SCSI command.
+ *
+ * Contains (a subset of) the input and output arguments of SCSI
+ * Execute Command procedure call (see SAM-4 chapter 5.1)
+ */
+typedef struct {
+	/*
+	 * Related to IN fields
+	 */
+
+	/** Command Descriptor Block */
+	void *cdb;
+	/** CDB size in bytes */
+	size_t cdb_size;
+
+	/** Outgoing data */
+	const void *data_out;
+	/** Size of outgoing data in bytes */
+	size_t data_out_size;
+
+	/*
+	 * Related to OUT fields
+	 */
+
+	/** Buffer for incoming data */
+	void *data_in;
+	/** Size of input buffer in bytes */
+	size_t data_in_size;
+
+	/** Number of bytes actually received */
+	size_t rcvd_size;
+
+	/** Status */
+	cmd_status_t status;
+} scsi_cmd_t;
+
+extern int usb_massstor_cmd(usbmast_fun_t *, uint32_t, scsi_cmd_t *);
+extern int usb_massstor_reset(usbmast_dev_t *);
+extern void usb_massstor_reset_recovery(usbmast_dev_t *);
+extern int usb_massstor_get_max_lun(usbmast_dev_t *);
+extern size_t usb_masstor_get_lun_count(usbmast_dev_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/cmdw.c
===================================================================
--- uspace/drv/bus/usb/usbmast/cmdw.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/cmdw.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011 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 drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage commands.
+ */
+
+#include <byteorder.h>
+#include <mem.h>
+#include <sys/types.h>
+#include <usb/usb.h>
+#include "cmdw.h"
+
+void usb_massstor_cbw_prepare(usb_massstor_cbw_t *cbw,
+    uint32_t tag, uint32_t transfer_length, usb_direction_t dir,
+    uint8_t lun, uint8_t cmd_len, const uint8_t *cmd)
+{
+	cbw->dCBWSignature = uint32_host2usb(0x43425355);
+	cbw->dCBWTag = tag;
+	cbw->dCBWDataTransferLength = transfer_length;
+
+	cbw->bmCBWFlags = 0;
+	if (dir == USB_DIRECTION_IN) {
+		cbw->bmCBWFlags |= (1 << 7);
+	}
+
+	/* Only lowest 4 bits. */
+	cbw->bCBWLUN = lun & 0x0F;
+
+	/* Only lowest 5 bits. */
+	cbw->bCBWBLength = cmd_len & 0x1F;
+
+	memcpy(cbw->CBWCB, cmd, cbw->bCBWBLength);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/cmdw.h
===================================================================
--- uspace/drv/bus/usb/usbmast/cmdw.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/cmdw.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011 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 drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage commands.
+ */
+
+#ifndef CMDW_H_
+#define CMDW_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+
+typedef struct {
+	uint32_t dCBWSignature;
+	uint32_t dCBWTag;
+	uint32_t dCBWDataTransferLength;
+	uint8_t bmCBWFlags;
+	uint8_t bCBWLUN;
+	uint8_t bCBWBLength;
+	uint8_t CBWCB[16];
+} __attribute__((packed)) usb_massstor_cbw_t;
+
+typedef struct {
+	uint32_t dCSWSignature;
+	uint32_t dCSWTag;
+	uint32_t dCSWDataResidue;
+	uint8_t dCSWStatus;
+} __attribute__((packed)) usb_massstor_csw_t;
+
+enum cmd_block_status {
+	cbs_passed	= 0x00,
+	cbs_failed	= 0x01,
+	cbs_phase_error = 0x02
+};
+
+extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t,
+    usb_direction_t, uint8_t, uint8_t, const uint8_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbmast
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB mass storage driver.
+ */
+#include <as.h>
+#include <async.h>
+#include <ipc/bd.h>
+#include <macros.h>
+#include <usb/dev/driver.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/massstor.h>
+#include <errno.h>
+#include <str_error.h>
+#include "cmdw.h"
+#include "bo_trans.h"
+#include "scsi_ms.h"
+#include "usbmast.h"
+
+#define NAME "usbmast"
+
+#define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
+#define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
+
+static usb_endpoint_description_t bulk_in_ep = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_MASS_STORAGE,
+	.interface_subclass = USB_MASSSTOR_SUBCLASS_SCSI,
+	.interface_protocol = USB_MASSSTOR_PROTOCOL_BBB,
+	.flags = 0
+};
+static usb_endpoint_description_t bulk_out_ep = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_MASS_STORAGE,
+	.interface_subclass = USB_MASSSTOR_SUBCLASS_SCSI,
+	.interface_protocol = USB_MASSSTOR_PROTOCOL_BBB,
+	.flags = 0
+};
+
+usb_endpoint_description_t *mast_endpoints[] = {
+	&bulk_in_ep,
+	&bulk_out_ep,
+	NULL
+};
+
+static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun);
+static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg);
+
+/** Callback when new device is attached and recognized as a mass storage.
+ *
+ * @param dev Representation of a the USB device.
+ * @return Error code.
+ */
+static int usbmast_add_device(usb_device_t *dev)
+{
+	int rc;
+	usbmast_dev_t *mdev = NULL;
+	unsigned i;
+
+	/* Allocate softstate */
+	mdev = calloc(1, sizeof(usbmast_dev_t));
+	if (mdev == NULL) {
+		usb_log_error("Failed allocating softstate.\n");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	mdev->ddf_dev = dev->ddf_dev;
+	mdev->usb_dev = dev;
+
+	usb_log_info("Initializing mass storage `%s'.\n",
+	    dev->ddf_dev->name);
+	usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
+	    dev->pipes[BULK_IN_EP].pipe->endpoint_no,
+	    (size_t) dev->pipes[BULK_IN_EP].descriptor->max_packet_size);
+	usb_log_debug("Bulk out endpoint: %d [%zuB].\n",
+	    dev->pipes[BULK_OUT_EP].pipe->endpoint_no,
+	    (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
+
+	usb_log_debug("Get LUN count...\n");
+	mdev->luns = usb_masstor_get_lun_count(mdev);
+
+	for (i = 0; i < mdev->luns; i++) {
+		rc = usbmast_fun_create(mdev, i);
+		if (rc != EOK)
+			goto error;
+	}
+
+	return EOK;
+error:
+	/* XXX Destroy functions */
+	if (mdev != NULL)
+		free(mdev);
+	return rc;
+}
+
+/** Create mass storage function.
+ *
+ * Called once for each LUN.
+ *
+ * @param mdev		Mass storage device
+ * @param lun		LUN
+ * @return		EOK on success or negative error code.
+ */
+static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun)
+{
+	int rc;
+	char *fun_name = NULL;
+	ddf_fun_t *fun = NULL;
+	usbmast_fun_t *mfun = NULL;
+
+	/* Allocate softstate */
+	mfun = calloc(1, sizeof(usbmast_fun_t));
+	if (mfun == NULL) {
+		usb_log_error("Failed allocating softstate.\n");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	mfun->mdev = mdev;
+	mfun->lun = lun;
+
+	if (asprintf(&fun_name, "l%u", lun) < 0) {
+		usb_log_error("Out of memory.\n");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name);
+	if (fun == NULL) {
+		usb_log_error("Failed to create DDF function %s.\n", fun_name);
+		rc = ENOMEM;
+		goto error;
+	}
+
+	free(fun_name);
+	fun_name = NULL;
+
+	/* Set up a connection handler. */
+	fun->conn_handler = usbmast_bd_connection;
+	fun->driver_data = mfun;
+
+	usb_log_debug("Inquire...\n");
+	usbmast_inquiry_data_t inquiry;
+	rc = usbmast_inquiry(mfun, &inquiry);
+	if (rc != EOK) {
+		usb_log_warning("Failed to inquire device `%s': %s.\n",
+		    mdev->ddf_dev->name, str_error(rc));
+		rc = EIO;
+		goto error;
+	}
+
+	usb_log_info("Mass storage `%s' LUN %u: " \
+	    "%s by %s rev. %s is %s (%s).\n",
+	    mdev->ddf_dev->name,
+	    lun,
+	    inquiry.product,
+	    inquiry.vendor,
+	    inquiry.revision,
+	    usbmast_scsi_dev_type_str(inquiry.device_type),
+	    inquiry.removable ? "removable" : "non-removable");
+
+	uint32_t nblocks, block_size;
+
+	rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
+	if (rc != EOK) {
+		usb_log_warning("Failed to read capacity, device `%s': %s.\n",
+		    mdev->ddf_dev->name, str_error(rc));
+		rc = EIO;
+		goto error;
+	}
+
+	usb_log_info("Read Capacity: nblocks=%" PRIu32 ", "
+	    "block_size=%" PRIu32 "\n", nblocks, block_size);
+
+	mfun->nblocks = nblocks;
+	mfun->block_size = block_size;
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		usb_log_error("Failed to bind DDF function %s: %s.\n",
+		    fun_name, str_error(rc));
+		goto error;
+	}
+
+	return EOK;
+
+	/* Error cleanup */
+error:
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	if (fun_name != NULL)
+		free(fun_name);
+	if (mfun != NULL)
+		free(mfun);
+	return rc;
+}
+
+/** Blockdev client connection handler. */
+static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
+{
+	usbmast_fun_t *mfun;
+	void *comm_buf = NULL;
+	size_t comm_size;
+	ipc_callid_t callid;
+	ipc_call_t call;
+	unsigned int flags;
+	sysarg_t method;
+	uint64_t ba;
+	size_t cnt;
+	int retval;
+
+	async_answer_0(iid, EOK);
+
+	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
+		async_answer_0(callid, EHANGUP);
+		return;
+	}
+
+	comm_buf = as_get_mappable_page(comm_size);
+	if (comm_buf == NULL) {
+		async_answer_0(callid, EHANGUP);
+		return;
+	}
+
+	(void) async_share_out_finalize(callid, comm_buf);
+
+	mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
+
+	while (true) {
+		callid = async_get_call(&call);
+		method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		switch (method) {
+		case BD_GET_BLOCK_SIZE:
+			async_answer_1(callid, EOK, mfun->block_size);
+			break;
+		case BD_GET_NUM_BLOCKS:
+			async_answer_2(callid, EOK, LOWER32(mfun->nblocks),
+			    UPPER32(mfun->nblocks));
+			break;
+		case BD_READ_BLOCKS:
+			ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+			cnt = IPC_GET_ARG3(call);
+			retval = usbmast_read(mfun, ba, cnt, comm_buf);
+			async_answer_0(callid, retval);
+			break;
+		case BD_WRITE_BLOCKS:
+			ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
+			cnt = IPC_GET_ARG3(call);
+			retval = usbmast_write(mfun, ba, cnt, comm_buf);
+			async_answer_0(callid, retval);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+/** USB mass storage driver ops. */
+static usb_driver_ops_t usbmast_driver_ops = {
+	.add_device = usbmast_add_device,
+};
+
+/** USB mass storage driver. */
+static usb_driver_t usbmast_driver = {
+	.name = NAME,
+	.ops = &usbmast_driver_ops,
+	.endpoints = mast_endpoints
+};
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&usbmast_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/scsi_ms.c
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbmast
+ * @{
+ */
+/**
+ * @file
+ * SCSI functions for USB mass storage driver.
+ */
+#include <bitops.h>
+#include <byteorder.h>
+#include <inttypes.h>
+#include <macros.h>
+#include <usb/dev/driver.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+#include <str.h>
+#include <scsi/sbc.h>
+#include <scsi/spc.h>
+#include "cmdw.h"
+#include "bo_trans.h"
+#include "scsi_ms.h"
+#include "usbmast.h"
+
+/** Get string representation for SCSI peripheral device type.
+ *
+ * @param type		SCSI peripheral device type code.
+ * @return		String representation.
+ */
+const char *usbmast_scsi_dev_type_str(unsigned type)
+{
+	return scsi_get_dev_type_str(type);
+}
+
+static void usbmast_dump_sense(scsi_sense_data_t *sense_buf)
+{
+	unsigned sense_key;
+
+	sense_key = sense_buf->flags_key & 0x0f;
+	printf("Got sense data. Sense key: 0x%x (%s), ASC 0x%02x, "
+	    "ASCQ 0x%02x.\n", sense_key,
+	    scsi_get_sense_key_str(sense_key),
+	    sense_buf->additional_code,
+	    sense_buf->additional_cqual);
+}
+
+/** Run SCSI command.
+ *
+ * Run command and repeat in case of unit attention.
+ * XXX This is too simplified.
+ */
+static int usbmast_run_cmd(usbmast_fun_t *mfun, scsi_cmd_t *cmd)
+{
+	uint8_t sense_key;
+	scsi_sense_data_t sense_buf;
+	int rc;
+
+	do {
+		rc = usb_massstor_cmd(mfun, 0xDEADBEEF, cmd);
+		if (rc != EOK) {
+			usb_log_error("Inquiry transport failed, device %s: %s.\n",
+			   mfun->mdev->ddf_dev->name, str_error(rc));
+			return rc;
+		}
+
+		if (cmd->status == CMDS_GOOD)
+			return EOK;
+
+		usb_log_error("SCSI command failed, device %s.\n",
+		    mfun->mdev->ddf_dev->name);
+
+		rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf));
+		if (rc != EOK) {
+			usb_log_error("Failed to read sense data.\n");
+			return EIO;
+		}
+
+		/* Dump sense data to log */
+		usbmast_dump_sense(&sense_buf);
+
+		/* Get sense key */
+		sense_key = sense_buf.flags_key & 0x0f;
+
+		if (sense_key == SCSI_SK_UNIT_ATTENTION) {
+			printf("Got unit attention. Re-trying command.\n");
+		}
+
+	} while (sense_key == SCSI_SK_UNIT_ATTENTION);
+
+	/* Command status is not good, nevertheless transport succeeded. */
+	return EOK;
+}
+
+/** Perform SCSI Inquiry command on USB mass storage device.
+ *
+ * @param mfun		Mass storage function
+ * @param inquiry_result Where to store parsed inquiry result
+ * @return		Error code
+ */
+int usbmast_inquiry(usbmast_fun_t *mfun, usbmast_inquiry_data_t *inq_res)
+{
+	scsi_std_inquiry_data_t inq_data;
+	scsi_cmd_t cmd;
+	scsi_cdb_inquiry_t cdb;
+	int rc;
+
+	memset(&cdb, 0, sizeof(cdb));
+	cdb.op_code = SCSI_CMD_INQUIRY;
+	cdb.alloc_len = host2uint16_t_be(sizeof(inq_data));
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_in = &inq_data;
+	cmd.data_in_size = sizeof(inq_data);
+
+	rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd);
+
+	if (rc != EOK) {
+		usb_log_error("Inquiry transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.status != CMDS_GOOD) {
+		usb_log_error("Inquiry command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		return EIO;
+	}
+
+	if (cmd.rcvd_size < SCSI_STD_INQUIRY_DATA_MIN_SIZE) {
+		usb_log_error("SCSI Inquiry response too short (%zu).\n",
+		    cmd.rcvd_size);
+		return EIO;
+	}
+
+	/*
+	 * Parse inquiry data and fill in the result structure.
+	 */
+
+	bzero(inq_res, sizeof(*inq_res));
+
+	inq_res->device_type = BIT_RANGE_EXTRACT(uint8_t,
+	    inq_data.pqual_devtype, SCSI_PQDT_DEV_TYPE_h, SCSI_PQDT_DEV_TYPE_l);
+
+	inq_res->removable = BIT_RANGE_EXTRACT(uint8_t,
+	    inq_data.rmb, SCSI_RMB_RMB, SCSI_RMB_RMB);
+
+	spascii_to_str(inq_res->vendor, SCSI_INQ_VENDOR_STR_BUFSIZE,
+	    inq_data.vendor, sizeof(inq_data.vendor));
+
+	spascii_to_str(inq_res->product, SCSI_INQ_PRODUCT_STR_BUFSIZE,
+	    inq_data.product, sizeof(inq_data.product));
+
+	spascii_to_str(inq_res->revision, SCSI_INQ_REVISION_STR_BUFSIZE,
+	    inq_data.revision, sizeof(inq_data.revision));
+
+	return EOK;
+}
+
+/** Perform SCSI Request Sense command on USB mass storage device.
+ *
+ * @param mfun		Mass storage function
+ * @param buf		Destination buffer
+ * @param size		Size of @a buf
+ *
+ * @return		Error code.
+ */
+int usbmast_request_sense(usbmast_fun_t *mfun, void *buf, size_t size)
+{
+	scsi_cmd_t cmd;
+	scsi_cdb_request_sense_t cdb;
+	int rc;
+
+	memset(&cdb, 0, sizeof(cdb));
+	cdb.op_code = SCSI_CMD_REQUEST_SENSE;
+	cdb.alloc_len = min(size, SCSI_SENSE_DATA_MAX_SIZE);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_in = buf;
+	cmd.data_in_size = size;
+
+	rc = usb_massstor_cmd(mfun, 0xDEADBEEF, &cmd);
+
+        if (rc != EOK || cmd.status != CMDS_GOOD) {
+		usb_log_error("Request Sense failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.rcvd_size < SCSI_SENSE_DATA_MIN_SIZE) {
+		/* The missing bytes should be considered to be zeroes. */
+		memset((uint8_t *)buf + cmd.rcvd_size, 0,
+		    SCSI_SENSE_DATA_MIN_SIZE - cmd.rcvd_size);
+	}
+
+	return EOK;
+}
+
+/** Perform SCSI Read Capacity command on USB mass storage device.
+ *
+ * @param mfun		Mass storage function
+ * @param nblocks	Output, number of blocks
+ * @param block_size	Output, block size in bytes
+ *
+ * @return		Error code.
+ */
+int usbmast_read_capacity(usbmast_fun_t *mfun, uint32_t *nblocks,
+    uint32_t *block_size)
+{
+	scsi_cmd_t cmd;
+	scsi_cdb_read_capacity_10_t cdb;
+	scsi_read_capacity_10_data_t data;
+	int rc;
+
+	memset(&cdb, 0, sizeof(cdb));
+	cdb.op_code = SCSI_CMD_READ_CAPACITY_10;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_in = &data;
+	cmd.data_in_size = sizeof(data);
+
+	rc = usbmast_run_cmd(mfun, &cmd);
+
+        if (rc != EOK) {
+		usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.status != CMDS_GOOD) {
+		usb_log_error("Read Capacity (10) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		return EIO;
+	}
+
+	if (cmd.rcvd_size < sizeof(data)) {
+		usb_log_error("SCSI Read Capacity response too short (%zu).\n",
+		    cmd.rcvd_size);
+		return EIO;
+	}
+
+	*nblocks = uint32_t_be2host(data.last_lba) + 1;
+	*block_size = uint32_t_be2host(data.block_size);
+
+	return EOK;
+}
+
+/** Perform SCSI Read command on USB mass storage device.
+ *
+ * @param mfun		Mass storage function
+ * @param ba		Address of first block
+ * @param nblocks	Number of blocks to read
+ *
+ * @return		Error code
+ */
+int usbmast_read(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks, void *buf)
+{
+	scsi_cmd_t cmd;
+	scsi_cdb_read_10_t cdb;
+	int rc;
+
+	if (ba > UINT32_MAX)
+		return ELIMIT;
+
+	if (nblocks > UINT16_MAX)
+		return ELIMIT;
+
+	memset(&cdb, 0, sizeof(cdb));
+	cdb.op_code = SCSI_CMD_READ_10;
+	cdb.lba = host2uint32_t_be(ba);
+	cdb.xfer_len = host2uint16_t_be(nblocks);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_in = buf;
+	cmd.data_in_size = nblocks * mfun->block_size;
+
+	rc = usbmast_run_cmd(mfun, &cmd);
+
+        if (rc != EOK) {
+		usb_log_error("Read (10) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.status != CMDS_GOOD) {
+		usb_log_error("Read (10) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		return EIO;
+	}
+
+	if (cmd.rcvd_size < nblocks * mfun->block_size) {
+		usb_log_error("SCSI Read response too short (%zu).\n",
+		    cmd.rcvd_size);
+		return EIO;
+	}
+
+	return EOK;
+}
+
+/** Perform SCSI Write command on USB mass storage device.
+ *
+ * @param mfun		Mass storage function
+ * @param ba		Address of first block
+ * @param nblocks	Number of blocks to read
+ * @param data		Data to write
+ *
+ * @return		Error code
+ */
+int usbmast_write(usbmast_fun_t *mfun, uint64_t ba, size_t nblocks,
+    const void *data)
+{
+	scsi_cmd_t cmd;
+	scsi_cdb_write_10_t cdb;
+	int rc;
+
+	if (ba > UINT32_MAX)
+		return ELIMIT;
+
+	if (nblocks > UINT16_MAX)
+		return ELIMIT;
+
+	memset(&cdb, 0, sizeof(cdb));
+	cdb.op_code = SCSI_CMD_WRITE_10;
+	cdb.lba = host2uint32_t_be(ba);
+	cdb.xfer_len = host2uint16_t_be(nblocks);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cdb = &cdb;
+	cmd.cdb_size = sizeof(cdb);
+	cmd.data_out = data;
+	cmd.data_out_size = nblocks * mfun->block_size;
+
+	rc = usbmast_run_cmd(mfun, &cmd);
+
+        if (rc != EOK) {
+		usb_log_error("Write (10) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (cmd.status != CMDS_GOOD) {
+		usb_log_error("Write (10) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		return EIO;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/scsi_ms.h
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi_ms.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011 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 drvusbmast
+ * @{
+ */
+/** @file
+ * SCSI functions for USB mass storage.
+ */
+
+#ifndef USB_USBMAST_SCSI_MS_H_
+#define USB_USBMAST_SCSI_MS_H_
+
+#include <scsi/spc.h>
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/dev/driver.h>
+
+/** Result of SCSI Inquiry command.
+ * This is already parsed structure, not the original buffer returned by
+ * the device.
+ */
+typedef struct {
+	/** SCSI peripheral device type */
+	unsigned device_type;
+	/** Whether the device is removable */
+	bool removable;
+	/** Vendor ID string */
+	char vendor[SCSI_INQ_VENDOR_STR_BUFSIZE];
+	/** Product ID string */
+	char product[SCSI_INQ_PRODUCT_STR_BUFSIZE];
+	/** Revision string */
+	char revision[SCSI_INQ_REVISION_STR_BUFSIZE];
+} usbmast_inquiry_data_t;
+
+extern int usbmast_inquiry(usbmast_fun_t *, usbmast_inquiry_data_t *);
+extern int usbmast_request_sense(usbmast_fun_t *, void *, size_t);
+extern int usbmast_read_capacity(usbmast_fun_t *, uint32_t *, uint32_t *);
+extern int usbmast_read(usbmast_fun_t *, uint64_t, size_t, void *);
+extern int usbmast_write(usbmast_fun_t *, uint64_t, size_t, const void *);
+extern const char *usbmast_scsi_dev_type_str(unsigned);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/usbmast.h
===================================================================
--- uspace/drv/bus/usb/usbmast/usbmast.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/usbmast.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbmast
+ * @{
+ */
+/** @file
+ * USB mass storage commands.
+ */
+
+#ifndef USBMAST_H_
+#define USBMAST_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+
+/** Mass storage device. */
+typedef struct {
+	/** DDF device */
+	ddf_dev_t *ddf_dev;
+	/** USB device */
+	usb_device_t *usb_dev;
+	/** Number of LUNs */
+	unsigned luns;
+} usbmast_dev_t;
+
+/** Mass storage function.
+ *
+ * Serves as soft state for function/LUN.
+ */
+typedef struct {
+	/** Mass storage device the function belongs to */
+	usbmast_dev_t *mdev;
+	/** DDF function */
+	ddf_fun_t *ddf_fun;
+	/** LUN */
+	unsigned lun;
+	/** Total number of blocks */
+	uint64_t nblocks;
+	/** Block size in bytes */
+	size_t block_size;
+} usbmast_fun_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmast/usbmast.ma
===================================================================
--- uspace/drv/bus/usb/usbmast/usbmast.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmast/usbmast.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+50 usb&interface&class=mass-storage&subclass=0x06&protocol=0x50
Index: uspace/drv/bus/usb/usbmid/Makefile
===================================================================
--- uspace/drv/bus/usb/usbmid/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmid/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbmid
+
+SOURCES = \
+	dump.c \
+	explore.c \
+	main.c \
+	usbmid.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbmid/dump.c
===================================================================
--- uspace/drv/bus/usb/usbmid/dump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmid/dump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Dumping and debugging functions.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/dp.h>
+#include <usb/classes/classes.h>
+#include "usbmid.h"
+
+/** Dump found descriptor.
+ *
+ * @param data Descriptor data.
+ * @param depth Nesting depth.
+ */
+static void dump_tree_descriptor(uint8_t *data, size_t depth)
+{
+	if (data == NULL) {
+		return;
+	}
+	int type = (int) *(data + 1);
+	if (type == USB_DESCTYPE_INTERFACE) {
+		usb_standard_interface_descriptor_t *descriptor
+		    = (usb_standard_interface_descriptor_t *) data;
+		usb_log_info("Found interface: %s (0x%02x/0x%02x/0x%02x).\n",
+		    usb_str_class(descriptor->interface_class),
+		    (int) descriptor->interface_class,
+		    (int) descriptor->interface_subclass,
+		    (int) descriptor->interface_protocol);
+	}
+}
+
+/** Dump tree of descriptors.
+ *
+ * @param parser Descriptor parser.
+ * @param data Descriptor parser data.
+ * @param root Pointer to current root.
+ * @param depth Nesting depth.
+ */
+static void dump_tree_internal(usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
+    uint8_t *root, size_t depth)
+{
+	if (root == NULL) {
+		return;
+	}
+	dump_tree_descriptor(root, depth);
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
+	do {
+		dump_tree_internal(parser, data, child, depth + 1);
+		child = usb_dp_get_sibling_descriptor(parser, data, root, child);
+	} while (child != NULL);
+}
+
+/** Dump descriptor tree.
+ *
+ * @param parser Descriptor parser.
+ * @param data Descriptor parser data.
+ */
+static void dump_tree(usb_dp_parser_t *parser, usb_dp_parser_data_t *data)
+{
+	uint8_t *ptr = data->data;
+	dump_tree_internal(parser, data, ptr, 0);
+}
+
+/** Dump given descriptors.
+ *
+ * @param descriptors Descriptors buffer (typically full config descriptor).
+ * @param length Size of @p descriptors buffer in bytes.
+ */
+void usbmid_dump_descriptors(uint8_t *descriptors, size_t length)
+{
+	usb_dp_parser_data_t data = {
+		.data = descriptors,
+		.size = length,
+		.arg = NULL
+	};
+
+	usb_dp_parser_t parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+
+	dump_tree(&parser, &data);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/explore.c
===================================================================
--- uspace/drv/bus/usb/usbmid/explore.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmid/explore.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2011 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Exploration of available interfaces in the USB device.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb/classes/classes.h>
+#include <usb/dev/request.h>
+#include <usb/dev/dp.h>
+#include <usb/ddfiface.h>
+#include "usbmid.h"
+
+/** Operations of the device itself. */
+static ddf_dev_ops_t mid_device_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
+};
+
+/** Tell whether given interface is already in the list.
+ *
+ * @param list List of usbmid_interface_t members to be searched.
+ * @param interface_no Interface number caller is looking for.
+ * @return Interface @p interface_no is already present in the list.
+ */
+static bool interface_in_list(list_t *list, int interface_no)
+{
+	list_foreach(*list, l) {
+		usbmid_interface_t *iface
+		    = list_get_instance(l, usbmid_interface_t, link);
+		if (iface->interface_no == interface_no) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/** Create list of interfaces from configuration descriptor.
+ *
+ * @param config_descriptor Configuration descriptor.
+ * @param config_descriptor_size Size of configuration descriptor in bytes.
+ * @param list List where to add the interfaces.
+ */
+static void create_interfaces(uint8_t *config_descriptor,
+    size_t config_descriptor_size, list_t *list)
+{
+	usb_dp_parser_data_t data = {
+		.data = config_descriptor,
+		.size = config_descriptor_size,
+		.arg = NULL
+	};
+
+	usb_dp_parser_t parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+
+	uint8_t *interface_ptr = usb_dp_get_nested_descriptor(&parser, &data,
+	    data.data);
+	if (interface_ptr == NULL) {
+		return;
+	}
+
+	do {
+		if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) {
+			goto next_descriptor;
+		}
+
+		usb_standard_interface_descriptor_t *interface
+		    = (usb_standard_interface_descriptor_t *) interface_ptr;
+
+		/* Skip alternate interfaces. */
+		if (!interface_in_list(list, interface->interface_number)) {
+			usbmid_interface_t *iface
+			    = malloc(sizeof(usbmid_interface_t));
+			if (iface == NULL) {
+				break;
+			}
+			link_initialize(&iface->link);
+			iface->fun = NULL;
+			iface->interface_no = interface->interface_number;
+			iface->interface = interface;
+
+			list_append(&iface->link, list);
+		}
+
+		/* TODO: add the alternatives and create match ids from them
+		 * as well.
+		 */
+
+next_descriptor:
+		interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data,
+		    data.data, interface_ptr);
+
+	} while (interface_ptr != NULL);
+
+}
+
+/** Explore MID device.
+ *
+ * We expect that @p dev is initialized and session on control pipe is
+ * started.
+ *
+ * @param dev Device to be explored.
+ * @return Whether to accept this device from devman.
+ */
+bool usbmid_explore_device(usb_device_t *dev)
+{
+	int rc;
+
+	int dev_class = dev->descriptors.device.device_class;
+	if (dev_class != USB_CLASS_USE_INTERFACE) {
+		usb_log_warning(
+		    "Device class: %d (%s), but expected class 0.\n",
+		    dev_class, usb_str_class(dev_class));
+		usb_log_error("Not multi interface device, refusing.\n");
+		return false;
+	}
+
+	/* Short cuts to save on typing ;-). */
+	uint8_t *config_descriptor_raw = dev->descriptors.configuration;
+	size_t config_descriptor_size = dev->descriptors.configuration_size;
+	usb_standard_configuration_descriptor_t *config_descriptor =
+	    (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
+
+	/* Select the first configuration */
+	rc = usb_request_set_configuration(&dev->ctrl_pipe,
+	    config_descriptor->configuration_number);
+	if (rc != EOK) {
+		usb_log_error("Failed to set device configuration: %s.\n",
+		    str_error(rc));
+		return false;
+	}
+
+	/* Create control function */
+	ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
+	if (ctl_fun == NULL) {
+		usb_log_error("Failed to create control function.\n");
+		return false;
+	}
+
+	ctl_fun->ops = &mid_device_ops;
+
+	rc = ddf_fun_bind(ctl_fun);
+	if (rc != EOK) {
+		usb_log_error("Failed to bind control function: %s.\n",
+		    str_error(rc));
+		return false;
+	}
+
+	/* Create interface children. */
+	list_t interface_list;
+	list_initialize(&interface_list);
+	create_interfaces(config_descriptor_raw, config_descriptor_size,
+	    &interface_list);
+
+	list_foreach(interface_list, link) {
+		usbmid_interface_t *iface = list_get_instance(link,
+		    usbmid_interface_t, link);
+
+		usb_log_info("Creating child for interface %d (%s).\n",
+		    (int) iface->interface_no,
+		    usb_str_class(iface->interface->interface_class));
+
+		rc = usbmid_spawn_interface_child(dev, iface,
+		    &dev->descriptors.device, iface->interface);
+		if (rc != EOK) {
+			usb_log_error("Failed to create interface child: %s.\n",
+			    str_error(rc));
+		}
+	}
+
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/main.c
===================================================================
--- uspace/drv/bus/usb/usbmid/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmid/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB multi interface device driver.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/dev/request.h>
+#include <usb/descriptor.h>
+#include <usb/dev/pipes.h>
+
+#include "usbmid.h"
+
+/** Callback when new MID device is attached to the host.
+ *
+ * @param gen_dev Generic DDF device representing the new device.
+ * @return Error code.
+ */
+static int usbmid_add_device(usb_device_t *dev)
+{
+	usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
+
+	usb_pipe_start_long_transfer(&dev->ctrl_pipe);
+
+	bool accept = usbmid_explore_device(dev);
+
+	usb_pipe_end_long_transfer(&dev->ctrl_pipe);
+
+	if (!accept) {
+		return ENOTSUP;
+	}
+
+	return EOK;
+}
+
+/** USB MID driver ops. */
+static usb_driver_ops_t mid_driver_ops = {
+	.add_device = usbmid_add_device,
+};
+
+/** USB MID driver. */
+static usb_driver_t mid_driver = {
+	.name = NAME,
+	.ops = &mid_driver_ops,
+	.endpoints = NULL
+};
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": USB multi interface device driver.\n");
+
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	return usb_driver_main(&mid_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/usbmid.c
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmid/usbmid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2011 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 drvusbmid
+ * @{
+ */
+/**
+ * @file
+ * Helper functions.
+ */
+#include <errno.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <usb_iface.h>
+#include <usb/ddfiface.h>
+#include <usb/dev/pipes.h>
+#include <usb/classes/classes.h>
+#include <usb/dev/recognise.h>
+#include "usbmid.h"
+
+/** Callback for DDF USB interface. */
+static int usb_iface_get_address_impl(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	return usb_iface_get_address_hub_impl(fun, handle, address);
+}
+
+/** Callback for DDF USB interface. */
+static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle,
+    int *iface_no)
+{
+	assert(fun);
+
+	usbmid_interface_t *iface = fun->driver_data;
+	assert(iface);
+
+	if (iface_no != NULL) {
+		*iface_no = iface->interface_no;
+	}
+
+	return EOK;
+}
+
+/** DDF interface of the child - interface function. */
+static usb_iface_t child_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
+	.get_address = usb_iface_get_address_impl,
+	.get_interface = usb_iface_get_interface_impl
+};
+
+/** Operations for children - interface functions. */
+static ddf_dev_ops_t child_device_ops = {
+	.interfaces[USB_DEV_IFACE] = &child_usb_iface
+};
+
+
+/** Spawn new child device from one interface.
+ *
+ * @param parent Parent MID device.
+ * @param iface Interface information.
+ * @param device_descriptor Device descriptor.
+ * @param interface_descriptor Interface descriptor.
+ * @return Error code.
+ */
+int usbmid_spawn_interface_child(usb_device_t *parent,
+    usbmid_interface_t *iface,
+    const usb_standard_device_descriptor_t *device_descriptor,
+    const usb_standard_interface_descriptor_t *interface_descriptor)
+{
+	ddf_fun_t *child = NULL;
+	char *child_name = NULL;
+	int rc;
+
+	/*
+	 * Name is class name followed by interface number.
+	 * The interface number shall provide uniqueness while the
+	 * class name something humanly understandable.
+	 */
+	rc = asprintf(&child_name, "%s%d",
+	    usb_str_class(interface_descriptor->interface_class),
+	    (int) interface_descriptor->interface_number);
+	if (rc < 0) {
+		goto error_leave;
+	}
+
+	/* Create the device. */
+	child = ddf_fun_create(parent->ddf_dev, fun_inner, child_name);
+	if (child == NULL) {
+		rc = ENOMEM;
+		goto error_leave;
+	}
+
+	iface->fun = child;
+
+	child->driver_data = iface;
+	child->ops = &child_device_ops;
+
+	rc = usb_device_create_match_ids_from_interface(device_descriptor,
+	    interface_descriptor,
+	    &child->match_ids);
+	if (rc != EOK) {
+		goto error_leave;
+	}
+
+	rc = ddf_fun_bind(child);
+	if (rc != EOK) {
+		goto error_leave;
+	}
+
+	return EOK;
+
+error_leave:
+	if (child != NULL) {
+		child->name = NULL;
+		/* This takes care of match_id deallocation as well. */
+		ddf_fun_destroy(child);
+	}
+	if (child_name != NULL) {
+		free(child_name);
+	}
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/usbmid.h
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmid/usbmid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 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 drvusbmid
+ * @{
+ */
+/** @file
+ * Common definitions.
+ */
+
+#ifndef USBMID_H_
+#define USBMID_H_
+
+#include <adt/list.h>
+#include <ddf/driver.h>
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/debug.h>
+#include <usb/dev/driver.h>
+
+#define NAME "usbmid"
+
+/** Container for single interface in a MID device. */
+typedef struct {
+	/** Function container. */
+	ddf_fun_t *fun;
+	/** Interface descriptor. */
+	usb_standard_interface_descriptor_t *interface;
+	/** Interface number. */
+	int interface_no;
+	/** List link. */
+	link_t link;
+} usbmid_interface_t;
+
+bool usbmid_explore_device(usb_device_t *);
+int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t *,
+    const usb_standard_device_descriptor_t *,
+    const usb_standard_interface_descriptor_t *);
+void usbmid_dump_descriptors(uint8_t *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmid/usbmid.ma
===================================================================
--- uspace/drv/bus/usb/usbmid/usbmid.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmid/usbmid.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+100 usb&mid
Index: uspace/drv/bus/usb/usbmouse/Makefile
===================================================================
--- uspace/drv/bus/usb/usbmouse/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmouse/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBHID_PREFIX)/libusbhid.a \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHID_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+
+BINARY = usbmouse
+
+SOURCES = \
+	init.c \
+	main.c \
+	mouse.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbmouse/init.c
===================================================================
--- uspace/drv/bus/usb/usbmouse/init.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmouse/init.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2011 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Initialization routines for USB mouse driver.
+ */
+
+#include "mouse.h"
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <usb/hid/hid.h>
+#include <usb/dev/request.h>
+#include <usb/hid/request.h>
+#include <errno.h>
+
+/** Mouse polling endpoint description for boot protocol subclass. */
+usb_endpoint_description_t poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HID,
+	.interface_subclass = USB_HID_SUBCLASS_BOOT,
+	.interface_protocol = USB_HID_PROTOCOL_MOUSE,
+	.flags = 0
+};
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param fun     Device function handling the call.
+ * @param icallid Call ID.
+ * @param icall   Call data.
+ *
+ */
+static void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid,
+    ipc_call_t *icall)
+{
+	usb_mouse_t *mouse = (usb_mouse_t *) fun->driver_data;
+	assert(mouse != NULL);
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
+	
+	if (callback) {
+		if (mouse->console_sess == NULL) {
+			mouse->console_sess = callback;
+			async_answer_0(icallid, EOK);
+		} else
+			async_answer_0(icallid, ELIMIT);
+	} else
+		async_answer_0(icallid, EINVAL);
+}
+
+/** Device ops for USB mouse. */
+static ddf_dev_ops_t mouse_ops = {
+	.default_handler = default_connection_handler
+};
+
+/** Create USB mouse device.
+ *
+ * The mouse device is stored into <code>dev-&gt;driver_data</code>.
+ *
+ * @param dev Generic device.
+ * @return Error code.
+ */
+int usb_mouse_create(usb_device_t *dev)
+{
+	usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
+	if (mouse == NULL)
+		return ENOMEM;
+	
+	mouse->dev = dev;
+	mouse->console_sess = NULL;
+	
+	int rc;
+	
+	/* Create DDF function. */
+	mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse");
+	if (mouse->mouse_fun == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+	
+	mouse->mouse_fun->ops = &mouse_ops;
+	
+	rc = ddf_fun_bind(mouse->mouse_fun);
+	if (rc != EOK)
+		goto leave;
+	
+	/* Add the function to mouse class. */
+	rc = ddf_fun_add_to_category(mouse->mouse_fun, "mouse");
+	if (rc != EOK)
+		goto leave;
+	
+	/* Set the boot protocol. */
+	rc = usbhid_req_set_protocol(&dev->ctrl_pipe, dev->interface_no,
+	    USB_HID_PROTOCOL_BOOT);
+	if (rc != EOK)
+		goto leave;
+	
+	/* Everything allright. */
+	dev->driver_data = mouse;
+	mouse->mouse_fun->driver_data = mouse;
+	
+	return EOK;
+	
+leave:
+	free(mouse);
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/main.c
===================================================================
--- uspace/drv/bus/usb/usbmouse/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmouse/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2011 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Main routines of USB boot protocol mouse driver.
+ */
+
+#include "mouse.h"
+#include <usb/debug.h>
+#include <usb/dev/poll.h>
+#include <errno.h>
+#include <str_error.h>
+
+#define NAME  "usbmouse"
+
+/** Callback when new mouse device is attached and recognised by DDF.
+ *
+ * @param dev Representation of a generic DDF device.
+ *
+ * @return Error code.
+ *
+ */
+static int usbmouse_add_device(usb_device_t *dev)
+{
+	int rc = usb_mouse_create(dev);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize device driver: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_log_debug("Polling pipe at endpoint %d.\n",
+	    dev->pipes[0].pipe->endpoint_no);
+	
+	rc = usb_device_auto_poll(dev, 0, usb_mouse_polling_callback,
+	    dev->pipes[0].pipe->max_packet_size,
+	    usb_mouse_polling_ended_callback, dev->driver_data);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to start polling fibril: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_log_info("controlling new mouse (handle %" PRIun ").\n",
+	    dev->ddf_dev->handle);
+	
+	return EOK;
+}
+
+/** USB mouse driver ops. */
+static usb_driver_ops_t mouse_driver_ops = {
+	.add_device = usbmouse_add_device,
+};
+
+static usb_endpoint_description_t *endpoints[] = {
+	&poll_endpoint_description,
+	NULL
+};
+
+/** USB mouse driver. */
+static usb_driver_t mouse_driver = {
+	.name = NAME,
+	.ops = &mouse_driver_ops,
+	.endpoints = endpoints
+};
+
+int main(int argc, char *argv[])
+{
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+	return usb_driver_main(&mouse_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/mouse.c
===================================================================
--- uspace/drv/bus/usb/usbmouse/mouse.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmouse/mouse.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Actual handling of USB mouse protocol.
+ */
+
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ipc/mouseev.h>
+#include <async.h>
+#include "mouse.h"
+
+/** Mouse polling callback.
+ *
+ * @param dev    Device that is being polled.
+ * @param buffer Data buffer.
+ * @param size   Buffer size in bytes.
+ * @param arg    Pointer to usb_mouse_t.
+ *
+ * @return Always true.
+ *
+ */
+bool usb_mouse_polling_callback(usb_device_t *dev, uint8_t *buffer,
+    size_t size, void *arg)
+{
+	usb_mouse_t *mouse = (usb_mouse_t *) arg;
+	
+	usb_log_debug2("got buffer: %s.\n",
+	    usb_debug_str_buffer(buffer, size, 0));
+	
+	uint8_t butt = buffer[0];
+	char str_buttons[4] = {
+		butt & 1 ? '#' : '.',
+		butt & 2 ? '#' : '.',
+		butt & 4 ? '#' : '.',
+		0
+	};
+	
+	int shift_x = ((int) buffer[1]) - 127;
+	int shift_y = ((int) buffer[2]) - 127;
+	int wheel = ((int) buffer[3]) - 127;
+	
+	if (buffer[1] == 0)
+		shift_x = 0;
+	
+	if (buffer[2] == 0)
+		shift_y = 0;
+	
+	if (buffer[3] == 0)
+		wheel = 0;
+	
+	if (mouse->console_sess) {
+		if ((shift_x != 0) || (shift_y != 0)) {
+			// FIXME: guessed for QEMU
+			
+			async_exch_t *exch = async_exchange_begin(mouse->console_sess);
+			async_req_2_0(exch, MOUSEEV_MOVE_EVENT, -shift_x / 10, -shift_y / 10);
+			async_exchange_end(exch);
+		}
+		if (butt) {
+			// FIXME: proper button clicking
+			
+			async_exch_t *exch = async_exchange_begin(mouse->console_sess);
+			async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, 1, 1);
+			async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, 1, 0);
+			async_exchange_end(exch);
+		}
+	}
+	
+	usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
+	    str_buttons, shift_x, shift_y, wheel);
+	
+	/* Guess. */
+	async_usleep(1000);
+	
+	return true;
+}
+
+/** Callback when polling is terminated.
+ *
+ * @param dev              Device where the polling terminated.
+ * @param recurring_errors Whether the polling was terminated due to
+ *                         recurring errors.
+ * @param arg              Pointer to usb_mouse_t.
+ *
+ */
+void usb_mouse_polling_ended_callback(usb_device_t *dev, bool recurring_errors,
+    void *arg)
+{
+	usb_mouse_t *mouse = (usb_mouse_t *) arg;
+	
+	async_hangup(mouse->console_sess);
+	mouse->console_sess = NULL;
+	
+	usb_device_destroy(dev);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/mouse.h
===================================================================
--- uspace/drv/bus/usb/usbmouse/mouse.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmouse/mouse.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011 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 drvusbmouse
+ * @{
+ */
+/**
+ * @file
+ * Common definitions for USB mouse driver.
+ */
+
+#ifndef USBMOUSE_MOUSE_H_
+#define USBMOUSE_MOUSE_H_
+
+#include <usb/dev/driver.h>
+#include <usb/dev/pipes.h>
+#include <time.h>
+#include <async.h>
+
+#define POLL_PIPE(dev) \
+	((dev)->pipes[0].pipe)
+
+/** Container for USB mouse device. */
+typedef struct {
+	/** Generic device container. */
+	usb_device_t *dev;
+	
+	/** Function representing the device. */
+	ddf_fun_t *mouse_fun;
+	
+	/** Polling interval in microseconds. */
+	suseconds_t poll_interval_us;
+	
+	/** Callback session to console (consumer). */
+	async_sess_t *console_sess;
+} usb_mouse_t;
+
+extern usb_endpoint_description_t poll_endpoint_description;
+
+extern int usb_mouse_create(usb_device_t *);
+extern bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t,
+    void *);
+extern void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbmouse/usbmouse.ma
===================================================================
--- uspace/drv/bus/usb/usbmouse/usbmouse.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/usbmouse/usbmouse.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+100 usb&interface&class=HID&subclass=0x01&protocol=0x02
Index: uspace/drv/bus/usb/vhc/Makefile
===================================================================
--- uspace/drv/bus/usb/vhc/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,57 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSBHOST_PREFIX)/libusbhost.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBUSBVIRT_PREFIX)/libusbvirt.a \
+	$(LIBDRV_PREFIX)/libdrv.a
+
+EXTRA_CFLAGS += \
+	-I$(LIBUSBVIRT_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBUSBHOST_PREFIX)/include \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include
+BINARY = vhc
+
+SOURCES = \
+	hub/virthub.c \
+	hub/hub.c \
+	hub/virthubops.c \
+	conndev.c \
+	connhost.c \
+	devconn.c \
+	hub.c \
+	main.c \
+	transfer.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/vhc/conn.h
===================================================================
--- uspace/drv/bus/usb/vhc/conn.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/conn.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Connection handling of incoming calls.
+ */
+#ifndef VHCD_CONN_H_
+#define VHCD_CONN_H_
+
+#include <usb/usb.h>
+#include <usbhc_iface.h>
+#include <usb_iface.h>
+#include "vhcd.h"
+
+extern usbhc_iface_t vhc_iface;
+extern usb_iface_t vhc_usb_iface;
+extern usb_iface_t rh_usb_iface;
+
+void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
+void on_client_close(ddf_fun_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/conndev.c
===================================================================
--- uspace/drv/bus/usb/vhc/conndev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/conndev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2011 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * Connection handling of calls from virtual device (implementation).
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <ddf/driver.h>
+#include <usbvirt/ipc.h>
+#include <async.h>
+#include "conn.h"
+
+static fibril_local uintptr_t plugged_device_handle = 0;
+#define PLUGGED_DEVICE_NAME_MAXLEN 256
+static fibril_local char plugged_device_name[PLUGGED_DEVICE_NAME_MAXLEN + 1] = "<unknown>";
+
+/** Receive device name.
+ *
+ * @warning Errors are silently ignored.
+ *
+ * @param sess Session to the virtual device.
+ *
+ */
+static void receive_device_name(async_sess_t *sess)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	aid_t opening_request = async_send_0(exch, IPC_M_USBVIRT_GET_NAME, NULL);
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		return;
+	}
+	
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(exch, plugged_device_name,
+	     PLUGGED_DEVICE_NAME_MAXLEN, &data_request_call);
+	
+	async_exchange_end(exch);
+	
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return;
+	}
+	
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	if ((data_request_rc != EOK) || (opening_request_rc != EOK))
+		return;
+	
+	size_t len = IPC_GET_ARG2(data_request_call);
+	plugged_device_name[len] = 0;
+}
+
+/** Default handler for IPC methods not handled by DDF.
+ *
+ * @param fun Device handling the call.
+ * @param icallid Call id.
+ * @param icall Call data.
+ */
+void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid,
+    ipc_call_t *icall)
+{
+	vhc_data_t *vhc = fun->dev->driver_data;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
+	
+	if (callback) {
+		int rc = vhc_virtdev_plug(vhc, callback, &plugged_device_handle);
+		if (rc != EOK) {
+			async_answer_0(icallid, rc);
+			async_hangup(callback);
+			return;
+		}
+		
+		async_answer_0(icallid, EOK);
+		
+		receive_device_name(callback);
+		
+		usb_log_info("New virtual device `%s' (id: %" PRIxn ").\n",
+		    plugged_device_name, plugged_device_handle);
+	} else
+		async_answer_0(icallid, EINVAL);
+}
+
+/** Callback when client disconnects.
+ *
+ * Used to unplug virtual USB device.
+ *
+ * @param fun
+ */
+void on_client_close(ddf_fun_t *fun)
+{
+	vhc_data_t *vhc = fun->dev->driver_data;
+
+	if (plugged_device_handle != 0) {
+		usb_log_info("Virtual device `%s' disconnected (id: %" PRIxn ").\n",
+		    plugged_device_name, plugged_device_handle);
+		vhc_virtdev_unplug(vhc, plugged_device_handle);
+	}
+}
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/connhost.c
===================================================================
--- uspace/drv/bus/usb/vhc/connhost.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/connhost.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2011 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * Host controller interface implementation.
+ */
+#include <assert.h>
+#include <errno.h>
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+#include <usbhc_iface.h>
+#include "vhcd.h"
+
+#define GET_VHC_DATA(fun) \
+	((vhc_data_t *)fun->dev->driver_data)
+#define VHC_DATA(vhc, fun) \
+	vhc_data_t *vhc = GET_VHC_DATA(fun); assert(vhc->magic == 0xdeadbeef)
+
+#define UNSUPPORTED(methodname) \
+	usb_log_warning("Unsupported interface method `%s()' in %s:%d.\n", \
+	    methodname, __FILE__, __LINE__)
+
+/** Found free USB address.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] speed Speed of the device that will get this address.
+ * @param[out] address Non-null pointer where to store the free address.
+ * @return Error code.
+ */
+static int request_address(ddf_fun_t *fun, usb_speed_t speed,
+    usb_address_t *address)
+{
+	VHC_DATA(vhc, fun);
+
+	usb_address_t addr = device_keeper_get_free_address(&vhc->dev_keeper,
+	    USB_SPEED_HIGH);
+	if (addr < 0) {
+		return addr;
+	}
+
+	if (address != NULL) {
+		*address = addr;
+	}
+
+	return EOK;
+}
+
+/** Bind USB address with device devman handle.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] handle Devman handle of the device.
+ * @return Error code.
+ */
+static int bind_address(ddf_fun_t *fun,
+    usb_address_t address, devman_handle_t handle)
+{
+	VHC_DATA(vhc, fun);
+	usb_log_debug("Binding handle %" PRIun " to address %d.\n",
+	    handle, address);
+	usb_device_keeper_bind(&vhc->dev_keeper, address, handle);
+
+	return EOK;
+}
+
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	VHC_DATA(vhc, fun);
+	bool found =
+	    usb_device_keeper_find_by_address(&vhc->dev_keeper, address, handle);
+	return found ? EOK : ENOENT;
+}
+
+/** Release previously requested address.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address to be released.
+ * @return Error code.
+ */
+static int release_address(ddf_fun_t *fun, usb_address_t address)
+{
+	VHC_DATA(vhc, fun);
+	usb_log_debug("Releasing address %d...\n", address);
+	usb_device_keeper_release(&vhc->dev_keeper, address);
+
+	return ENOTSUP;
+}
+
+/** Register endpoint for bandwidth reservation.
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] speed Endpoint speed (invalid means to use device one).
+ * @param[in] endpoint Endpoint number.
+ * @param[in] transfer_type USB transfer type.
+ * @param[in] direction Endpoint data direction.
+ * @param[in] max_packet_size Max packet size of the endpoint.
+ * @param[in] interval Polling interval.
+ * @return Error code.
+ */
+static int register_endpoint(ddf_fun_t *fun,
+    usb_address_t address, usb_speed_t speed, usb_endpoint_t endpoint,
+    usb_transfer_type_t transfer_type, usb_direction_t direction,
+    size_t max_packet_size, unsigned int interval)
+{
+	/* TODO: Use usb_endpoint_manager_add_ep */
+	VHC_DATA(vhc, fun);
+
+	endpoint_t *ep = endpoint_get(
+	    address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1);
+	if (ep == NULL) {
+		return ENOMEM;
+	}
+
+	int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
+	if (rc != EOK) {
+		endpoint_destroy(ep);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Unregister endpoint (free some bandwidth reservation).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] address USB address of the device.
+ * @param[in] endpoint Endpoint number.
+ * @param[in] direction Endpoint data direction.
+ * @return Error code.
+ */
+static int unregister_endpoint(ddf_fun_t *fun, usb_address_t address,
+    usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	VHC_DATA(vhc, fun);
+
+	endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
+	    address, endpoint, direction, NULL);
+	if (ep == NULL) {
+		return ENOENT;
+	}
+
+	int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
+	    address, endpoint, direction);
+
+	return rc;
+}
+
+/** Schedule interrupt out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_out(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	VHC_DATA(vhc, fun);
+
+	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
+	    target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_INTERRUPT,
+	    fun, arg);
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->data_buffer = data;
+	transfer->data_buffer_size = size;
+	transfer->callback_out = callback;
+
+	int rc = vhc_virtdev_add_transfer(vhc, transfer);
+	if (rc != EOK) {
+		free(transfer);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Schedule interrupt in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int interrupt_in(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	VHC_DATA(vhc, fun);
+
+	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
+	    target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_INTERRUPT,
+	    fun, arg);
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->data_buffer = data;
+	transfer->data_buffer_size = size;
+	transfer->callback_in = callback;
+
+	int rc = vhc_virtdev_add_transfer(vhc, transfer);
+	if (rc != EOK) {
+		free(transfer);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Schedule bulk out transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Data to be sent (in USB endianess, allocated and deallocated
+ *	by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_out(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	UNSUPPORTED("bulk_out");
+
+	return ENOTSUP;
+}
+
+/** Schedule bulk in transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] data Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] size Size of the @p data buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int bulk_in(ddf_fun_t *fun, usb_target_t target,
+    void *data, size_t size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	UNSUPPORTED("bulk_in");
+
+	return ENOTSUP;
+}
+
+/** Schedule control write transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Data buffer (in USB endianess, allocated and
+ *	deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_write(ddf_fun_t *fun, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data_buffer, size_t data_buffer_size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	VHC_DATA(vhc, fun);
+
+	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
+	    target.endpoint, USB_DIRECTION_OUT, USB_TRANSFER_CONTROL,
+	    fun, arg);
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->setup_buffer = setup_packet;
+	transfer->setup_buffer_size = setup_packet_size;
+	transfer->data_buffer = data_buffer;
+	transfer->data_buffer_size = data_buffer_size;
+	transfer->callback_out = callback;
+
+	int rc = vhc_virtdev_add_transfer(vhc, transfer);
+	if (rc != EOK) {
+		free(transfer);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Schedule control read transfer.
+ *
+ * The callback is supposed to be called once the transfer (on the wire) is
+ * complete regardless of the outcome.
+ * However, the callback could be called only when this function returns
+ * with success status (i.e. returns EOK).
+ *
+ * @param[in] fun Device function the action was invoked on.
+ * @param[in] target Target pipe (address and endpoint number) specification.
+ * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated
+ *	and deallocated by the caller).
+ * @param[in] setup_packet_size Size of @p setup_packet buffer in bytes.
+ * @param[in] data_buffer Buffer where to store the data (in USB endianess,
+ *	allocated and deallocated by the caller).
+ * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.
+ * @param[in] callback Callback to be issued once the transfer is complete.
+ * @param[in] arg Pass-through argument to the callback.
+ * @return Error code.
+ */
+static int control_read(ddf_fun_t *fun, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data_buffer, size_t data_buffer_size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	VHC_DATA(vhc, fun);
+
+	vhc_transfer_t *transfer = vhc_transfer_create(target.address,
+	    target.endpoint, USB_DIRECTION_IN, USB_TRANSFER_CONTROL,
+	    fun, arg);
+	if (transfer == NULL) {
+		return ENOMEM;
+	}
+
+	transfer->setup_buffer = setup_packet;
+	transfer->setup_buffer_size = setup_packet_size;
+	transfer->data_buffer = data_buffer;
+	transfer->data_buffer_size = data_buffer_size;
+	transfer->callback_in = callback;
+
+	int rc = vhc_virtdev_add_transfer(vhc, transfer);
+	if (rc != EOK) {
+		free(transfer);
+		return rc;
+	}
+
+	return EOK;
+}
+
+static int tell_address(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	UNSUPPORTED("tell_address");
+
+	return ENOTSUP;
+}
+
+static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun,
+    devman_handle_t *handle)
+{
+	VHC_DATA(vhc, root_hub_fun);
+
+	*handle = vhc->hc_fun->handle;
+
+	return EOK;
+}
+
+static int tell_address_rh(ddf_fun_t *root_hub_fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	VHC_DATA(vhc, root_hub_fun);
+
+	if (handle == 0) {
+		handle = root_hub_fun->handle;
+	}
+
+	usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
+	usb_address_t addr = usb_device_keeper_find(&vhc->dev_keeper, handle);
+	if (addr < 0) {
+		return addr;
+	} else {
+		*address = addr;
+		return EOK;
+	}
+}
+
+usbhc_iface_t vhc_iface = {
+	.request_address = request_address,
+	.bind_address = bind_address,
+	.find_by_address = find_by_address,
+	.release_address = release_address,
+
+	.register_endpoint = register_endpoint,
+	.unregister_endpoint = unregister_endpoint,
+
+	.interrupt_out = interrupt_out,
+	.interrupt_in = interrupt_in,
+
+	.bulk_in = bulk_in,
+	.bulk_out = bulk_out,
+
+	.control_write = control_write,
+	.control_read = control_read
+};
+
+usb_iface_t vhc_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_hc_impl,
+	.get_address = tell_address
+};
+
+usb_iface_t rh_usb_iface = {
+	.get_hc_handle = usb_iface_get_hc_handle_rh_impl,
+	.get_address = tell_address_rh
+};
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/devconn.c
===================================================================
--- uspace/drv/bus/usb/vhc/devconn.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/devconn.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <errno.h>
+#include "vhcd.h"
+#include "hub/virthub.h"
+
+
+static vhc_virtdev_t *vhc_virtdev_create()
+{
+	vhc_virtdev_t *dev = malloc(sizeof(vhc_virtdev_t));
+	if (dev == NULL) {
+		return NULL;
+	}
+	dev->address = 0;
+	dev->dev_sess = NULL;
+	dev->dev_local = NULL;
+	dev->plugged = true;
+	link_initialize(&dev->link);
+	fibril_mutex_initialize(&dev->guard);
+	list_initialize(&dev->transfer_queue);
+
+	return dev;
+}
+
+static int vhc_virtdev_plug_generic(vhc_data_t *vhc,
+    async_sess_t *sess, usbvirt_device_t *virtdev,
+    uintptr_t *handle, bool connect)
+{
+	vhc_virtdev_t *dev = vhc_virtdev_create();
+	if (dev == NULL) {
+		return ENOMEM;
+	}
+
+	dev->dev_sess = sess;
+	dev->dev_local = virtdev;
+
+	fibril_mutex_lock(&vhc->guard);
+	list_append(&dev->link, &vhc->devices);
+	fibril_mutex_unlock(&vhc->guard);
+
+	fid_t fibril = fibril_create(vhc_transfer_queue_processor, dev);
+	if (fibril == 0) {
+		free(dev);
+		return ENOMEM;
+	}
+	fibril_add_ready(fibril);
+
+	if (handle != NULL) {
+		*handle = (uintptr_t) dev;
+	}
+
+	if (connect) {
+		// FIXME: check status
+		(void) virthub_connect_device(vhc->hub, dev);
+	}
+
+	return EOK;
+}
+
+int vhc_virtdev_plug(vhc_data_t *vhc, async_sess_t *sess, uintptr_t *handle)
+{
+	return vhc_virtdev_plug_generic(vhc, sess, NULL, handle, true);
+}
+
+int vhc_virtdev_plug_local(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
+{
+	return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, true);
+}
+
+int vhc_virtdev_plug_hub(vhc_data_t *vhc, usbvirt_device_t *dev, uintptr_t *handle)
+{
+	return vhc_virtdev_plug_generic(vhc, NULL, dev, handle, false);
+}
+
+void vhc_virtdev_unplug(vhc_data_t *vhc, uintptr_t handle)
+{
+	vhc_virtdev_t *dev = (vhc_virtdev_t *) handle;
+
+	// FIXME: check status
+	(void) virthub_disconnect_device(vhc->hub, dev);
+
+	fibril_mutex_lock(&vhc->guard);
+	fibril_mutex_lock(&dev->guard);
+	dev->plugged = false;
+	list_remove(&dev->link);
+	fibril_mutex_unlock(&dev->guard);
+	fibril_mutex_unlock(&vhc->guard);
+}
Index: uspace/drv/bus/usb/vhc/hub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,135 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Virtual USB hub.
+ */
+
+#include <usb/classes/classes.h>
+#include <usbvirt/device.h>
+#include <errno.h>
+#include <async.h>
+#include <str_error.h>
+#include <stdlib.h>
+#include <ddf/driver.h>
+#include <devman.h>
+#include <usb/dev/hub.h>
+#include <usb/dev/recognise.h>
+
+#include "hub.h"
+#include "vhcd.h"
+#include "conn.h"
+
+usbvirt_device_t virtual_hub_device = {
+	.name = "root hub",
+	.ops = &hub_ops,
+	.address = 0
+};
+
+static ddf_dev_ops_t rh_ops = {
+	.interfaces[USB_DEV_IFACE] = &rh_usb_iface,
+};
+
+static int hub_register_in_devman_fibril(void *arg);
+
+void virtual_hub_device_init(ddf_fun_t *hc_dev)
+{
+	virthub_init(&virtual_hub_device);
+
+	/*
+	 * We need to register the root hub.
+	 * This must be done in separate fibril because the device
+	 * we are connecting to are ourselves and we cannot connect
+	 * before leaving the add_device() function.
+	 */
+	fid_t root_hub_registration
+	    = fibril_create(hub_register_in_devman_fibril, hc_dev);
+	if (root_hub_registration == 0) {
+		usb_log_fatal("Failed to create hub registration fibril.\n");
+		return;
+	}
+
+	fibril_add_ready(root_hub_registration);
+}
+
+static int pretend_port_rest(int unused, void *unused2)
+{
+	return EOK;
+}
+
+/** Register root hub in devman.
+ *
+ * @param arg Host controller device (type <code>device_t *</code>).
+ * @return Error code.
+ */
+int hub_register_in_devman_fibril(void *arg)
+{
+	ddf_fun_t *hc_dev = (ddf_fun_t *) arg;
+
+	/*
+	 * Wait until parent device is properly initialized.
+	 */
+	async_sess_t *sess;
+	do {
+		sess = devman_device_connect(EXCHANGE_SERIALIZE, hc_dev->handle, 0);
+	} while (!sess);
+	async_hangup(sess);
+
+	int rc;
+
+	usb_hc_connection_t hc_conn;
+	rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle);
+	assert(rc == EOK);
+
+	rc = usb_hc_connection_open(&hc_conn);
+	assert(rc == EOK);
+
+	ddf_fun_t *hub_dev;
+	rc = usb_hc_new_device_wrapper(hc_dev->dev, &hc_conn,
+	    USB_SPEED_FULL,
+	    pretend_port_rest, 0, NULL,
+	    NULL, NULL, &rh_ops, hc_dev, &hub_dev);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to create root hub: %s.\n",
+		    str_error(rc));
+	}
+
+	usb_hc_connection_close(&hc_conn);
+
+	usb_log_info("Created root hub function (handle %zu).\n",
+	    (size_t) hub_dev->handle);
+
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub.h
===================================================================
--- uspace/drv/bus/usb/vhc/hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,52 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Virtual USB hub.
+ */
+
+#ifndef VHCD_HUB_H_
+#define VHCD_HUB_H_
+
+#include <usbvirt/device.h>
+#include <ddf/driver.h>
+
+#include "hub/hub.h"
+#include "hub/virthub.h"
+
+extern usbvirt_device_t virtual_hub_device;
+
+void virtual_hub_device_init(ddf_fun_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/hub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub/hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/hub/hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,523 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Representation of an USB hub (implementation).
+ */
+#include <usb/classes/classes.h>
+#include <usbvirt/device.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ddf/driver.h>
+#include <usb/debug.h>
+
+#include "hub.h"
+
+
+/** Produce a byte from bit values.
+ */
+#define MAKE_BYTE(b0, b1, b2, b3, b4, b5, b6, b7) \
+	(( \
+		((b0) << 0) \
+		| ((b1) << 1) \
+		| ((b2) << 2) \
+		| ((b3) << 3) \
+		| ((b4) << 4) \
+		| ((b5) << 5) \
+		| ((b6) << 6) \
+		| ((b7) << 7) \
+	))
+
+/* Static functions. */
+static hub_port_t *get_hub_port(hub_t *, size_t);
+static void set_port_status_change(hub_port_t *, hub_status_change_t);
+static void clear_port_status_change(hub_port_t *, uint16_t);
+static int set_port_state_delayed_fibril(void *);
+static void set_port_state_delayed(hub_t *, size_t, suseconds_t,
+    hub_port_state_t, hub_port_state_t);
+
+/** Convert hub port state to a char. */
+char hub_port_state_to_char(hub_port_state_t state) {
+	switch (state) {
+		case HUB_PORT_STATE_NOT_CONFIGURED:
+			return '-';
+		case HUB_PORT_STATE_POWERED_OFF:
+			return 'O';
+		case HUB_PORT_STATE_DISCONNECTED:
+			return 'X';
+		case HUB_PORT_STATE_DISABLED:
+			return 'D';
+		case HUB_PORT_STATE_RESETTING:
+			return 'R';
+		case HUB_PORT_STATE_ENABLED:
+			return 'E';
+		case HUB_PORT_STATE_SUSPENDED:
+			return 'S';
+		case HUB_PORT_STATE_RESUMING:
+			return 'F';
+		default:
+			return '?';
+	}
+}
+
+/** Initialize single hub port.
+ *
+ * @param port Port to be initialized.
+ * @param index Port index (one based).
+ */
+static void hub_init_port(hub_port_t *port, hub_t *hub, size_t index)
+{
+	port->connected_device = NULL;
+	port->index = index;
+	port->state = HUB_PORT_STATE_NOT_CONFIGURED;
+	port->status_change = 0;
+	port->hub = hub;
+}
+
+/** Initialize the hub.
+ *
+ * @param hub Hub to be initialized.
+ */
+void hub_init(hub_t *hub)
+{
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_init_port(&hub->ports[i], hub, i + 1);
+	}
+	hub->custom_data = NULL;
+	hub->signal_changes = true;
+	fibril_mutex_initialize(&hub->guard);
+}
+
+/** Connect a device to the hub.
+ *
+ * @param hub Hub to connect device to.
+ * @param device Device to be connected.
+ * @return Index of port the device was connected to.
+ * @retval -1 No free port available.
+ */
+size_t hub_connect_device(hub_t *hub, void *device)
+{
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_port_t *port = &hub->ports[i];
+
+		if (port->connected_device != NULL) {
+			continue;
+		}
+
+		port->connected_device = device;
+
+		/*
+		 * TODO:
+		 * If the hub was configured, we can normally
+		 * announce the plug-in.
+		 * Otherwise, we will wait until hub is configured
+		 * and announce changes in single burst.
+		 */
+		//if (port->state == HUB_PORT_STATE_DISCONNECTED) {
+			port->state = HUB_PORT_STATE_DISABLED;
+			set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
+		//}
+
+		return i;
+	}
+
+	return (size_t) -1;
+}
+
+/** Disconnects a device from a hub.
+ *
+ * @param hub Hub the device was connected to.
+ * @param device Device to be disconnected.
+ * @return Error code.
+ */
+int hub_disconnect_device(hub_t *hub, void *device)
+{
+	size_t index = hub_find_device(hub, device);
+	if (index == (size_t) -1) {
+		return ENOENT;
+	}
+
+	hub_port_t *port = &hub->ports[index];
+
+	port->connected_device = NULL;
+	port->state = HUB_PORT_STATE_DISCONNECTED;
+	set_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
+
+	return EOK;
+}
+
+/** Find port device is connected to.
+ *
+ * @param hub Hub in question.
+ * @param device Device in question.
+ * @return Port index (zero based).
+ * @retval -1 Device is not connected.
+ */
+size_t hub_find_device(hub_t *hub, void *device)
+{
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_port_t *port = &hub->ports[i];
+
+		if (port->connected_device == device) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+
+/** Acquire exclusive access to the hub.
+ *
+ * @param hub Hub in question.
+ */
+void hub_acquire(hub_t *hub)
+{
+	fibril_mutex_lock(&hub->guard);
+}
+
+/** Give up exclusive access to the hub.
+ *
+ * @param hub Hub in question.
+ */
+void hub_release(hub_t *hub)
+{
+	fibril_mutex_unlock(&hub->guard);
+}
+
+/** Change port state.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @param state New port state.
+ */
+void hub_set_port_state(hub_t *hub, size_t port_index, hub_port_state_t state)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return;
+	}
+
+	usb_log_debug("Setting port %zu to state %d.\n", port_index, state);
+
+	switch (state) {
+		case HUB_PORT_STATE_POWERED_OFF:
+			clear_port_status_change(port, HUB_STATUS_C_PORT_CONNECTION);
+			clear_port_status_change(port, HUB_STATUS_C_PORT_ENABLE);
+			clear_port_status_change(port, HUB_STATUS_C_PORT_RESET);
+			break;
+		case HUB_PORT_STATE_RESUMING:
+			port->state = state;
+			set_port_state_delayed(hub, port_index,
+			    10, state, HUB_PORT_STATE_ENABLED);
+			break;
+		case HUB_PORT_STATE_RESETTING:
+			port->state = state;
+			set_port_state_delayed(hub, port_index,
+			    10, state, HUB_PORT_STATE_ENABLED);
+			break;
+		case HUB_PORT_STATE_ENABLED:
+			if (port->state == HUB_PORT_STATE_RESETTING) {
+				set_port_status_change(port, HUB_STATUS_C_PORT_RESET);
+			}
+			break;
+		default:
+			break;
+	}
+
+	port->state = state;
+}
+
+/** Change state of all ports.
+ *
+ * @param hub Hub in question.
+ * @param state New state for all ports.
+ */
+void hub_set_port_state_all(hub_t *hub, hub_port_state_t state)
+{
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_set_port_state(hub, i, state);
+	}
+}
+
+/** Get port state.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @return Port state.
+ */
+hub_port_state_t hub_get_port_state(hub_t *hub, size_t port_index)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return HUB_PORT_STATE_UNKNOWN;
+	}
+
+	return port->state;
+}
+
+/** Clear port status change bit.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @param change Change to be cleared.
+ */
+void hub_clear_port_status_change(hub_t *hub, size_t port_index,
+    hub_status_change_t change)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return;
+	}
+
+	clear_port_status_change(port, change);
+}
+
+/** Get port status change bits.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @return Port status change bitmap in standard format.
+ */
+uint16_t hub_get_port_status_change(hub_t *hub, size_t port_index)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return 0;
+	}
+
+	return port->status_change;
+}
+
+/** Get port status bits.
+ *
+ * @param hub Hub the port belongs to.
+ * @param port_index Port index (zero based).
+ * @return Port status bitmap in standard format.
+ */
+uint32_t hub_get_port_status(hub_t *hub, size_t port_index)
+{
+	hub_port_t *port = get_hub_port(hub, port_index);
+	if (port == NULL) {
+		return 0;
+	}
+
+	uint32_t status;
+	status = MAKE_BYTE(
+	    /* Current connect status. */
+	    port->connected_device == NULL ? 0 : 1,
+	    /* Port enabled/disabled. */
+	    port->state == HUB_PORT_STATE_ENABLED ? 1 : 0,
+	    /* Suspend. */
+	    (port->state == HUB_PORT_STATE_SUSPENDED)
+		|| (port->state == HUB_PORT_STATE_RESUMING) ? 1 : 0,
+	    /* Over-current. */
+	    0,
+	    /* Reset. */
+	    port->state == HUB_PORT_STATE_RESETTING ? 1 : 0,
+	    /* Reserved. */
+	    0, 0, 0)
+
+	    | (MAKE_BYTE(
+	    /* Port power. */
+	    port->state == HUB_PORT_STATE_POWERED_OFF ? 0 : 1,
+	    /* Full-speed device. */
+	    0,
+	    /* Reserved. */
+	    0, 0, 0, 0, 0, 0
+	    )) << 8;
+
+	status |= (port->status_change << 16);
+
+	return status;
+}
+
+/** Create hub status change bitmap.
+ *
+ * @warning This function assumes that the whole bitmap fits into 8 bits.
+ *
+ * @param hub Hub in question.
+ * @return Hub status change bitmap.
+ */
+uint8_t hub_get_status_change_bitmap(hub_t *hub)
+{
+	uint8_t change_map = 0;
+
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		hub_port_t *port = &hub->ports[i];
+
+		if (port->status_change != 0) {
+			change_map |= (1 << port->index);
+		}
+	}
+
+	return change_map;
+}
+
+
+/*
+ *
+ * STATIC (HELPER) FUNCTIONS
+ *
+ */
+
+/** Find a port in a hub.
+ *
+ * @param hub Hub in question.
+ * @param port Port index (zero based).
+ * @return Port structure.
+ * @retval NULL Invalid port index.
+ */
+static hub_port_t *get_hub_port(hub_t *hub, size_t port)
+{
+	if (port >= HUB_PORT_COUNT) {
+		return NULL;
+	}
+
+	return &hub->ports[port];
+}
+
+/** Adds a port status change to a port.
+ *
+ * @param port The port with status change.
+ * @param change Change to be added to the status.
+ */
+static void set_port_status_change(hub_port_t *port,
+    hub_status_change_t change)
+{
+	assert(port != NULL);
+	uint16_t old_value = port->status_change;
+	port->status_change |= change;
+	usb_log_debug("Changing status change on %zu: %04x => %04x\n",
+	    port->index,
+	    (unsigned int) old_value, (unsigned int) port->status_change);
+	port->hub->signal_changes = true;
+}
+
+/** Clears a port status change on a port.
+ *
+ * @param port The port with status change.
+ * @param change Change to be removed from the status.
+ */
+static void clear_port_status_change(hub_port_t *port,
+    uint16_t change)
+{
+	assert(port != NULL);
+	port->status_change &= (~change);
+	port->hub->signal_changes = true;
+}
+
+/** Structure for automatic (delayed) port state change. */
+struct delay_port_state_change {
+	/** Delay in microseconds. */
+	suseconds_t delay;
+	/** Old state of the port. */
+	hub_port_state_t old_state;
+	/** New state of the port. */
+	hub_port_state_t new_state;
+	/** Port index (zero based). */
+	size_t port;
+	/** Hub. */
+	hub_t *hub;
+};
+
+/** Fibril responsible for delayed port state change.
+ *
+ * @param arg Pointer to delay_port_state_change.
+ * @return Always EOK.
+ */
+static int set_port_state_delayed_fibril(void *arg)
+{
+	struct delay_port_state_change *change
+	    = (struct delay_port_state_change *) arg;
+
+	async_usleep(change->delay);
+
+	hub_acquire(change->hub);
+
+	hub_port_t *port = get_hub_port(change->hub, change->port);
+	assert(port != NULL);
+
+	if (port->state == change->old_state) {
+		hub_set_port_state(change->hub, change->port,
+		    change->new_state);
+	}
+
+	hub_release(change->hub);
+
+	free(change);
+
+	return EOK;
+}
+
+/** Change port state with a delay.
+ *
+ * @warning If the port state changes during the waiting phase, the state
+ * is not changed.
+ *
+ * @param hub Hub in question.
+ * @param port_index Port index (zero based).
+ * @param delay_time_ms Delay time in miliseconds.
+ * @param old_state Old (current) state of the port.
+ * @param new_state New state of the port.
+ */
+static void set_port_state_delayed(hub_t *hub, size_t port_index,
+    suseconds_t delay_time_ms,
+    hub_port_state_t old_state, hub_port_state_t new_state)
+{
+	struct delay_port_state_change *change
+	    = malloc(sizeof(struct delay_port_state_change));
+
+	change->hub = hub;
+	change->port = port_index;
+	change->delay = delay_time_ms * 1000;
+	change->old_state = old_state;
+	change->new_state = new_state;
+	fid_t fibril = fibril_create(set_port_state_delayed_fibril, change);
+	if (fibril == 0) {
+		printf("Failed to create fibril\n");
+		free(change);
+		return;
+	}
+	fibril_add_ready(fibril);
+}
+
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/hub.h
===================================================================
--- uspace/drv/bus/usb/vhc/hub/hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/hub/hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,120 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Representation of an USB hub.
+ */
+#ifndef VHC_HUB_HUB_H_
+#define VHC_HUB_HUB_H_
+
+#include <fibril_synch.h>
+
+#ifndef HUB_PORT_COUNT
+#define HUB_PORT_COUNT 2
+#endif
+#define BITS2BYTES(bits) (bits ? ((((bits)-1)>>3)+1) : 0)
+
+/** Hub port internal state.
+ * Some states (e.g. port over current) are not covered as they are not
+ * simulated at all.
+ */
+typedef enum {
+	HUB_PORT_STATE_UNKNOWN,
+	HUB_PORT_STATE_NOT_CONFIGURED,
+	HUB_PORT_STATE_POWERED_OFF,
+	HUB_PORT_STATE_DISCONNECTED,
+	HUB_PORT_STATE_DISABLED,
+	HUB_PORT_STATE_RESETTING,
+	HUB_PORT_STATE_ENABLED,
+	HUB_PORT_STATE_SUSPENDED,
+	HUB_PORT_STATE_RESUMING,
+	/* HUB_PORT_STATE_, */
+} hub_port_state_t;
+
+char hub_port_state_to_char(hub_port_state_t);
+
+/** Hub status change mask bits. */
+typedef enum {
+	HUB_STATUS_C_PORT_CONNECTION = (1 << 0),
+	HUB_STATUS_C_PORT_ENABLE = (1 << 1),
+	HUB_STATUS_C_PORT_SUSPEND = (1 << 2),
+	HUB_STATUS_C_PORT_OVER_CURRENT = (1 << 3),
+	HUB_STATUS_C_PORT_RESET = (1 << 4),
+	/* HUB_STATUS_C_ = (1 << ), */
+} hub_status_change_t;
+
+typedef struct hub hub_t;
+
+/** Hub port information. */
+typedef struct {
+	/** Custom pointer to connected device. */
+	void *connected_device;
+	/** Port index (one based). */
+	size_t index;
+	/** Port state. */
+	hub_port_state_t state;
+	/** Status change bitmap. */
+	uint16_t status_change;
+	/** Containing hub. */
+	hub_t *hub;
+} hub_port_t;
+
+/** Hub device type. */
+struct hub {
+	/** Hub ports. */
+	hub_port_t ports[HUB_PORT_COUNT];
+	/** Custom hub data. */
+	void *custom_data;
+	/** Access guard to the whole hub. */
+	fibril_mutex_t guard;
+	/** Last value of status change bitmap. */
+	bool signal_changes;
+};
+
+void hub_init(hub_t *);
+size_t hub_connect_device(hub_t *, void *);
+int hub_disconnect_device(hub_t *, void *);
+size_t hub_find_device(hub_t *, void *);
+void hub_acquire(hub_t *);
+void hub_release(hub_t *);
+void hub_set_port_state(hub_t *, size_t, hub_port_state_t);
+void hub_set_port_state_all(hub_t *, hub_port_state_t);
+hub_port_state_t hub_get_port_state(hub_t *, size_t);
+void hub_clear_port_status_change(hub_t *, size_t, hub_status_change_t);
+uint16_t hub_get_port_status_change(hub_t *, size_t);
+uint32_t hub_get_port_status(hub_t *, size_t);
+uint8_t hub_get_status_change_bitmap(hub_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/virthub.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub/virthub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/hub/virthub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,260 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief
+ */
+#include <usb/classes/classes.h>
+#include <usbvirt/device.h>
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ddf/driver.h>
+
+#include "virthub.h"
+#include "hub.h"
+
+
+/** Standard device descriptor. */
+usb_standard_device_descriptor_t std_device_descriptor = {
+	.length = sizeof(usb_standard_device_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_DEVICE,
+	.usb_spec_version = 0x110,
+	.device_class = USB_CLASS_HUB,
+	.device_subclass = 0,
+	.device_protocol = 0,
+	.max_packet_size = 64,
+	.configuration_count = 1
+};
+
+/** Standard interface descriptor. */
+usb_standard_interface_descriptor_t std_interface_descriptor = {
+	.length = sizeof(usb_standard_interface_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_INTERFACE,
+	.interface_number = 0,
+	.alternate_setting = 0,
+	.endpoint_count = 1,
+	.interface_class = USB_CLASS_HUB,
+	.interface_subclass = 0,
+	.interface_protocol = 0,
+	.str_interface = 0
+};
+
+/** Hub descriptor. */
+hub_descriptor_t hub_descriptor = {
+	.length = sizeof(hub_descriptor_t),
+	.type = USB_DESCTYPE_HUB,
+	.port_count = HUB_PORT_COUNT,
+	.characteristics = 0, 
+	.power_on_warm_up = 50, /* Huh? */
+	.max_current = 100, /* Huh again. */
+	.removable_device = { 0 },
+	.port_power = { 0xFF }
+};
+
+/** Endpoint descriptor. */
+usb_standard_endpoint_descriptor_t endpoint_descriptor = {
+	.length = sizeof(usb_standard_endpoint_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_ENDPOINT,
+	.endpoint_address = HUB_STATUS_CHANGE_PIPE | 128,
+	.attributes = USB_TRANSFER_INTERRUPT,
+	.max_packet_size = 8,
+	.poll_interval = 0xFF
+};
+
+/** Standard configuration descriptor. */
+usb_standard_configuration_descriptor_t std_configuration_descriptor = {
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
+	.total_length = 
+		sizeof(usb_standard_configuration_descriptor_t)
+		+ sizeof(std_interface_descriptor)
+		+ sizeof(hub_descriptor)
+		+ sizeof(endpoint_descriptor)
+		,
+	.interface_count = 1,
+	.configuration_number = HUB_CONFIGURATION_ID,
+	.str_configuration = 0,
+	.attributes = 128, /* denotes bus-powered device */
+	.max_power = 50
+};
+
+/** All hub configuration descriptors. */
+static usbvirt_device_configuration_extras_t extra_descriptors[] = {
+	{
+		.data = (uint8_t *) &std_interface_descriptor,
+		.length = sizeof(std_interface_descriptor)
+	},
+	{
+		.data = (uint8_t *) &hub_descriptor,
+		.length = sizeof(hub_descriptor)
+	},
+	{
+		.data = (uint8_t *) &endpoint_descriptor,
+		.length = sizeof(endpoint_descriptor)
+	}
+};
+
+/** Hub configuration. */
+usbvirt_device_configuration_t configuration = {
+	.descriptor = &std_configuration_descriptor,
+	.extra = extra_descriptors,
+	.extra_count = sizeof(extra_descriptors)/sizeof(extra_descriptors[0])
+};
+
+/** Hub standard descriptors. */
+usbvirt_descriptors_t descriptors = {
+	.device = &std_device_descriptor,
+	.configuration = &configuration,
+	.configuration_count = 1,
+};
+
+/** Initializes virtual hub device.
+ *
+ * @param dev Virtual USB device backend.
+ * @return Error code.
+ */
+int virthub_init(usbvirt_device_t *dev)
+{
+	if (dev == NULL) {
+		return EBADMEM;
+	}
+	dev->ops = &hub_ops;
+	dev->descriptors = &descriptors;
+
+	hub_t *hub = malloc(sizeof(hub_t));
+	if (hub == NULL) {
+		return ENOMEM;
+	}
+
+	hub_init(hub);
+	dev->device_data = hub;
+
+	return EOK;
+}
+
+/** Connect a device to a virtual hub.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param conn Device to be connected.
+ * @return Port device was connected to.
+ */
+int virthub_connect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
+{
+	assert(dev != NULL);
+	assert(conn != NULL);
+
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+	size_t port = hub_connect_device(hub, conn);
+	hub_release(hub);
+
+	return port;
+}
+
+/** Disconnect a device from a virtual hub.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param conn Device to be disconnected.
+ * @return Error code.
+ */
+int virthub_disconnect_device(usbvirt_device_t *dev, vhc_virtdev_t *conn)
+{
+	assert(dev != NULL);
+	assert(conn != NULL);
+
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+	hub_disconnect_device(hub, conn);
+	hub_release(hub);
+
+	return EOK;
+}
+
+/** Whether trafic is propagated to given device.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param conn Connected device.
+ * @return Whether port is signalling to the device.
+ */
+bool virthub_is_device_enabled(usbvirt_device_t *dev, vhc_virtdev_t *conn)
+{
+	assert(dev != NULL);
+	assert(conn != NULL);
+
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+
+	hub_port_state_t state = HUB_PORT_STATE_UNKNOWN;
+	size_t port = hub_find_device(hub, conn);
+	if (port != (size_t) -1) {
+		state = hub_get_port_state(hub, port);
+	}
+	hub_release(hub);
+
+	return state == HUB_PORT_STATE_ENABLED;
+}
+
+/** Format status of a virtual hub.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param[out] status Hub status information.
+ * @param[in] len Size of the @p status buffer.
+ */
+void virthub_get_status(usbvirt_device_t *dev, char *status, size_t len)
+{
+	assert(dev != NULL);
+	if (len == 0) {
+		return;
+	}
+
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	char port_status[HUB_PORT_COUNT + 1];
+
+	size_t i;
+	for (i = 0; i < HUB_PORT_COUNT; i++) {
+		port_status[i] = hub_port_state_to_char(
+		    hub_get_port_state(hub, i));
+	}
+	port_status[HUB_PORT_COUNT] = 0;
+
+	snprintf(status, len, "vhub:%s", port_status);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/virthub.h
===================================================================
--- uspace/drv/bus/usb/vhc/hub/virthub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/hub/virthub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,90 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief USB hub as a virtual USB device.
+ */
+#ifndef VHC_HUB_VIRTHUB_H_
+#define VHC_HUB_VIRTHUB_H_
+
+#include <usbvirt/device.h>
+#include "hub.h"
+
+#ifdef STANDALONE_HUB
+#define virtdev_connection_t int
+#else
+#include "../vhcd.h"
+#endif
+
+/** Endpoint number for status change pipe. */
+#define HUB_STATUS_CHANGE_PIPE 1
+/** Configuration value for hub configuration. */
+#define HUB_CONFIGURATION_ID 1
+
+
+/** Hub descriptor.
+ */
+typedef struct {
+	/** Size of this descriptor in bytes. */
+	uint8_t length;
+	/** Descriptor type (USB_DESCTYPE_HUB). */
+	uint8_t type;
+	/** Number of downstream ports. */
+	uint8_t port_count;
+	/** Hub characteristics. */
+	uint16_t characteristics;
+	/** Time from power-on to stabilized current.
+	 * Expressed in 2ms unit.
+	 */
+	uint8_t power_on_warm_up;
+	/** Maximum current (in mA). */
+	uint8_t max_current;
+	/** Whether device at given port is removable. */
+	uint8_t removable_device[BITS2BYTES(HUB_PORT_COUNT+1)];
+	/** Port power control.
+	 * This is USB1.0 compatibility field, all bits must be 1.
+	 */
+	uint8_t port_power[BITS2BYTES(HUB_PORT_COUNT+1)];
+} __attribute__ ((packed)) hub_descriptor_t;
+
+extern usbvirt_device_ops_t hub_ops;
+extern hub_descriptor_t hub_descriptor;
+
+int virthub_init(usbvirt_device_t *);
+int virthub_connect_device(usbvirt_device_t *, vhc_virtdev_t *);
+int virthub_disconnect_device(usbvirt_device_t *, vhc_virtdev_t *);
+bool virthub_is_device_enabled(usbvirt_device_t *, vhc_virtdev_t *);
+void virthub_get_status(usbvirt_device_t *, char *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/hub/virthubops.c
===================================================================
--- uspace/drv/bus/usb/vhc/hub/virthubops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/hub/virthubops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,457 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Virtual USB hub operations.
+ */
+#include <errno.h>
+#include <usb/classes/hub.h>
+#include <usbvirt/device.h>
+#include "virthub.h"
+#include "hub.h"
+
+/** Callback when device changes states. */
+static void on_state_change(usbvirt_device_t *dev,
+    usbvirt_device_state_t old_state, usbvirt_device_state_t new_state)
+{
+	hub_t *hub = (hub_t *)dev->device_data;
+
+	hub_acquire(hub);
+
+	switch (new_state) {
+		case USBVIRT_STATE_CONFIGURED:
+			hub_set_port_state_all(hub, HUB_PORT_STATE_POWERED_OFF);
+			break;
+		case USBVIRT_STATE_ADDRESS:
+			hub_set_port_state_all(hub, HUB_PORT_STATE_NOT_CONFIGURED);
+			break;
+		default:
+			break;
+	}
+
+	hub_release(hub);
+}
+
+/** Callback for data request. */
+static int req_on_status_change_pipe(usbvirt_device_t *dev,
+    usb_endpoint_t endpoint, usb_transfer_type_t tr_type,
+    void *buffer, size_t buffer_size, size_t *actual_size)
+{
+	if (endpoint != HUB_STATUS_CHANGE_PIPE) {
+		return ESTALL;
+	}
+	if (tr_type != USB_TRANSFER_INTERRUPT) {
+		return ESTALL;
+	}
+	
+	hub_t *hub = dev->device_data;
+
+	hub_acquire(hub);
+
+	if (!hub->signal_changes) {
+		hub_release(hub);
+
+		return ENAK;
+	}
+
+
+	uint8_t change_map = hub_get_status_change_bitmap(hub);
+
+	uint8_t *b = (uint8_t *) buffer;
+	if (buffer_size > 0) {
+		*b = change_map;
+		*actual_size = 1;
+	} else {
+		*actual_size = 0;
+	}
+	
+	hub->signal_changes = false;
+
+	hub_release(hub);
+
+	return EOK;
+}
+
+/** Handle ClearHubFeature request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_clear_hub_feature(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	return ENOTSUP;
+}
+
+/** Handle ClearPortFeature request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_clear_port_feature(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	int rc;
+	size_t port = request->index - 1;
+	usb_hub_class_feature_t feature = request->value;
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+
+	hub_port_state_t port_state = hub_get_port_state(hub, port);
+
+	switch (feature) {
+		case USB_HUB_FEATURE_PORT_ENABLE:
+			if ((port_state != HUB_PORT_STATE_NOT_CONFIGURED)
+			    && (port_state != HUB_PORT_STATE_POWERED_OFF)) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_DISABLED);
+			}
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_PORT_SUSPEND:
+			if (port_state != HUB_PORT_STATE_SUSPENDED) {
+				rc = EOK;
+				break;
+			}
+			hub_set_port_state(hub, port, HUB_PORT_STATE_RESUMING);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_PORT_POWER:
+			if (port_state != HUB_PORT_STATE_NOT_CONFIGURED) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_POWERED_OFF);
+			}
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_CONNECTION:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_CONNECTION);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_ENABLE:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_ENABLE);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_SUSPEND:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_SUSPEND);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_OVER_CURRENT:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_OVER_CURRENT);
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_C_PORT_RESET:
+			hub_clear_port_status_change(hub, port, HUB_STATUS_C_PORT_RESET);
+			rc = EOK;
+			break;
+
+		default:
+			rc = ENOTSUP;
+			break;
+	}
+
+	hub_release(hub);
+
+	return rc;
+}
+
+/** Handle GetBusState request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_get_bus_state(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	return ENOTSUP;
+}
+
+/** Handle GetDescriptor request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_get_descriptor(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	if (request->value_high == USB_DESCTYPE_HUB) {
+		usbvirt_control_reply_helper(request, data, act_size,
+		    &hub_descriptor, hub_descriptor.length);
+
+		return EOK;
+	}
+	/* Let the framework handle all the rest. */
+	return EFORWARD;
+}
+
+/** Handle GetHubStatus request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_get_hub_status(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	uint32_t hub_status = 0;
+
+	usbvirt_control_reply_helper(request, data, act_size,
+	    &hub_status, sizeof(hub_status));
+
+	return EOK;
+}
+
+/** Handle GetPortStatus request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_get_port_status(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+
+	uint32_t status = hub_get_port_status(hub, request->index - 1);
+
+	hub_release(hub);
+
+	usbvirt_control_reply_helper(request, data, act_size,
+	    &status, sizeof(status));
+
+	return EOK;
+}
+
+/** Handle SetHubFeature request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_set_hub_feature(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	return ENOTSUP;
+}
+
+/** Handle SetPortFeature request.
+ *
+ * @param dev Virtual device representing the hub.
+ * @param request The SETUP packet of the control request.
+ * @param data Extra data (when DATA stage present).
+ * @return Error code.
+ */
+static int req_set_port_feature(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *request, uint8_t *data,
+    size_t *act_size)
+{
+	int rc;
+	size_t port = request->index - 1;
+	usb_hub_class_feature_t feature = request->value;
+	hub_t *hub = (hub_t *) dev->device_data;
+
+	hub_acquire(hub);
+
+	hub_port_state_t port_state = hub_get_port_state(hub, port);
+
+	switch (feature) {
+		case USB_HUB_FEATURE_PORT_RESET:
+			if (port_state != HUB_PORT_STATE_POWERED_OFF) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_RESETTING);
+			}
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_PORT_SUSPEND:
+			if (port_state == HUB_PORT_STATE_ENABLED) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_SUSPENDED);
+			}
+			rc = EOK;
+			break;
+
+		case USB_HUB_FEATURE_PORT_POWER:
+			if (port_state == HUB_PORT_STATE_POWERED_OFF) {
+				hub_set_port_state(hub, port, HUB_PORT_STATE_DISCONNECTED);
+			}
+			rc = EOK;
+			break;
+
+		default:
+			break;
+	}
+
+	hub_release(hub);
+
+	return rc;
+}
+
+
+/** IN class request. */
+#define CLASS_REQ_IN(recipient) \
+	USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_IN, \
+	USBVIRT_REQUEST_TYPE_CLASS, recipient)
+/** OUT class request. */
+#define CLASS_REQ_OUT(recipient) \
+	USBVIRT_MAKE_CONTROL_REQUEST_TYPE(USB_DIRECTION_OUT, \
+	USBVIRT_REQUEST_TYPE_CLASS, recipient)
+
+/** Recipient: other. */
+#define REC_OTHER USB_REQUEST_RECIPIENT_OTHER
+/** Recipient: device. */
+#define REC_DEVICE USB_REQUEST_RECIPIENT_DEVICE
+/** Direction: in. */
+#define DIR_IN USB_DIRECTION_IN
+/** Direction: out. */
+#define DIR_OUT USB_DIRECTION_OUT
+
+
+/** Create a class request.
+ *
+ * @param direction Request direction.
+ * @param recipient Request recipient.
+ * @param req Request code.
+ */
+#define CLASS_REQ(direction, recipient, req) \
+	.req_direction = direction, \
+	.req_recipient = recipient, \
+	.req_type = USB_REQUEST_TYPE_CLASS, \
+	.request = req
+
+/** Create a standard request.
+ *
+ * @param direction Request direction.
+ * @param recipient Request recipient.
+ * @param req Request code.
+ */
+#define STD_REQ(direction, recipient, req) \
+	.req_direction = direction, \
+	.req_recipient = recipient, \
+	.req_type = USB_REQUEST_TYPE_STANDARD, \
+	.request = req
+
+/** Hub operations on control endpoint zero. */
+static usbvirt_control_request_handler_t endpoint_zero_handlers[] = {
+	{
+		STD_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
+		.name = "GetDescriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_DEVICE, USB_DEVREQ_GET_DESCRIPTOR),
+		.name = "GetDescriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
+		.name = "GetPortStatus",
+		.callback = req_get_port_status
+	},
+	{
+		CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_CLEAR_FEATURE),
+		.name = "ClearHubFeature",
+		.callback = req_clear_hub_feature
+	},
+	{
+		CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_CLEAR_FEATURE),
+		.name = "ClearPortFeature",
+		.callback = req_clear_port_feature
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATE),
+		.name = "GetBusState",
+		.callback = req_get_bus_state
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_DESCRIPTOR),
+		.name = "GetHubDescriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_DEVICE, USB_HUB_REQUEST_GET_STATUS),
+		.name = "GetHubStatus",
+		.callback = req_get_hub_status
+	},
+	{
+		CLASS_REQ(DIR_IN, REC_OTHER, USB_HUB_REQUEST_GET_STATUS),
+		.name = "GetPortStatus",
+		.callback = req_get_port_status
+	},
+	{
+		CLASS_REQ(DIR_OUT, REC_DEVICE, USB_HUB_REQUEST_SET_FEATURE),
+		.name = "SetHubFeature",
+		.callback = req_set_hub_feature
+	},
+	{
+		CLASS_REQ(DIR_OUT, REC_OTHER, USB_HUB_REQUEST_SET_FEATURE),
+		.name = "SetPortFeature",
+		.callback = req_set_port_feature
+	},
+	{
+		.callback = NULL
+	}
+};
+
+
+/** Hub operations. */
+usbvirt_device_ops_t hub_ops = {
+	.control = endpoint_zero_handlers,
+	.data_in[HUB_STATUS_CHANGE_PIPE] = req_on_status_change_pipe,
+	.state_changed = on_state_change,
+};
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/main.c
===================================================================
--- uspace/drv/bus/usb/vhc/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2011 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * Virtual host controller.
+ */
+
+#include <loc.h>
+#include <async.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+
+#include <usb/usb.h>
+#include <usb/ddfiface.h>
+#include <usb_iface.h>
+#include "vhcd.h"
+#include "hub.h"
+#include "conn.h"
+
+static ddf_dev_ops_t vhc_ops = {
+	.interfaces[USBHC_DEV_IFACE] = &vhc_iface,
+	.interfaces[USB_DEV_IFACE] = &vhc_usb_iface,
+	.close = on_client_close,
+	.default_handler = default_connection_handler
+};
+
+static int vhc_add_device(ddf_dev_t *dev)
+{
+	static int vhc_count = 0;
+	int rc;
+
+	if (vhc_count > 0) {
+		return ELIMIT;
+	}
+
+	vhc_data_t *data = malloc(sizeof(vhc_data_t));
+	if (data == NULL) {
+		usb_log_fatal("Failed to allocate memory.\n");
+		return ENOMEM;
+	}
+	data->magic = 0xDEADBEEF;
+	rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to initialize endpoint manager.\n");
+		free(data);
+		return rc;
+	}
+	usb_device_keeper_init(&data->dev_keeper);
+
+	ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc");
+	if (hc == NULL) {
+		usb_log_fatal("Failed to create device function.\n");
+		free(data);
+		return ENOMEM;
+	}
+
+	hc->ops = &vhc_ops;
+	list_initialize(&data->devices);
+	fibril_mutex_initialize(&data->guard);
+	data->hub = &virtual_hub_device;
+	data->hc_fun = hc;
+
+	dev->driver_data = data;
+
+	rc = ddf_fun_bind(hc);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to bind HC function: %s.\n",
+		    str_error(rc));
+		free(data);
+		return rc;
+	}
+
+	rc = ddf_fun_add_to_category(hc, USB_HC_CATEGORY);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to add function to HC class: %s.\n",
+		    str_error(rc));
+		free(data);
+		return rc;
+	}
+
+	virtual_hub_device_init(hc);
+
+	usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n",
+	    (size_t) dev->handle, (size_t) hc->handle);
+
+
+
+	rc = vhc_virtdev_plug_hub(data, data->hub, NULL);
+	if (rc != EOK) {
+		usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc));
+		free(data);
+		return rc;
+	}
+
+	return EOK;
+}
+
+static driver_ops_t vhc_driver_ops = {
+	.add_device = vhc_add_device,
+};
+
+static driver_t vhc_driver = {
+	.name = NAME,
+	.driver_ops = &vhc_driver_ops
+};
+
+
+int main(int argc, char * argv[])
+{	
+	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
+
+	printf(NAME ": virtual USB host controller driver.\n");
+
+	return ddf_driver_main(&vhc_driver);
+}
+
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/vhc/transfer.c
===================================================================
--- uspace/drv/bus/usb/vhc/transfer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/transfer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+#include <errno.h>
+#include <str_error.h>
+#include <usbvirt/device.h>
+#include <usbvirt/ipc.h>
+#include "vhcd.h"
+
+vhc_transfer_t *vhc_transfer_create(usb_address_t address, usb_endpoint_t ep,
+    usb_direction_t dir, usb_transfer_type_t tr_type,
+    ddf_fun_t *fun, void *callback_arg)
+{
+	vhc_transfer_t *result = malloc(sizeof(vhc_transfer_t));
+	if (result == NULL) {
+		return NULL;
+	}
+	link_initialize(&result->link);
+	result->address = address;
+	result->endpoint = ep;
+	result->direction = dir;
+	result->transfer_type = tr_type;
+	result->setup_buffer = NULL;
+	result->setup_buffer_size = 0;
+	result->data_buffer = NULL;
+	result->data_buffer_size = 0;
+	result->ddf_fun = fun;
+	result->callback_arg = callback_arg;
+	result->callback_in = NULL;
+	result->callback_out = NULL;
+
+	usb_log_debug2("Created transfer %p (%d.%d %s %s)\n", result,
+	    address, ep, usb_str_transfer_type_short(tr_type),
+	    dir == USB_DIRECTION_IN ? "in" : "out");
+
+	return result;
+}
+
+static bool is_set_address_transfer(vhc_transfer_t *transfer)
+{
+	if (transfer->endpoint != 0) {
+		return false;
+	}
+	if (transfer->transfer_type != USB_TRANSFER_CONTROL) {
+		return false;
+	}
+	if (transfer->direction != USB_DIRECTION_OUT) {
+		return false;
+	}
+	if (transfer->setup_buffer_size != sizeof(usb_device_request_setup_packet_t)) {
+		return false;
+	}
+	usb_device_request_setup_packet_t *setup = transfer->setup_buffer;
+	if (setup->request_type != 0) {
+		return false;
+	}
+	if (setup->request != USB_DEVREQ_SET_ADDRESS) {
+		return false;
+	}
+
+	return true;
+}
+
+int vhc_virtdev_add_transfer(vhc_data_t *vhc, vhc_transfer_t *transfer)
+{
+	fibril_mutex_lock(&vhc->guard);
+
+	bool target_found = false;
+	list_foreach(vhc->devices, pos) {
+		vhc_virtdev_t *dev = list_get_instance(pos, vhc_virtdev_t, link);
+		fibril_mutex_lock(&dev->guard);
+		if (dev->address == transfer->address) {
+			if (target_found) {
+				usb_log_warning("Transfer would be accepted by more devices!\n");
+				goto next;
+			}
+			target_found = true;
+			list_append(&transfer->link, &dev->transfer_queue);
+		}
+next:
+		fibril_mutex_unlock(&dev->guard);
+	}
+
+	fibril_mutex_unlock(&vhc->guard);
+
+	if (target_found) {
+		return EOK;
+	} else {
+		return ENOENT;
+	}
+}
+
+static int process_transfer_local(vhc_transfer_t *transfer,
+    usbvirt_device_t *dev, size_t *actual_data_size)
+{
+	int rc;
+
+	if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
+		if (transfer->direction == USB_DIRECTION_IN) {
+			rc = usbvirt_control_read(dev,
+			    transfer->setup_buffer, transfer->setup_buffer_size,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    actual_data_size);
+		} else {
+			assert(transfer->direction == USB_DIRECTION_OUT);
+			rc = usbvirt_control_write(dev,
+			    transfer->setup_buffer, transfer->setup_buffer_size,
+			    transfer->data_buffer, transfer->data_buffer_size);
+		}
+	} else {
+		if (transfer->direction == USB_DIRECTION_IN) {
+			rc = usbvirt_data_in(dev, transfer->transfer_type,
+			    transfer->endpoint,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    actual_data_size);
+		} else {
+			assert(transfer->direction == USB_DIRECTION_OUT);
+			rc = usbvirt_data_out(dev, transfer->transfer_type,
+			    transfer->endpoint,
+			    transfer->data_buffer, transfer->data_buffer_size);
+		}
+	}
+
+	return rc;
+}
+
+static int process_transfer_remote(vhc_transfer_t *transfer,
+    async_sess_t *sess, size_t *actual_data_size)
+{
+	int rc;
+
+	if (transfer->transfer_type == USB_TRANSFER_CONTROL) {
+		if (transfer->direction == USB_DIRECTION_IN) {
+			rc = usbvirt_ipc_send_control_read(sess,
+			    transfer->setup_buffer, transfer->setup_buffer_size,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    actual_data_size);
+		} else {
+			assert(transfer->direction == USB_DIRECTION_OUT);
+			rc = usbvirt_ipc_send_control_write(sess,
+			    transfer->setup_buffer, transfer->setup_buffer_size,
+			    transfer->data_buffer, transfer->data_buffer_size);
+		}
+	} else {
+		if (transfer->direction == USB_DIRECTION_IN) {
+			rc = usbvirt_ipc_send_data_in(sess, transfer->endpoint,
+			    transfer->transfer_type,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    actual_data_size);
+		} else {
+			assert(transfer->direction == USB_DIRECTION_OUT);
+			rc = usbvirt_ipc_send_data_out(sess, transfer->endpoint,
+			    transfer->transfer_type,
+			    transfer->data_buffer, transfer->data_buffer_size);
+		}
+	}
+
+	return rc;
+}
+
+static vhc_transfer_t *dequeue_first_transfer(vhc_virtdev_t *dev)
+{
+	assert(fibril_mutex_is_locked(&dev->guard));
+	assert(!list_empty(&dev->transfer_queue));
+
+	vhc_transfer_t *transfer = list_get_instance(
+	    list_first(&dev->transfer_queue), vhc_transfer_t, link);
+	list_remove(&transfer->link);
+
+	return transfer;
+}
+
+
+static void execute_transfer_callback_and_free(vhc_transfer_t *transfer,
+    size_t data_transfer_size, int outcome)
+{
+	assert(outcome != ENAK);
+
+	usb_log_debug2("Transfer %p ended: %s.\n",
+	    transfer, str_error(outcome));
+
+	if (transfer->direction == USB_DIRECTION_IN) {
+		transfer->callback_in(transfer->ddf_fun, outcome,
+		    data_transfer_size, transfer->callback_arg);
+	} else {
+		assert(transfer->direction == USB_DIRECTION_OUT);
+		transfer->callback_out(transfer->ddf_fun, outcome,
+		    transfer->callback_arg);
+	}
+
+	free(transfer);
+}
+
+int vhc_transfer_queue_processor(void *arg)
+{
+	vhc_virtdev_t *dev = arg;
+	fibril_mutex_lock(&dev->guard);
+	while (dev->plugged) {
+		if (list_empty(&dev->transfer_queue)) {
+			fibril_mutex_unlock(&dev->guard);
+			async_usleep(10 * 1000);
+			fibril_mutex_lock(&dev->guard);
+			continue;
+		}
+
+		vhc_transfer_t *transfer = dequeue_first_transfer(dev);
+		fibril_mutex_unlock(&dev->guard);
+
+		int rc = EOK;
+		size_t data_transfer_size = 0;
+		if (dev->dev_sess) {
+			rc = process_transfer_remote(transfer, dev->dev_sess,
+			    &data_transfer_size);
+		} else if (dev->dev_local != NULL) {
+			rc = process_transfer_local(transfer, dev->dev_local,
+			    &data_transfer_size);
+		} else {
+			usb_log_warning("Device has no remote phone nor local node.\n");
+			rc = ESTALL;
+		}
+
+		usb_log_debug2("Transfer %p processed: %s.\n",
+		    transfer, str_error(rc));
+
+		fibril_mutex_lock(&dev->guard);
+		if (rc == EOK) {
+			if (is_set_address_transfer(transfer)) {
+				usb_device_request_setup_packet_t *setup
+				    = transfer->setup_buffer;
+				dev->address = setup->value;
+				usb_log_debug2("Address changed to %d\n",
+				    dev->address);
+			}
+		}
+		if (rc == ENAK) {
+			// FIXME: this will work only because we do
+			// not NAK control transfers but this is generally
+			// a VERY bad idea indeed
+			list_append(&transfer->link, &dev->transfer_queue);
+		}
+		fibril_mutex_unlock(&dev->guard);
+
+		if (rc != ENAK) {
+			execute_transfer_callback_and_free(transfer,
+			    data_transfer_size, rc);
+		}
+
+		async_usleep(1000 * 100);
+		fibril_mutex_lock(&dev->guard);
+	}
+
+	/* Immediately fail all remaining transfers. */
+	while (!list_empty(&dev->transfer_queue)) {
+		vhc_transfer_t *transfer = dequeue_first_transfer(dev);
+		execute_transfer_callback_and_free(transfer, 0, EBADCHECKSUM);
+	}
+
+	fibril_mutex_unlock(&dev->guard);
+
+	return EOK;
+}
+
Index: uspace/drv/bus/usb/vhc/vhc.ma
===================================================================
--- uspace/drv/bus/usb/vhc/vhc.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/vhc.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,2 @@
+10 usb&hc=vhc
+
Index: uspace/drv/bus/usb/vhc/vhcd.h
===================================================================
--- uspace/drv/bus/usb/vhc/vhcd.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/bus/usb/vhc/vhcd.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,97 @@
+/*
+ * 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 drvusbvhc
+ * @{
+ */
+/** @file
+ * @brief Virtual USB host controller common definitions.
+ */
+#ifndef VHCD_VHCD_H_
+#define VHCD_VHCD_H_
+
+#include <usb/debug.h>
+#include <usbvirt/device.h>
+#include <usb/host/usb_endpoint_manager.h>
+#include <usb/host/device_keeper.h>
+#include <usbhc_iface.h>
+#include <async.h>
+
+#define NAME "vhc"
+
+typedef struct {
+	link_t link;
+	async_sess_t *dev_sess;
+	usbvirt_device_t *dev_local;
+	bool plugged;
+	usb_address_t address;
+	fibril_mutex_t guard;
+	list_t transfer_queue;
+} vhc_virtdev_t;
+
+typedef struct {
+	uint32_t magic;
+	list_t devices;
+	fibril_mutex_t guard;
+	usb_endpoint_manager_t ep_manager;
+	usb_device_keeper_t dev_keeper;
+	usbvirt_device_t *hub;
+	ddf_fun_t *hc_fun;
+} vhc_data_t;
+
+typedef struct {
+	link_t link;
+	usb_address_t address;
+	usb_endpoint_t endpoint;
+	usb_direction_t direction;
+	usb_transfer_type_t transfer_type;
+	void *setup_buffer;
+	size_t setup_buffer_size;
+	void *data_buffer;
+	size_t data_buffer_size;
+	ddf_fun_t *ddf_fun;
+	void *callback_arg;
+	usbhc_iface_transfer_in_callback_t callback_in;
+	usbhc_iface_transfer_out_callback_t callback_out;
+} vhc_transfer_t;
+
+vhc_transfer_t *vhc_transfer_create(usb_address_t, usb_endpoint_t,
+    usb_direction_t, usb_transfer_type_t, ddf_fun_t *, void *);
+int vhc_virtdev_plug(vhc_data_t *, async_sess_t *, uintptr_t *);
+int vhc_virtdev_plug_local(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
+int vhc_virtdev_plug_hub(vhc_data_t *, usbvirt_device_t *, uintptr_t *);
+void vhc_virtdev_unplug(vhc_data_t *, uintptr_t);
+int vhc_virtdev_add_transfer(vhc_data_t *, vhc_transfer_t *);
+
+int vhc_transfer_queue_processor(void *arg);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/char/ns8250/Makefile
===================================================================
--- uspace/drv/char/ns8250/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/char/ns8250/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = ns8250
+
+SOURCES = \
+	ns8250.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/char/ns8250/cyclic_buffer.h
===================================================================
--- uspace/drv/char/ns8250/cyclic_buffer.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/char/ns8250/cyclic_buffer.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,83 @@
+/*
+ * 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 ns8250
+ * @{
+ */
+/** @file
+ */
+
+#ifndef CYCLIC_BUFFER_H_
+#define CYCLIC_BUFFER_H_
+
+#define BUF_LEN 256
+
+typedef struct cyclic_buffer {
+	uint8_t buf[BUF_LEN];
+	int start;
+	int cnt;
+}  cyclic_buffer_t;
+
+/*
+ * @return		False if the buffer is full.
+ */
+static inline bool buf_push_back(cyclic_buffer_t *buf, uint8_t item)
+{
+	if (buf->cnt >= BUF_LEN)
+		return false;
+	int pos = (buf->start + buf->cnt) % BUF_LEN;
+	buf->buf[pos] = item;
+	buf->cnt++;
+	return true;
+}
+
+static inline bool buf_is_empty(cyclic_buffer_t *buf)
+{
+	return buf->cnt == 0;
+}
+
+static inline uint8_t buf_pop_front(cyclic_buffer_t *buf)
+{
+	assert(!buf_is_empty(buf));
+	
+	uint8_t res = buf->buf[buf->start];
+	buf->start = (buf->start + 1) % BUF_LEN;
+	buf->cnt--;
+	return res;
+}
+
+static inline void buf_clear(cyclic_buffer_t *buf)
+{
+	buf->cnt = 0;
+}
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/drv/char/ns8250/ns8250.c
===================================================================
--- uspace/drv/char/ns8250/ns8250.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/char/ns8250/ns8250.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,963 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup ns8250 Serial port driver.
+ * @brief HelenOS serial port driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+#include <malloc.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+
+#include <ddf/driver.h>
+#include <ddf/interrupt.h>
+#include <ddf/log.h>
+#include <ops/char_dev.h>
+
+#include <devman.h>
+#include <ipc/devman.h>
+#include <device/hw_res.h>
+#include <ipc/serial_ctl.h>
+
+#include "cyclic_buffer.h"
+
+#define NAME "ns8250"
+
+#define REG_COUNT 7
+#define MAX_BAUD_RATE 115200
+#define DLAB_MASK (1 << 7)
+
+/** Obtain soft-state structure from function node */
+#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
+
+/** Obtain soft-state structure from device node */
+#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
+
+/** The number of bits of one data unit send by the serial port. */
+typedef enum {
+	WORD_LENGTH_5,
+	WORD_LENGTH_6,
+	WORD_LENGTH_7,
+	WORD_LENGTH_8
+} word_length_t;
+
+/** The number of stop bits used by the serial port. */
+typedef enum {
+	/** Use one stop bit. */
+	ONE_STOP_BIT,
+	/** 1.5 stop bits for word length 5, 2 stop bits otherwise. */
+	TWO_STOP_BITS
+} stop_bit_t;
+
+/** The driver data for the serial port devices. */
+typedef struct ns8250 {
+	/** DDF device node */
+	ddf_dev_t *dev;
+	/** DDF function node */
+	ddf_fun_t *fun;
+	/** Is there any client conntected to the device? */
+	bool client_connected;
+	/** The irq assigned to this device. */
+	int irq;
+	/** The base i/o address of the devices registers. */
+	uint32_t io_addr;
+	/** The i/o port used to access the serial ports registers. */
+	ioport8_t *port;
+	/** The buffer for incomming data. */
+	cyclic_buffer_t input_buffer;
+	/** The fibril mutex for synchronizing the access to the device. */
+	fibril_mutex_t mutex;
+} ns8250_t;
+
+/** Create per-device soft-state structure.
+ *
+ * @return	Pointer to soft-state structure.
+ */
+static ns8250_t *ns8250_new(void)
+{
+	ns8250_t *ns;
+	
+	ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));
+	if (ns == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&ns->mutex);
+	return ns;
+}
+
+/** Delete soft-state structure.
+ *
+ * @param ns	The driver data structure.
+ */
+static void ns8250_delete(ns8250_t *ns)
+{
+	assert(ns != NULL);
+	free(ns);
+}
+
+/** Find out if there is some incomming data available on the serial port.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @return		True if there are data waiting to be read, false
+ *			otherwise.
+ */
+static bool ns8250_received(ioport8_t *port)
+{
+	return (pio_read_8(port + 5) & 1) != 0;
+}
+
+/** Read one byte from the serial port.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @return		The data read.
+ */
+static uint8_t ns8250_read_8(ioport8_t *port)
+{
+	return pio_read_8(port);
+}
+
+/** Find out wheter it is possible to send data.
+ *
+ * @param port		The base address of the serial port device's ports.
+ */
+static bool is_transmit_empty(ioport8_t *port)
+{
+	return (pio_read_8(port + 5) & 0x20) != 0;
+}
+
+/** Write one character on the serial port.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @param c		The character to be written to the serial port device.
+ */
+static void ns8250_write_8(ioport8_t *port, uint8_t c)
+{
+	while (!is_transmit_empty(port))
+		;
+	
+	pio_write_8(port, c);
+}
+
+/** Read data from the serial port device.
+ *
+ * @param fun		The serial port function
+ * @param buf		The ouput buffer for read data.
+ * @param count		The number of bytes to be read.
+ *
+ * @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 = NS8250(fun);
+	int ret = EOK;
+	
+	fibril_mutex_lock(&ns->mutex);
+	while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
+		buf[ret] = (char)buf_pop_front(&ns->input_buffer);
+		ret++;
+	}
+	fibril_mutex_unlock(&ns->mutex);
+	
+	return ret;
+}
+
+/** Write a character to the serial port.
+ *
+ * @param ns		Serial port device
+ * @param c		The character to be written
+ */
+static inline void ns8250_putchar(ns8250_t *ns, uint8_t c)
+{
+	fibril_mutex_lock(&ns->mutex);
+	ns8250_write_8(ns->port, c);
+	fibril_mutex_unlock(&ns->mutex);
+}
+
+/** Write data to the serial port.
+ *
+ * @param fun		The serial port function
+ * @param buf		The data to be written
+ * @param count		The number of bytes to be written
+ * @return		Zero on success
+ */
+static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
+{
+	ns8250_t *ns = NS8250(fun);
+	size_t idx;
+	
+	for (idx = 0; idx < count; idx++)
+		ns8250_putchar(ns, (uint8_t) buf[idx]);
+	
+	return 0;
+}
+
+static ddf_dev_ops_t ns8250_dev_ops;
+
+/** The character interface's callbacks. */
+static char_dev_ops_t ns8250_char_dev_ops = {
+	.read = &ns8250_read,
+	.write = &ns8250_write
+};
+
+static int ns8250_add_device(ddf_dev_t *dev);
+
+/** The serial port device driver's standard operations. */
+static driver_ops_t ns8250_ops = {
+	.add_device = &ns8250_add_device
+};
+
+/** The serial port device driver structure. */
+static driver_t ns8250_driver = {
+	.name = NAME,
+	.driver_ops = &ns8250_ops
+};
+
+/** Clean up the serial port soft-state
+ *
+ * @param ns		Serial port device
+ */
+static void ns8250_dev_cleanup(ns8250_t *ns)
+{
+	if (ns->dev->parent_sess) {
+		async_hangup(ns->dev->parent_sess);
+		ns->dev->parent_sess = NULL;
+	}
+}
+
+/** Enable the i/o ports of the device.
+ *
+ * @param ns		Serial port device
+ * @return		True on success, false otherwise
+ */
+static bool ns8250_pio_enable(ns8250_t *ns)
+{
+	ddf_msg(LVL_DEBUG, "ns8250_pio_enable %s", ns->dev->name);
+	
+	/* Gain control over port's registers. */
+	if (pio_enable((void *)(uintptr_t) ns->io_addr, REG_COUNT,
+	    (void **) &ns->port)) {
+		ddf_msg(LVL_ERROR, "Cannot map the port %#" PRIx32
+		    " for device %s.", ns->io_addr, ns->dev->name);
+		return false;
+	}
+	
+	return true;
+}
+
+/** Probe the serial port device for its presence.
+ *
+ * @param ns		Serial port device
+ * @return		True if the device is present, false otherwise
+ */
+static bool ns8250_dev_probe(ns8250_t *ns)
+{
+	ddf_msg(LVL_DEBUG, "ns8250_dev_probe %s", ns->dev->name);
+	
+	ioport8_t *port_addr = ns->port;
+	bool res = true;
+	uint8_t olddata;
+	
+	olddata = pio_read_8(port_addr + 4);
+	
+	pio_write_8(port_addr + 4, 0x10);
+	if (pio_read_8(port_addr + 6) & 0xf0)
+		res = false;
+	
+	pio_write_8(port_addr + 4, 0x1f);
+	if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0)
+		res = false;
+	
+	pio_write_8(port_addr + 4, olddata);
+	
+	if (!res) {
+		ddf_msg(LVL_DEBUG, "Device %s is not present.",
+		    ns->dev->name);
+	}
+	
+	return res;
+}
+
+/** Initialize serial port device.
+ *
+ * @param ns		Serial port device
+ * @return		Zero on success, negative error number otherwise
+ */
+static int ns8250_dev_initialize(ns8250_t *ns)
+{
+	ddf_msg(LVL_DEBUG, "ns8250_dev_initialize %s", ns->dev->name);
+	
+	int ret = EOK;
+	
+	hw_resource_list_t hw_resources;
+	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
+	
+	/* Connect to the parent's driver. */
+	ns->dev->parent_sess = devman_parent_device_connect(EXCHANGE_SERIALIZE,
+	    ns->dev->handle, IPC_FLAG_BLOCKING);
+	if (!ns->dev->parent_sess) {
+		ddf_msg(LVL_ERROR, "Failed to connect to parent driver of "
+		    "device %s.", ns->dev->name);
+		ret = ENOENT;
+		goto failed;
+	}
+	
+	/* Get hw resources. */
+	ret = hw_res_get_resource_list(ns->dev->parent_sess, &hw_resources);
+	if (ret != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to get HW resources for device "
+		    "%s.", ns->dev->name);
+		goto failed;
+	}
+	
+	size_t i;
+	hw_resource_t *res;
+	bool irq = false;
+	bool ioport = false;
+	
+	for (i = 0; i < hw_resources.count; i++) {
+		res = &hw_resources.resources[i];
+		switch (res->type) {
+		case INTERRUPT:
+			ns->irq = res->res.interrupt.irq;
+			irq = true;
+			ddf_msg(LVL_NOTE, "Device %s was asigned irq = 0x%x.",
+			    ns->dev->name, ns->irq);
+			break;
+			
+		case IO_RANGE:
+			ns->io_addr = res->res.io_range.address;
+			if (res->res.io_range.size < REG_COUNT) {
+				ddf_msg(LVL_ERROR, "I/O range assigned to "
+				    "device %s is too small.", ns->dev->name);
+				ret = ELIMIT;
+				goto failed;
+			}
+			ioport = true;
+			ddf_msg(LVL_NOTE, "Device %s was asigned I/O address = "
+			    "0x%x.", ns->dev->name, ns->io_addr);
+    			break;
+			
+		default:
+			break;
+		}
+	}
+	
+	if (!irq || !ioport) {
+		ddf_msg(LVL_ERROR, "Missing HW resource(s) for device %s.",
+		    ns->dev->name);
+		ret = ENOENT;
+		goto failed;
+	}
+	
+	hw_res_clean_resource_list(&hw_resources);
+	return ret;
+	
+failed:
+	ns8250_dev_cleanup(ns);
+	hw_res_clean_resource_list(&hw_resources);
+	return ret;
+}
+
+/** Enable interrupts on the serial port device.
+ *
+ * Interrupt when data is received
+ *
+ * @param port		The base address of the serial port device's ports.
+ */
+static inline void ns8250_port_interrupts_enable(ioport8_t *port)
+{
+	pio_write_8(port + 1, 0x1);	/* Interrupt when data received. */
+	pio_write_8(port + 4, 0xB);
+}
+
+/** Disable interrupts on the serial port device.
+ *
+ * @param port		The base address of the serial port device's ports
+ */
+static inline void ns8250_port_interrupts_disable(ioport8_t *port)
+{
+	pio_write_8(port + 1, 0x0);	/* Disable all interrupts. */
+}
+
+/** Enable interrupts for the serial port device.
+ *
+ * @param ns		Serial port device
+ * @return		Zero on success, negative error number otherwise
+ */
+static int ns8250_interrupt_enable(ns8250_t *ns)
+{
+	/* Enable interrupt on the serial port. */
+	ns8250_port_interrupts_enable(ns->port);
+	
+	return EOK;
+}
+
+/** Set Divisor Latch Access Bit.
+ *
+ * When the Divisor Latch Access Bit is set, it is possible to set baud rate of
+ * the serial port device.
+ *
+ * @param port		The base address of the serial port device's ports.
+ */
+static inline void enable_dlab(ioport8_t *port)
+{
+	uint8_t val = pio_read_8(port + 3);
+	pio_write_8(port + 3, val | DLAB_MASK);
+}
+
+/** Clear Divisor Latch Access Bit.
+ *
+ * @param port		The base address of the serial port device's ports.
+ */
+static inline void clear_dlab(ioport8_t *port)
+{
+	uint8_t val = pio_read_8(port + 3);
+	pio_write_8(port + 3, val & (~DLAB_MASK));
+}
+
+/** Set baud rate of the serial communication on the serial device.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @param baud_rate	The baud rate to be used by the device.
+ * @return		Zero on success, negative error number otherwise (EINVAL
+ *			if the specified baud_rate is not valid).
+ */
+static int ns8250_port_set_baud_rate(ioport8_t *port, unsigned int baud_rate)
+{
+	uint16_t divisor;
+	uint8_t div_low, div_high;
+	
+	if (baud_rate < 50 || MAX_BAUD_RATE % baud_rate != 0) {
+		ddf_msg(LVL_ERROR, "Invalid baud rate %d requested.",
+		    baud_rate);
+		return EINVAL;
+	}
+	
+	divisor = MAX_BAUD_RATE / baud_rate;
+	div_low = (uint8_t)divisor;
+	div_high = (uint8_t)(divisor >> 8);
+	
+	/* Enable DLAB to be able to access baud rate divisor. */
+	enable_dlab(port);
+	
+	/* Set divisor low byte. */
+	pio_write_8(port + 0, div_low);
+	/* Set divisor high byte. */
+	pio_write_8(port + 1, div_high);
+	
+	clear_dlab(port);
+	
+	return EOK;
+}
+
+/** Get baud rate used by the serial port device.
+ *
+ * @param port		The base address of the serial port device's ports.
+ * @param baud_rate	The ouput parameter to which the baud rate is stored.
+ */
+static unsigned int ns8250_port_get_baud_rate(ioport8_t *port)
+{
+	uint16_t divisor;
+	uint8_t div_low, div_high;
+	
+	/* Enable DLAB to be able to access baud rate divisor. */
+	enable_dlab(port);
+	
+	/* Get divisor low byte. */
+	div_low = pio_read_8(port + 0);
+	/* Get divisor high byte. */
+	div_high = pio_read_8(port + 1);
+	
+	clear_dlab(port);
+	
+	divisor = (div_high << 8) | div_low;
+	return MAX_BAUD_RATE / divisor;
+}
+
+/** Get the parameters of the serial communication set on the serial port
+ * device.
+ *
+ * @param parity	The parity used.
+ * @param word_length	The length of one data unit in bits.
+ * @param stop_bits	The number of stop bits used (one or two).
+ */
+static void ns8250_port_get_com_props(ioport8_t *port, unsigned int *parity,
+    unsigned int *word_length, unsigned int *stop_bits)
+{
+	uint8_t val;
+	
+	val = pio_read_8(port + 3);
+	*parity = ((val >> 3) & 7);
+	
+	switch (val & 3) {
+	case WORD_LENGTH_5:
+		*word_length = 5;
+		break;
+	case WORD_LENGTH_6:
+		*word_length = 6;
+		break;
+	case WORD_LENGTH_7:
+		*word_length = 7;
+		break;
+	case WORD_LENGTH_8:
+		*word_length = 8;
+		break;
+	}
+	
+	if ((val >> 2) & 1)
+		*stop_bits = 2;
+	else
+		*stop_bits = 1;
+}
+
+/** Set the parameters of the serial communication on the serial port device.
+ *
+ * @param parity	The parity to be used.
+ * @param word_length	The length of one data unit in bits.
+ * @param stop_bits	The number of stop bits used (one or two).
+ * @return		Zero on success, EINVAL if some of the specified values
+ *			is invalid.
+ */
+static int ns8250_port_set_com_props(ioport8_t *port, unsigned int parity,
+    unsigned int word_length, unsigned int stop_bits)
+{
+	uint8_t val;
+	
+	switch (word_length) {
+	case 5:
+		val = WORD_LENGTH_5;
+		break;
+	case 6:
+		val = WORD_LENGTH_6;
+		break;
+	case 7:
+		val = WORD_LENGTH_7;
+		break;
+	case 8:
+		val = WORD_LENGTH_8;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	switch (stop_bits) {
+	case 1:
+		val |= ONE_STOP_BIT << 2;
+		break;
+	case 2:
+		val |= TWO_STOP_BITS << 2;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	switch (parity) {
+	case SERIAL_NO_PARITY:
+	case SERIAL_ODD_PARITY:
+	case SERIAL_EVEN_PARITY:
+	case SERIAL_MARK_PARITY:
+	case SERIAL_SPACE_PARITY:
+		val |= parity << 3;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	pio_write_8(port + 3, val);
+	
+	return EOK;
+}
+
+/** Initialize the serial port device.
+ *
+ * Set the default parameters of the serial communication.
+ *
+ * @param ns		Serial port device
+ */
+static void ns8250_initialize_port(ns8250_t *ns)
+{
+	ioport8_t *port = ns->port;
+	
+	/* Disable interrupts. */
+	ns8250_port_interrupts_disable(port);
+	/* Set baud rate. */
+	ns8250_port_set_baud_rate(port, 38400);
+	/* 8 bits, no parity, two stop bits. */
+	ns8250_port_set_com_props(port, SERIAL_NO_PARITY, 8, 2);
+	/* Enable FIFO, clear them, with 14-byte threshold. */
+	pio_write_8(port + 2, 0xC7);
+	/*
+	 * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
+	 * Aux Output2 set - needed for interrupts.
+	 */
+	pio_write_8(port + 4, 0x0B);
+}
+
+/** Read the data from the serial port device and store them to the input
+ * buffer.
+ *
+ * @param ns		Serial port device
+ */
+static void ns8250_read_from_device(ns8250_t *ns)
+{
+	ioport8_t *port = ns->port;
+	bool cont = true;
+	
+	while (cont) {
+		fibril_mutex_lock(&ns->mutex);
+		
+		cont = ns8250_received(port);
+		if (cont) {
+			uint8_t val = ns8250_read_8(port);
+			
+			if (ns->client_connected) {
+				if (!buf_push_back(&ns->input_buffer, val)) {
+					ddf_msg(LVL_WARN, "Buffer overflow on "
+					    "%s.", ns->dev->name);
+				} else {
+					ddf_msg(LVL_DEBUG2, "Character %c saved "
+					    "to the buffer of %s.",
+					    val, ns->dev->name);
+				}
+			}
+		}
+		
+		fibril_mutex_unlock(&ns->mutex);
+		fibril_yield();
+	}
+}
+
+/** The interrupt handler.
+ *
+ * The serial port is initialized to interrupt when some data come, so the
+ * interrupt is handled by reading the incomming data.
+ *
+ * @param dev		The serial port device.
+ */
+static inline void ns8250_interrupt_handler(ddf_dev_t *dev, ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	ns8250_read_from_device(NS8250_FROM_DEV(dev));
+}
+
+/** Register the interrupt handler for the device.
+ *
+ * @param ns		Serial port device
+ */
+static inline int ns8250_register_interrupt_handler(ns8250_t *ns)
+{
+	return register_interrupt_handler(ns->dev, ns->irq,
+	    ns8250_interrupt_handler, NULL);
+}
+
+/** Unregister the interrupt handler for the device.
+ *
+ * @param ns		Serial port device
+ */
+static inline int ns8250_unregister_interrupt_handler(ns8250_t *ns)
+{
+	return unregister_interrupt_handler(ns->dev, ns->irq);
+}
+
+/** The add_device callback method of the serial port driver.
+ *
+ * Probe and initialize the newly added device.
+ *
+ * @param dev		The serial port device.
+ */
+static int ns8250_add_device(ddf_dev_t *dev)
+{
+	ns8250_t *ns = NULL;
+	ddf_fun_t *fun = NULL;
+	bool need_cleanup = false;
+	int rc;
+	
+	ddf_msg(LVL_DEBUG, "ns8250_add_device %s (handle = %d)",
+	    dev->name, (int) dev->handle);
+	
+	/* Allocate soft-state for the device */
+	ns = ns8250_new();
+	if (ns == NULL) {
+		rc = ENOMEM;
+		goto fail;
+	}
+	
+	ns->dev = dev;
+	dev->driver_data = ns;
+	
+	rc = ns8250_dev_initialize(ns);
+	if (rc != EOK)
+		goto fail;
+	
+	need_cleanup = true;
+	
+	if (!ns8250_pio_enable(ns)) {
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
+	
+	/* Find out whether the device is present. */
+	if (!ns8250_dev_probe(ns)) {
+		rc = ENOENT;
+		goto fail;
+	}
+	
+	/* Serial port initialization (baud rate etc.). */
+	ns8250_initialize_port(ns);
+	
+	/* Register interrupt handler. */
+	if (ns8250_register_interrupt_handler(ns) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to register interrupt handler.");
+		rc = EADDRNOTAVAIL;
+		goto fail;
+	}
+	
+	/* Enable interrupt. */
+	rc = ns8250_interrupt_enable(ns);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed to enable the interrupt. Error code = "
+		    "%d.", rc);
+		goto fail;
+	}
+	
+	fun = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function.");
+		goto fail;
+	}
+	
+	/* Set device operations. */
+	fun->ops = &ns8250_dev_ops;
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function.");
+		goto fail;
+	}
+
+	ns->fun = fun;
+	
+	ddf_fun_add_to_category(fun, "serial");
+	
+	ddf_msg(LVL_NOTE, "Device %s successfully initialized.",
+	    dev->name);
+	
+	return EOK;
+fail:
+	if (fun != NULL)
+		ddf_fun_destroy(fun);
+	if (need_cleanup)
+		ns8250_dev_cleanup(ns);
+	if (ns != NULL)
+		ns8250_delete(ns);
+	return rc;
+}
+
+/** Open the device.
+ *
+ * This is a callback function called when a client tries to connect to the
+ * device.
+ *
+ * @param dev		The device.
+ */
+static int ns8250_open(ddf_fun_t *fun)
+{
+	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
+	int res;
+	
+	fibril_mutex_lock(&data->mutex);
+	if (data->client_connected) {
+		res = ELIMIT;
+	} else {
+		res = EOK;
+		data->client_connected = true;
+	}
+	fibril_mutex_unlock(&data->mutex);
+	
+	return res;
+}
+
+/** Close the device.
+ *
+ * This is a callback function called when a client tries to disconnect from
+ * the device.
+ *
+ * @param dev		The device.
+ */
+static void ns8250_close(ddf_fun_t *fun)
+{
+	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
+	
+	fibril_mutex_lock(&data->mutex);
+	
+	assert(data->client_connected);
+	
+	data->client_connected = false;
+	buf_clear(&data->input_buffer);
+	
+	fibril_mutex_unlock(&data->mutex);
+}
+
+/** Get parameters of the serial communication which are set to the specified
+ * device.
+ *
+ * @param dev		The serial port device.
+ * @param baud_rate	The baud rate used by the device.
+ * @param parity	The type of parity used by the device.
+ * @param word_length	The size of one data unit in bits.
+ * @param stop_bits	The number of stop bits used.
+ */
+static void
+ns8250_get_props(ddf_dev_t *dev, unsigned int *baud_rate, unsigned int *parity,
+    unsigned int *word_length, unsigned int* stop_bits)
+{
+	ns8250_t *data = (ns8250_t *) dev->driver_data;
+	ioport8_t *port = data->port;
+	
+	fibril_mutex_lock(&data->mutex);
+	ns8250_port_interrupts_disable(port);
+	*baud_rate = ns8250_port_get_baud_rate(port);
+	ns8250_port_get_com_props(port, parity, word_length, stop_bits);
+	ns8250_port_interrupts_enable(port);
+	fibril_mutex_unlock(&data->mutex);
+	
+	ddf_msg(LVL_DEBUG, "ns8250_get_props: baud rate %d, parity 0x%x, word "
+	    "length %d, stop bits %d", *baud_rate, *parity, *word_length,
+	    *stop_bits);
+}
+
+/** Set parameters of the serial communication to the specified serial port
+ * device.
+ *
+ * @param dev		The serial port device.
+ * @param baud_rate	The baud rate to be used by the device.
+ * @param parity	The type of parity to be used by the device.
+ * @param word_length	The size of one data unit in bits.
+ * @param stop_bits	The number of stop bits to be used.
+ */
+static int ns8250_set_props(ddf_dev_t *dev, unsigned int baud_rate,
+    unsigned int parity, unsigned int word_length, unsigned int stop_bits)
+{
+	ddf_msg(LVL_DEBUG, "ns8250_set_props: baud rate %d, parity 0x%x, word "
+	    "length %d, stop bits %d", baud_rate, parity, word_length,
+	    stop_bits);
+	
+	ns8250_t *data = (ns8250_t *) dev->driver_data;
+	ioport8_t *port = data->port;
+	int ret;
+	
+	fibril_mutex_lock(&data->mutex);
+	ns8250_port_interrupts_disable(port);
+	ret = ns8250_port_set_baud_rate(port, baud_rate);
+	if (ret == EOK)
+		ret = ns8250_port_set_com_props(port, parity, word_length, stop_bits);
+	ns8250_port_interrupts_enable(port);
+	fibril_mutex_unlock(&data->mutex);
+	
+	return ret;
+}
+
+/** Default handler for client requests which are not handled by the standard
+ * interfaces.
+ *
+ * Configure the parameters of the serial communication.
+ */
+static void ns8250_default_handler(ddf_fun_t *fun, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	sysarg_t method = IPC_GET_IMETHOD(*call);
+	int ret;
+	unsigned int baud_rate, parity, word_length, stop_bits;
+	
+	switch (method) {
+	case SERIAL_GET_COM_PROPS:
+		ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
+		    &stop_bits);
+		async_answer_4(callid, EOK, baud_rate, parity, word_length,
+		    stop_bits);
+		break;
+		
+	case SERIAL_SET_COM_PROPS:
+ 		baud_rate = IPC_GET_ARG1(*call);
+		parity = IPC_GET_ARG2(*call);
+		word_length = IPC_GET_ARG3(*call);
+		stop_bits = IPC_GET_ARG4(*call);
+		ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
+		    stop_bits);
+		async_answer_0(callid, ret);
+		break;
+		
+	default:
+		async_answer_0(callid, ENOTSUP);
+	}
+}
+
+/** Initialize the serial port driver.
+ *
+ * Initialize device operations structures with callback methods for handling
+ * client requests to the serial port devices.
+ */
+static void ns8250_init(void)
+{
+	ddf_log_init(NAME, LVL_ERROR);
+	
+	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;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS serial port driver\n");
+	ns8250_init();
+	return ddf_driver_main(&ns8250_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/char/ns8250/ns8250.ma
===================================================================
--- uspace/drv/char/ns8250/ns8250.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/char/ns8250/ns8250.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 isa/ns8250
Index: uspace/drv/infrastructure/root/Makefile
===================================================================
--- uspace/drv/infrastructure/root/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/root/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = root
+
+SOURCES = \
+	root.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/root/root.c
===================================================================
--- uspace/drv/infrastructure/root/root.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/root/root.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup root Root device driver.
+ * @brief HelenOS root device driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <str_error.h>
+#include <ctype.h>
+#include <macros.h>
+#include <inttypes.h>
+#include <sysinfo.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <devman.h>
+#include <ipc/devman.h>
+
+#define NAME "root"
+
+#define PLATFORM_FUN_NAME "hw"
+#define PLATFORM_FUN_MATCH_ID_FMT "platform/%s"
+#define PLATFORM_FUN_MATCH_SCORE 100
+
+#define VIRTUAL_FUN_NAME "virt"
+#define VIRTUAL_FUN_MATCH_ID "rootvirt"
+#define VIRTUAL_FUN_MATCH_SCORE 100
+
+static int root_add_device(ddf_dev_t *dev);
+
+/** The root device driver's standard operations. */
+static driver_ops_t root_ops = {
+	.add_device = &root_add_device
+};
+
+/** The root device driver structure. */
+static driver_t root_driver = {
+	.name = NAME,
+	.driver_ops = &root_ops
+};
+
+/** Create the function which represents the root of virtual device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_virtual_root_fun(ddf_dev_t *dev)
+{
+	const char *name = VIRTUAL_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Adding new function for virtual devices. "
+	    "Function node is `%s' (%d %s)", name,
+	    VIRTUAL_FUN_MATCH_SCORE, VIRTUAL_FUN_MATCH_ID);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, VIRTUAL_FUN_MATCH_ID,
+	    VIRTUAL_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Create the function which represents the root of HW device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_platform_fun(ddf_dev_t *dev)
+{
+	char *match_id;
+	char *platform;
+	size_t platform_size;
+
+	const char *name = PLATFORM_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
+
+	/* Get platform name from sysinfo. */
+	platform = sysinfo_get_data("platform", &platform_size);
+	if (platform == NULL) {
+		ddf_msg(LVL_ERROR, "Failed to obtain platform name.");
+		return ENOENT;
+	}
+
+	/* Null-terminate string. */
+	platform = realloc(platform, platform_size + 1);
+	if (platform == NULL) {
+		ddf_msg(LVL_ERROR, "Memory allocation failed.");
+		return ENOMEM;
+	}
+
+	platform[platform_size] = '\0';
+
+	/* Construct match ID. */
+	if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
+		ddf_msg(LVL_ERROR, "Memory allocation failed.");
+		return ENOMEM;
+	}
+
+	/* Add function. */
+	ddf_msg(LVL_DEBUG, "Adding platform function. Function node is `%s' "
+	    " (%d %s)", PLATFORM_FUN_NAME, PLATFORM_FUN_MATCH_SCORE,
+	    match_id);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Error creating function %s", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, PLATFORM_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	free(match_id);
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Get the root device.
+ *
+ * @param dev		The device which is root of the whole device tree (both
+ *			of HW and pseudo devices).
+ */
+static int root_add_device(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "root_add_device, device handle=%" PRIun,
+	    dev->handle);
+
+	/*
+	 * Register virtual devices root.
+	 * We ignore error occurrence because virtual devices shall not be
+	 * vital for the system.
+	 */
+	add_virtual_root_fun(dev);
+
+	/* Register root device's children. */
+	int res = add_platform_fun(dev);
+	if (EOK != res)
+		ddf_msg(LVL_ERROR, "Failed adding child device for platform.");
+
+	return res;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS root device driver\n");
+
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&root_driver);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/infrastructure/root/root.ma
===================================================================
--- uspace/drv/infrastructure/root/root.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/root/root.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 root
Index: uspace/drv/infrastructure/rootmac/Makefile
===================================================================
--- uspace/drv/infrastructure/rootmac/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootmac/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = rootmac
+
+SOURCES = \
+	rootmac.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/rootmac/rootmac.c
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootmac/rootmac.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/**
+ * @defgroup root_mac Mac platform driver.
+ * @brief HelenOS Mac platform driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <errno.h>
+#include <ops/hw_res.h>
+#include <stdio.h>
+
+#define NAME  "rootmac"
+
+/** Obtain function soft-state from DDF function node */
+#define ROOTMAC_FUN(fnode) \
+	((rootmac_fun_t *) (fnode)->driver_data)
+
+typedef struct {
+	hw_resource_list_t hw_resources;
+} rootmac_fun_t;
+
+static hw_resource_t pci_conf_regs = {
+	.type = IO_RANGE,
+	.res.io_range = {
+		.address = 0xCF8,
+		.size = 8,
+		.endianness = LITTLE_ENDIAN
+	}
+};
+
+static rootmac_fun_t pci_data = {
+	.hw_resources = {
+		1,
+		&pci_conf_regs
+	}
+};
+
+static ddf_dev_ops_t rootmac_fun_ops;
+
+static bool rootmac_add_fun(ddf_dev_t *dev, const char *name,
+    const char *str_match_id, rootmac_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
+	
+	ddf_fun_t *fnode = NULL;
+	match_id_t *match_id = NULL;
+	
+	/* Create new device. */
+	fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL)
+		goto failure;
+	
+	fnode->driver_data = fun;
+	
+	/* Initialize match id list */
+	match_id = create_match_id();
+	if (match_id == NULL)
+		goto failure;
+	
+	match_id->id = str_match_id;
+	match_id->score = 100;
+	add_match_id(&fnode->match_ids, match_id);
+	
+	/* Set provided operations to the device. */
+	fnode->ops = &rootmac_fun_ops;
+	
+	/* Register function. */
+	if (ddf_fun_bind(fnode) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
+		goto failure;
+	}
+	
+	return true;
+	
+failure:
+	if (match_id != NULL)
+		match_id->id = NULL;
+	
+	if (fnode != NULL)
+		ddf_fun_destroy(fnode);
+	
+	ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name);
+	
+	return false;
+}
+
+/** Get the root device.
+ *
+ * @param dev Device which is root of the whole device tree
+ *            (both of HW and pseudo devices).
+ *
+ * @return Zero on success, negative error number otherwise.
+ *
+ */
+static int rootmac_add_device(ddf_dev_t *dev)
+{
+	/* Register functions */
+	if (!rootmac_add_fun(dev, "pci0", "pangea_pci", &pci_data))
+		ddf_msg(LVL_ERROR, "Failed to add functions for Mac platform.");
+	
+	return EOK;
+}
+
+/** The root device driver's standard operations. */
+static driver_ops_t rootmac_ops = {
+	.add_device = &rootmac_add_device
+};
+
+/** The root device driver structure. */
+static driver_t rootmac_driver = {
+	.name = NAME,
+	.driver_ops = &rootmac_ops
+};
+
+static hw_resource_list_t *rootmac_get_resources(ddf_fun_t *fnode)
+{
+	rootmac_fun_t *fun = ROOTMAC_FUN(fnode);
+	assert(fun != NULL);
+	
+	return &fun->hw_resources;
+}
+
+static bool rootmac_enable_interrupt(ddf_fun_t *fun)
+{
+	/* TODO */
+	
+	return false;
+}
+
+static hw_res_ops_t fun_hw_res_ops = {
+	&rootmac_get_resources,
+	&rootmac_enable_interrupt
+};
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS Mac platform driver\n", NAME);
+	ddf_log_init(NAME, LVL_ERROR);
+	rootmac_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
+	return ddf_driver_main(&rootmac_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/infrastructure/rootmac/rootmac.ma
===================================================================
--- uspace/drv/infrastructure/rootmac/rootmac.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootmac/rootmac.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 platform/mac
Index: uspace/drv/infrastructure/rootpc/Makefile
===================================================================
--- uspace/drv/infrastructure/rootpc/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootpc/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = rootpc
+
+SOURCES = \
+	rootpc.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/rootpc/rootpc.c
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootpc/rootpc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup root_pc PC platform driver.
+ * @brief HelenOS PC platform driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ctype.h>
+#include <macros.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <devman.h>
+#include <ipc/devman.h>
+#include <ipc/dev_iface.h>
+#include <ops/hw_res.h>
+#include <device/hw_res.h>
+
+#define NAME "rootpc"
+
+/** Obtain function soft-state from DDF function node */
+#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
+
+typedef struct rootpc_fun {
+	hw_resource_list_t hw_resources;
+} rootpc_fun_t;
+
+static int rootpc_add_device(ddf_dev_t *dev);
+static void root_pc_init(void);
+
+/** The root device driver's standard operations. */
+static driver_ops_t rootpc_ops = {
+	.add_device = &rootpc_add_device
+};
+
+/** The root device driver structure. */
+static driver_t rootpc_driver = {
+	.name = NAME,
+	.driver_ops = &rootpc_ops
+};
+
+static hw_resource_t pci_conf_regs = {
+	.type = IO_RANGE,
+	.res.io_range = {
+		.address = 0xCF8,
+		.size = 8,
+		.endianness = LITTLE_ENDIAN
+	}
+};
+
+static rootpc_fun_t pci_data = {
+	.hw_resources = {
+		1,
+		&pci_conf_regs
+	}
+};
+
+static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
+{
+	rootpc_fun_t *fun = ROOTPC_FUN(fnode);
+	
+	assert(fun != NULL);
+	return &fun->hw_resources;
+}
+
+static bool rootpc_enable_interrupt(ddf_fun_t *fun)
+{
+	/* TODO */
+	
+	return false;
+}
+
+static hw_res_ops_t fun_hw_res_ops = {
+	&rootpc_get_resources,
+	&rootpc_enable_interrupt
+};
+
+/* Initialized in root_pc_init() function. */
+static ddf_dev_ops_t rootpc_fun_ops;
+
+static bool
+rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
+    rootpc_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
+	
+	ddf_fun_t *fnode = NULL;
+	match_id_t *match_id = NULL;
+	
+	/* Create new device. */
+	fnode = ddf_fun_create(dev, fun_inner, name);
+	if (fnode == NULL)
+		goto failure;
+	
+	fnode->driver_data = fun;
+	
+	/* Initialize match id list */
+	match_id = create_match_id();
+	if (match_id == NULL)
+		goto failure;
+	
+	match_id->id = str_match_id;
+	match_id->score = 100;
+	add_match_id(&fnode->match_ids, match_id);
+	
+	/* Set provided operations to the device. */
+	fnode->ops = &rootpc_fun_ops;
+	
+	/* Register function. */
+	if (ddf_fun_bind(fnode) != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
+		goto failure;
+	}
+	
+	return true;
+	
+failure:
+	if (match_id != NULL)
+		match_id->id = NULL;
+	
+	if (fnode != NULL)
+		ddf_fun_destroy(fnode);
+	
+	ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name);
+	
+	return false;
+}
+
+static bool rootpc_add_functions(ddf_dev_t *dev)
+{
+	return rootpc_add_fun(dev, "pci0", "intel_pci", &pci_data);
+}
+
+/** Get the root device.
+ *
+ * @param dev		The device which is root of the whole device tree (both
+ *			of HW and pseudo devices).
+ * @return		Zero on success, negative error number otherwise.
+ */
+static int rootpc_add_device(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "rootpc_add_device, device handle = %d",
+	    (int)dev->handle);
+	
+	/* Register functions. */
+	if (!rootpc_add_functions(dev)) {
+		ddf_msg(LVL_ERROR, "Failed to add functions for PC platform.");
+	}
+	
+	return EOK;
+}
+
+static void root_pc_init(void)
+{
+	ddf_log_init(NAME, LVL_ERROR);
+	rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS PC platform driver\n");
+	root_pc_init();
+	return ddf_driver_main(&rootpc_driver);
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/infrastructure/rootpc/rootpc.ma
===================================================================
--- uspace/drv/infrastructure/rootpc/rootpc.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootpc/rootpc.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 platform/pc
Index: uspace/drv/infrastructure/rootvirt/Makefile
===================================================================
--- uspace/drv/infrastructure/rootvirt/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootvirt/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = rootvirt
+
+SOURCES = \
+	rootvirt.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/infrastructure/rootvirt/devices.def
===================================================================
--- uspace/drv/infrastructure/rootvirt/devices.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootvirt/devices.def	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,34 @@
+/*
+ * Add list of virtual devices you want to launch driver for here.
+ *
+ * Unless the list is empty, the last item shall be followed by a comma.
+ */
+#ifdef CONFIG_TEST_DRIVERS
+{
+	.name = "test1",
+	.match_id = "virtual&test1"
+},
+{
+	.name = "test2alpha",
+	.match_id = "virtual&test2"
+},
+{
+	.name = "test2bravo",
+	.match_id = "virtual&test2"
+},
+{
+	.name = "null",
+	.match_id = "virtual&test1"
+},
+{
+	.name = "test3",
+	.match_id = "virtual&test3"
+},
+#endif
+#ifdef CONFIG_RUN_VIRTUAL_USB_HC
+/* Virtual USB host controller. */
+{
+	.name = "usbhc",
+	.match_id = "usb&hc=vhc"
+},
+#endif
Index: uspace/drv/infrastructure/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup rootvirt Root device driver for virtual devices.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#define NAME "rootvirt"
+
+/** Virtual function entry */
+typedef struct {
+	/** Function name */
+	const char *name;
+	/** Function match ID */
+	const char *match_id;
+} virtual_function_t;
+
+/** List of existing virtual functions */
+virtual_function_t virtual_functions[] = {
+#include "devices.def"
+	/* Terminating item */
+	{
+		.name = NULL,
+		.match_id = NULL
+	}
+};
+
+static int rootvirt_add_device(ddf_dev_t *dev);
+
+static driver_ops_t rootvirt_ops = {
+	.add_device = &rootvirt_add_device
+};
+
+static driver_t rootvirt_driver = {
+	.name = NAME,
+	.driver_ops = &rootvirt_ops
+};
+
+/** Add function to the virtual device.
+ *
+ * @param vdev		The virtual device
+ * @param vfun		Virtual function description
+ * @return		EOK on success or negative error code.
+ */
+static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
+{
+	ddf_fun_t *fun;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Registering function `%s' (match \"%s\")",
+	    vfun->name, vfun->match_id);
+
+	fun = ddf_fun_create(vdev, fun_inner, vfun->name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", vfun->name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    vfun->name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s",
+		    vfun->name, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	ddf_msg(LVL_NOTE, "Registered child device `%s'", vfun->name);
+	return EOK;
+}
+
+static int rootvirt_add_device(ddf_dev_t *dev)
+{
+	static int instances = 0;
+
+	/*
+	 * Allow only single instance of root virtual device.
+	 */
+	instances++;
+	if (instances > 1) {
+		return ELIMIT;
+	}
+
+	ddf_msg(LVL_DEBUG, "add_device(handle=%d)", (int)dev->handle);
+
+	/*
+	 * Go through all virtual functions and try to add them.
+	 * We silently ignore failures.
+	 */
+	virtual_function_t *vfun = virtual_functions;
+	while (vfun->name != NULL) {
+		(void) rootvirt_add_fun(dev, vfun);
+		vfun++;
+	}
+
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS virtual devices root driver\n");
+
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&rootvirt_driver);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/infrastructure/rootvirt/rootvirt.ma
===================================================================
--- uspace/drv/infrastructure/rootvirt/rootvirt.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/infrastructure/rootvirt/rootvirt.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 rootvirt
Index: pace/drv/isa/Makefile
===================================================================
--- uspace/drv/isa/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = isa
-
-SOURCES = \
-	isa.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/isa/isa.c
===================================================================
--- uspace/drv/isa/isa.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,507 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @defgroup isa ISA bus driver.
- * @brief HelenOS ISA bus driver.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <str_error.h>
-#include <ctype.h>
-#include <macros.h>
-#include <malloc.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#include <ddf/driver.h>
-#include <ops/hw_res.h>
-
-#include <devman.h>
-#include <ipc/devman.h>
-#include <device/hw_res.h>
-
-#define NAME "isa"
-#define CHILD_FUN_CONF_PATH "/drv/isa/isa.dev"
-
-/** Obtain soft-state pointer from function node pointer */
-#define ISA_FUN(fnode) ((isa_fun_t *) ((fnode)->driver_data))
-
-#define ISA_MAX_HW_RES 4
-
-typedef struct isa_fun {
-	ddf_fun_t *fnode;
-	hw_resource_list_t hw_resources;
-} isa_fun_t;
-
-static hw_resource_list_t *isa_get_fun_resources(ddf_fun_t *fnode)
-{
-	isa_fun_t *fun = ISA_FUN(fnode);
-	assert(fun != NULL);
-
-	return &fun->hw_resources;
-}
-
-static bool isa_enable_fun_interrupt(ddf_fun_t *fnode)
-{
-	// TODO
-
-	return false;
-}
-
-static hw_res_ops_t isa_fun_hw_res_ops = {
-	&isa_get_fun_resources,
-	&isa_enable_fun_interrupt
-};
-
-static ddf_dev_ops_t isa_fun_ops;
-
-static int isa_add_device(ddf_dev_t *dev);
-
-/** The isa device driver's standard operations */
-static driver_ops_t isa_ops = {
-	.add_device = &isa_add_device
-};
-
-/** The isa device driver structure. */
-static driver_t isa_driver = {
-	.name = NAME,
-	.driver_ops = &isa_ops
-};
-
-static isa_fun_t *isa_fun_create(ddf_dev_t *dev, const char *name)
-{
-	isa_fun_t *fun = calloc(1, sizeof(isa_fun_t));
-	if (fun == NULL)
-		return NULL;
-
-	ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
-	if (fnode == NULL) {
-		free(fun);
-		return NULL;
-	}
-
-	fun->fnode = fnode;
-	fnode->driver_data = fun;
-	return fun;
-}
-
-static char *fun_conf_read(const char *conf_path)
-{
-	bool suc = false;
-	char *buf = NULL;
-	bool opened = false;
-	int fd;
-	size_t len = 0;
-
-	fd = open(conf_path, O_RDONLY);
-	if (fd < 0) {
-		printf(NAME ": unable to open %s\n", conf_path);
-		goto cleanup;
-	}
-
-	opened = true;
-
-	len = lseek(fd, 0, SEEK_END);
-	lseek(fd, 0, SEEK_SET);	
-	if (len == 0) {
-		printf(NAME ": fun_conf_read error: configuration file '%s' "
-		    "is empty.\n", conf_path);
-		goto cleanup;
-	}
-
-	buf = malloc(len + 1);
-	if (buf == NULL) {
-		printf(NAME ": fun_conf_read error: memory allocation failed.\n");
-		goto cleanup;
-	}
-
-	if (0 >= read(fd, buf, len)) {
-		printf(NAME ": fun_conf_read error: unable to read file '%s'.\n",
-		    conf_path);
-		goto cleanup;
-	}
-
-	buf[len] = 0;
-
-	suc = true;
-
-cleanup:
-	if (!suc && buf != NULL) {
-		free(buf);
-		buf = NULL;
-	}
-
-	if (opened)
-		close(fd);
-
-	return buf;
-}
-
-static char *str_get_line(char *str, char **next)
-{
-	char *line = str;
-
-	if (str == NULL) {
-		*next = NULL;
-		return NULL;
-	}
-
-	while (*str != '\0' && *str != '\n') {
-		str++;
-	}
-
-	if (*str != '\0') {
-		*next = str + 1;
-	} else {
-		*next = NULL;
-	}
-
-	*str = '\0';
-	return line;
-}
-
-static bool line_empty(const char *line)
-{
-	while (line != NULL && *line != 0) {
-		if (!isspace(*line))
-			return false;
-		line++;
-	}
-
-	return true;
-}
-
-static char *get_device_name(char *line)
-{
-	/* Skip leading spaces. */
-	while (*line != '\0' && isspace(*line)) {
-		line++;
-	}
-
-	/* Get the name part of the rest of the line. */
-	strtok(line, ":");
-
-	/* Allocate output buffer. */
-	size_t size = str_size(line) + 1;
-	char *name = malloc(size);
-
-	if (name != NULL) {
-		/* Copy the result to the output buffer. */
-		str_cpy(name, size, line);
-	}
-
-	return name;
-}
-
-static inline char *skip_spaces(char *line)
-{
-	/* Skip leading spaces. */
-	while (*line != '\0' && isspace(*line))
-		line++;
-
-	return line;
-}
-
-static void isa_fun_set_irq(isa_fun_t *fun, int irq)
-{
-	size_t count = fun->hw_resources.count;
-	hw_resource_t *resources = fun->hw_resources.resources;
-
-	if (count < ISA_MAX_HW_RES) {
-		resources[count].type = INTERRUPT;
-		resources[count].res.interrupt.irq = irq;
-
-		fun->hw_resources.count++;
-
-		printf(NAME ": added irq 0x%x to function %s\n", irq,
-		    fun->fnode->name);
-	}
-}
-
-static void isa_fun_set_io_range(isa_fun_t *fun, size_t addr, size_t len)
-{
-	size_t count = fun->hw_resources.count;
-	hw_resource_t *resources = fun->hw_resources.resources;
-
-	if (count < ISA_MAX_HW_RES) {
-		resources[count].type = IO_RANGE;
-		resources[count].res.io_range.address = addr;
-		resources[count].res.io_range.size = len;
-		resources[count].res.io_range.endianness = LITTLE_ENDIAN;
-
-		fun->hw_resources.count++;
-
-		printf(NAME ": added io range (addr=0x%x, size=0x%x) to "
-		    "function %s\n", (unsigned int) addr, (unsigned int) len,
-		    fun->fnode->name);
-	}
-}
-
-static void fun_parse_irq(isa_fun_t *fun, char *val)
-{
-	int irq = 0;
-	char *end = NULL;
-
-	val = skip_spaces(val);
-	irq = (int)strtol(val, &end, 0x10);
-
-	if (val != end)
-		isa_fun_set_irq(fun, irq);
-}
-
-static void fun_parse_io_range(isa_fun_t *fun, char *val)
-{
-	size_t addr, len;
-	char *end = NULL;
-
-	val = skip_spaces(val);
-	addr = strtol(val, &end, 0x10);
-
-	if (val == end)
-		return;
-
-	val = skip_spaces(end);
-	len = strtol(val, &end, 0x10);
-
-	if (val == end)
-		return;
-
-	isa_fun_set_io_range(fun, addr, len);
-}
-
-static void get_match_id(char **id, char *val)
-{
-	char *end = val;
-
-	while (!isspace(*end))
-		end++;
-
-	size_t size = end - val + 1;
-	*id = (char *)malloc(size);
-	str_cpy(*id, size, val);
-}
-
-static void fun_parse_match_id(isa_fun_t *fun, char *val)
-{
-	char *id = NULL;
-	int score = 0;
-	char *end = NULL;
-	int rc;
-
-	val = skip_spaces(val);
-
-	score = (int)strtol(val, &end, 10);
-	if (val == end) {
-		printf(NAME " : error - could not read match score for "
-		    "function %s.\n", fun->fnode->name);
-		return;
-	}
-
-	val = skip_spaces(end);
-	get_match_id(&id, val);
-	if (id == NULL) {
-		printf(NAME " : error - could not read match id for "
-		    "function %s.\n", fun->fnode->name);
-		return;
-	}
-
-	printf(NAME ": adding match id '%s' with score %d to function %s\n", id,
-	    score, fun->fnode->name);
-
-	rc = ddf_fun_add_match_id(fun->fnode, id, score);
-	if (rc != EOK)
-		printf(NAME ": error adding match ID: %s\n", str_error(rc));
-}
-
-static bool prop_parse(isa_fun_t *fun, char *line, const char *prop,
-    void (*read_fn)(isa_fun_t *, char *))
-{
-	size_t proplen = str_size(prop);
-
-	if (str_lcmp(line, prop, proplen) == 0) {
-		line += proplen;
-		line = skip_spaces(line);
-		(*read_fn)(fun, line);
-
-		return true;
-	}
-
-	return false;
-}
-
-static void fun_prop_parse(isa_fun_t *fun, char *line)
-{
-	/* Skip leading spaces. */
-	line = skip_spaces(line);
-
-	if (!prop_parse(fun, line, "io_range", &fun_parse_io_range) &&
-	    !prop_parse(fun, line, "irq", &fun_parse_irq) &&
-	    !prop_parse(fun, line, "match", &fun_parse_match_id))
-	{
-	    printf(NAME " error undefined device property at line '%s'\n",
-		line);
-	}
-}
-
-static void fun_hw_res_alloc(isa_fun_t *fun)
-{
-	fun->hw_resources.resources = 
-	    (hw_resource_t *)malloc(sizeof(hw_resource_t) * ISA_MAX_HW_RES);
-}
-
-static char *isa_fun_read_info(char *fun_conf, ddf_dev_t *dev)
-{
-	char *line;
-	char *fun_name = NULL;
-
-	/* Skip empty lines. */
-	while (true) {
-		line = str_get_line(fun_conf, &fun_conf);
-
-		if (line == NULL) {
-			/* no more lines */
-			return NULL;
-		}
-
-		if (!line_empty(line))
-			break;
-	}
-
-	/* Get device name. */
-	fun_name = get_device_name(line);
-	if (fun_name == NULL)
-		return NULL;
-
-	isa_fun_t *fun = isa_fun_create(dev, fun_name);
-	if (fun == NULL) {
-		free(fun_name);
-		return NULL;
-	}
-
-	/* Allocate buffer for the list of hardware resources of the device. */
-	fun_hw_res_alloc(fun);
-
-	/* Get properties of the device (match ids, irq and io range). */
-	while (true) {
-		line = str_get_line(fun_conf, &fun_conf);
-
-		if (line_empty(line)) {
-			/* no more device properties */
-			break;
-		}
-
-		/*
-		 * Get the device's property from the configuration line
-		 * and store it in the device structure.
-		 */
-		fun_prop_parse(fun, line);
-	}
-
-	/* Set device operations to the device. */
-	fun->fnode->ops = &isa_fun_ops;
-
-	printf(NAME ": Binding function %s.\n", fun->fnode->name);
-
-	/* XXX Handle error */
-	(void) ddf_fun_bind(fun->fnode);
-
-	return fun_conf;
-}
-
-static void fun_conf_parse(char *conf, ddf_dev_t *dev)
-{
-	while (conf != NULL && *conf != '\0') {
-		conf = isa_fun_read_info(conf, dev);
-	}
-}
-
-static void isa_functions_add(ddf_dev_t *dev)
-{
-	char *fun_conf;
-
-	fun_conf = fun_conf_read(CHILD_FUN_CONF_PATH);
-	if (fun_conf != NULL) {
-		fun_conf_parse(fun_conf, dev);
-		free(fun_conf);
-	}
-}
-
-static int isa_add_device(ddf_dev_t *dev)
-{
-	printf(NAME ": isa_add_device, device handle = %d\n",
-	    (int) dev->handle);
-
-	/* Make the bus device more visible. Does not do anything. */
-	printf(NAME ": adding a 'ctl' function\n");
-
-	ddf_fun_t *ctl = ddf_fun_create(dev, fun_exposed, "ctl");
-	if (ctl == NULL) {
-		printf(NAME ": Error creating control function.\n");
-		return EXDEV;
-	}
-
-	if (ddf_fun_bind(ctl) != EOK) {
-		printf(NAME ": Error binding control function.\n");
-		return EXDEV;
-	}
-
-	/* Add functions as specified in the configuration file. */
-	isa_functions_add(dev);
-	printf(NAME ": finished the enumeration of legacy functions\n");
-
-	return EOK;
-}
-
-static void isa_init() 
-{
-	isa_fun_ops.interfaces[HW_RES_DEV_IFACE] = &isa_fun_hw_res_ops;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS ISA bus driver\n");
-	isa_init();
-	return ddf_driver_main(&isa_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/isa/isa.dev
===================================================================
--- uspace/drv/isa/isa.dev	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,15 +1,0 @@
-com1:
-	match 100 isa/ns8250
-	irq 4
-	io_range 3f8 8
-
-com2:
-	match 100 isa/ns8250
-	irq 3
-	io_range 2f8 8
-
-keyboard:
-	match 100 isa/keyboard
-	irq 1
-	io_range 060 10
-	
Index: pace/drv/isa/isa.ma
===================================================================
--- uspace/drv/isa/isa.ma	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1 +1,0 @@
-9 	pci/ven=8086&dev=7000
Index: pace/drv/ns8250/Makefile
===================================================================
--- uspace/drv/ns8250/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = ns8250
-
-SOURCES = \
-	ns8250.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/ns8250/cyclic_buffer.h
===================================================================
--- uspace/drv/ns8250/cyclic_buffer.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,83 +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 ns8250
- * @{
- */
-/** @file
- */
-
-#ifndef CYCLIC_BUFFER_H_
-#define CYCLIC_BUFFER_H_
-
-#define BUF_LEN 256
-
-typedef struct cyclic_buffer {
-	uint8_t buf[BUF_LEN];
-	int start;
-	int cnt;
-}  cyclic_buffer_t;
-
-/*
- * @return		False if the buffer is full.
- */
-static inline bool buf_push_back(cyclic_buffer_t *buf, uint8_t item)
-{
-	if (buf->cnt >= BUF_LEN)
-		return false;
-	int pos = (buf->start + buf->cnt) % BUF_LEN;
-	buf->buf[pos] = item;
-	buf->cnt++;
-	return true;
-}
-
-static inline bool buf_is_empty(cyclic_buffer_t *buf)
-{
-	return buf->cnt == 0;
-}
-
-static inline uint8_t buf_pop_front(cyclic_buffer_t *buf)
-{
-	assert(!buf_is_empty(buf));
-	
-	uint8_t res = buf->buf[buf->start];
-	buf->start = (buf->start + 1) % BUF_LEN;
-	buf->cnt--;
-	return res;
-}
-
-static inline void buf_clear(cyclic_buffer_t *buf)
-{
-	buf->cnt = 0;
-}
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/ns8250/ns8250.c
===================================================================
--- uspace/drv/ns8250/ns8250.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,958 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @defgroup ns8250 Serial port driver.
- * @brief HelenOS serial port driver.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <ctype.h>
-#include <macros.h>
-#include <malloc.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-
-#include <ddf/driver.h>
-#include <ddf/interrupt.h>
-#include <ops/char_dev.h>
-
-#include <devman.h>
-#include <ipc/devman.h>
-#include <device/hw_res.h>
-#include <ipc/serial_ctl.h>
-
-#include "cyclic_buffer.h"
-
-#define NAME "ns8250"
-
-#define REG_COUNT 7
-#define MAX_BAUD_RATE 115200
-#define DLAB_MASK (1 << 7)
-
-/** Obtain soft-state structure from function node */
-#define NS8250(fnode) ((ns8250_t *) ((fnode)->dev->driver_data))
-
-/** Obtain soft-state structure from device node */
-#define NS8250_FROM_DEV(dnode) ((ns8250_t *) ((dnode)->driver_data))
-
-/** The number of bits of one data unit send by the serial port. */
-typedef enum {
-	WORD_LENGTH_5,
-	WORD_LENGTH_6,
-	WORD_LENGTH_7,
-	WORD_LENGTH_8
-} word_length_t;
-
-/** The number of stop bits used by the serial port. */
-typedef enum {
-	/** Use one stop bit. */
-	ONE_STOP_BIT,
-	/** 1.5 stop bits for word length 5, 2 stop bits otherwise. */
-	TWO_STOP_BITS
-} stop_bit_t;
-
-/** The driver data for the serial port devices. */
-typedef struct ns8250 {
-	/** DDF device node */
-	ddf_dev_t *dev;
-	/** DDF function node */
-	ddf_fun_t *fun;
-	/** Is there any client conntected to the device? */
-	bool client_connected;
-	/** The irq assigned to this device. */
-	int irq;
-	/** The base i/o address of the devices registers. */
-	uint32_t io_addr;
-	/** The i/o port used to access the serial ports registers. */
-	ioport8_t *port;
-	/** The buffer for incomming data. */
-	cyclic_buffer_t input_buffer;
-	/** The fibril mutex for synchronizing the access to the device. */
-	fibril_mutex_t mutex;
-} ns8250_t;
-
-/** Create per-device soft-state structure.
- *
- * @return	Pointer to soft-state structure.
- */
-static ns8250_t *ns8250_new(void)
-{
-	ns8250_t *ns;
-	
-	ns = (ns8250_t *) calloc(1, sizeof(ns8250_t));
-	if (ns == NULL)
-		return NULL;
-	
-	fibril_mutex_initialize(&ns->mutex);
-	return ns;
-}
-
-/** Delete soft-state structure.
- *
- * @param ns	The driver data structure.
- */
-static void ns8250_delete(ns8250_t *ns)
-{
-	assert(ns != NULL);
-	free(ns);
-}
-
-/** Find out if there is some incomming data available on the serial port.
- *
- * @param port		The base address of the serial port device's ports.
- * @return		True if there are data waiting to be read, false
- *			otherwise.
- */
-static bool ns8250_received(ioport8_t *port)
-{
-	return (pio_read_8(port + 5) & 1) != 0;
-}
-
-/** Read one byte from the serial port.
- *
- * @param port		The base address of the serial port device's ports.
- * @return		The data read.
- */
-static uint8_t ns8250_read_8(ioport8_t *port)
-{
-	return pio_read_8(port);
-}
-
-/** Find out wheter it is possible to send data.
- *
- * @param port		The base address of the serial port device's ports.
- */
-static bool is_transmit_empty(ioport8_t *port)
-{
-	return (pio_read_8(port + 5) & 0x20) != 0;
-}
-
-/** Write one character on the serial port.
- *
- * @param port		The base address of the serial port device's ports.
- * @param c		The character to be written to the serial port device.
- */
-static void ns8250_write_8(ioport8_t *port, uint8_t c)
-{
-	while (!is_transmit_empty(port))
-		;
-	
-	pio_write_8(port, c);
-}
-
-/** Read data from the serial port device.
- *
- * @param fun		The serial port function
- * @param buf		The ouput buffer for read data.
- * @param count		The number of bytes to be read.
- *
- * @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 = NS8250(fun);
-	int ret = EOK;
-	
-	fibril_mutex_lock(&ns->mutex);
-	while (!buf_is_empty(&ns->input_buffer) && (size_t)ret < count) {
-		buf[ret] = (char)buf_pop_front(&ns->input_buffer);
-		ret++;
-	}
-	fibril_mutex_unlock(&ns->mutex);
-	
-	return ret;
-}
-
-/** Write a character to the serial port.
- *
- * @param ns		Serial port device
- * @param c		The character to be written
- */
-static inline void ns8250_putchar(ns8250_t *ns, uint8_t c)
-{
-	fibril_mutex_lock(&ns->mutex);
-	ns8250_write_8(ns->port, c);
-	fibril_mutex_unlock(&ns->mutex);
-}
-
-/** Write data to the serial port.
- *
- * @param fun		The serial port function
- * @param buf		The data to be written
- * @param count		The number of bytes to be written
- * @return		Zero on success
- */
-static int ns8250_write(ddf_fun_t *fun, char *buf, size_t count)
-{
-	ns8250_t *ns = NS8250(fun);
-	size_t idx;
-	
-	for (idx = 0; idx < count; idx++)
-		ns8250_putchar(ns, (uint8_t) buf[idx]);
-	
-	return 0;
-}
-
-static ddf_dev_ops_t ns8250_dev_ops;
-
-/** The character interface's callbacks. */
-static char_dev_ops_t ns8250_char_dev_ops = {
-	.read = &ns8250_read,
-	.write = &ns8250_write
-};
-
-static int ns8250_add_device(ddf_dev_t *dev);
-
-/** The serial port device driver's standard operations. */
-static driver_ops_t ns8250_ops = {
-	.add_device = &ns8250_add_device
-};
-
-/** The serial port device driver structure. */
-static driver_t ns8250_driver = {
-	.name = NAME,
-	.driver_ops = &ns8250_ops
-};
-
-/** Clean up the serial port soft-state
- *
- * @param ns		Serial port device
- */
-static void ns8250_dev_cleanup(ns8250_t *ns)
-{
-	if (ns->dev->parent_phone > 0) {
-		async_hangup(ns->dev->parent_phone);
-		ns->dev->parent_phone = 0;
-	}
-}
-
-/** Enable the i/o ports of the device.
- *
- * @param ns		Serial port device
- * @return		True on success, false otherwise
- */
-static bool ns8250_pio_enable(ns8250_t *ns)
-{
-	printf(NAME ": ns8250_pio_enable %s\n", ns->dev->name);
-	
-	/* Gain control over port's registers. */
-	if (pio_enable((void *)(uintptr_t) ns->io_addr, REG_COUNT,
-	    (void **) &ns->port)) {
-		printf(NAME ": error - cannot gain the port %#" PRIx32 " for device "
-		    "%s.\n", ns->io_addr, ns->dev->name);
-		return false;
-	}
-	
-	return true;
-}
-
-/** Probe the serial port device for its presence.
- *
- * @param ns		Serial port device
- * @return		True if the device is present, false otherwise
- */
-static bool ns8250_dev_probe(ns8250_t *ns)
-{
-	printf(NAME ": ns8250_dev_probe %s\n", ns->dev->name);
-	
-	ioport8_t *port_addr = ns->port;
-	bool res = true;
-	uint8_t olddata;
-	
-	olddata = pio_read_8(port_addr + 4);
-	
-	pio_write_8(port_addr + 4, 0x10);
-	if (pio_read_8(port_addr + 6) & 0xf0)
-		res = false;
-	
-	pio_write_8(port_addr + 4, 0x1f);
-	if ((pio_read_8(port_addr + 6) & 0xf0) != 0xf0)
-		res = false;
-	
-	pio_write_8(port_addr + 4, olddata);
-	
-	if (!res)
-		printf(NAME ": device %s is not present.\n", ns->dev->name);
-	
-	return res;
-}
-
-/** Initialize serial port device.
- *
- * @param ns		Serial port device
- * @return		Zero on success, negative error number otherwise
- */
-static int ns8250_dev_initialize(ns8250_t *ns)
-{
-	printf(NAME ": ns8250_dev_initialize %s\n", ns->dev->name);
-	
-	int ret = EOK;
-	
-	hw_resource_list_t hw_resources;
-	memset(&hw_resources, 0, sizeof(hw_resource_list_t));
-	
-	/* Connect to the parent's driver. */
-	ns->dev->parent_phone = devman_parent_device_connect(ns->dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (ns->dev->parent_phone < 0) {
-		printf(NAME ": failed to connect to the parent driver of the "
-		    "device %s.\n", ns->dev->name);
-		ret = ns->dev->parent_phone;
-		goto failed;
-	}
-	
-	/* Get hw resources. */
-	ret = hw_res_get_resource_list(ns->dev->parent_phone, &hw_resources);
-	if (ret != EOK) {
-		printf(NAME ": failed to get hw resources for the device "
-		    "%s.\n", ns->dev->name);
-		goto failed;
-	}
-	
-	size_t i;
-	hw_resource_t *res;
-	bool irq = false;
-	bool ioport = false;
-	
-	for (i = 0; i < hw_resources.count; i++) {
-		res = &hw_resources.resources[i];
-		switch (res->type) {
-		case INTERRUPT:
-			ns->irq = res->res.interrupt.irq;
-			irq = true;
-			printf(NAME ": the %s device was asigned irq = 0x%x.\n",
-			    ns->dev->name, ns->irq);
-			break;
-			
-		case IO_RANGE:
-			ns->io_addr = res->res.io_range.address;
-			if (res->res.io_range.size < REG_COUNT) {
-				printf(NAME ": i/o range assigned to the device "
-				    "%s is too small.\n", ns->dev->name);
-				ret = ELIMIT;
-				goto failed;
-			}
-			ioport = true;
-			printf(NAME ": the %s device was asigned i/o address = "
-			    "0x%x.\n", ns->dev->name, ns->io_addr);
-			break;
-			
-		default:
-			break;
-		}
-	}
-	
-	if (!irq || !ioport) {
-		printf(NAME ": missing hw resource(s) for the device %s.\n",
-		    ns->dev->name);
-		ret = ENOENT;
-		goto failed;
-	}
-	
-	hw_res_clean_resource_list(&hw_resources);
-	return ret;
-	
-failed:
-	ns8250_dev_cleanup(ns);
-	hw_res_clean_resource_list(&hw_resources);
-	return ret;
-}
-
-/** Enable interrupts on the serial port device.
- *
- * Interrupt when data is received
- *
- * @param port		The base address of the serial port device's ports.
- */
-static inline void ns8250_port_interrupts_enable(ioport8_t *port)
-{
-	pio_write_8(port + 1, 0x1);	/* Interrupt when data received. */
-	pio_write_8(port + 4, 0xB);
-}
-
-/** Disable interrupts on the serial port device.
- *
- * @param port		The base address of the serial port device's ports
- */
-static inline void ns8250_port_interrupts_disable(ioport8_t *port)
-{
-	pio_write_8(port + 1, 0x0);	/* Disable all interrupts. */
-}
-
-/** Enable interrupts for the serial port device.
- *
- * @param ns		Serial port device
- * @return		Zero on success, negative error number otherwise
- */
-static int ns8250_interrupt_enable(ns8250_t *ns)
-{
-	/* Enable interrupt on the serial port. */
-	ns8250_port_interrupts_enable(ns->port);
-	
-	return EOK;
-}
-
-/** Set Divisor Latch Access Bit.
- *
- * When the Divisor Latch Access Bit is set, it is possible to set baud rate of
- * the serial port device.
- *
- * @param port		The base address of the serial port device's ports.
- */
-static inline void enable_dlab(ioport8_t *port)
-{
-	uint8_t val = pio_read_8(port + 3);
-	pio_write_8(port + 3, val | DLAB_MASK);
-}
-
-/** Clear Divisor Latch Access Bit.
- *
- * @param port		The base address of the serial port device's ports.
- */
-static inline void clear_dlab(ioport8_t *port)
-{
-	uint8_t val = pio_read_8(port + 3);
-	pio_write_8(port + 3, val & (~DLAB_MASK));
-}
-
-/** Set baud rate of the serial communication on the serial device.
- *
- * @param port		The base address of the serial port device's ports.
- * @param baud_rate	The baud rate to be used by the device.
- * @return		Zero on success, negative error number otherwise (EINVAL
- *			if the specified baud_rate is not valid).
- */
-static int ns8250_port_set_baud_rate(ioport8_t *port, unsigned int baud_rate)
-{
-	uint16_t divisor;
-	uint8_t div_low, div_high;
-	
-	if (baud_rate < 50 || MAX_BAUD_RATE % baud_rate != 0) {
-		printf(NAME ": error - somebody tried to set invalid baud rate "
-		    "%d\n", baud_rate);
-		return EINVAL;
-	}
-	
-	divisor = MAX_BAUD_RATE / baud_rate;
-	div_low = (uint8_t)divisor;
-	div_high = (uint8_t)(divisor >> 8);
-	
-	/* Enable DLAB to be able to access baud rate divisor. */
-	enable_dlab(port);
-	
-	/* Set divisor low byte. */
-	pio_write_8(port + 0, div_low);
-	/* Set divisor high byte. */
-	pio_write_8(port + 1, div_high);
-	
-	clear_dlab(port);
-	
-	return EOK;
-}
-
-/** Get baud rate used by the serial port device.
- *
- * @param port		The base address of the serial port device's ports.
- * @param baud_rate	The ouput parameter to which the baud rate is stored.
- */
-static unsigned int ns8250_port_get_baud_rate(ioport8_t *port)
-{
-	uint16_t divisor;
-	uint8_t div_low, div_high;
-	
-	/* Enable DLAB to be able to access baud rate divisor. */
-	enable_dlab(port);
-	
-	/* Get divisor low byte. */
-	div_low = pio_read_8(port + 0);
-	/* Get divisor high byte. */
-	div_high = pio_read_8(port + 1);
-	
-	clear_dlab(port);
-	
-	divisor = (div_high << 8) | div_low;
-	return MAX_BAUD_RATE / divisor;
-}
-
-/** Get the parameters of the serial communication set on the serial port
- * device.
- *
- * @param parity	The parity used.
- * @param word_length	The length of one data unit in bits.
- * @param stop_bits	The number of stop bits used (one or two).
- */
-static void ns8250_port_get_com_props(ioport8_t *port, unsigned int *parity,
-    unsigned int *word_length, unsigned int *stop_bits)
-{
-	uint8_t val;
-	
-	val = pio_read_8(port + 3);
-	*parity = ((val >> 3) & 7);
-	
-	switch (val & 3) {
-	case WORD_LENGTH_5:
-		*word_length = 5;
-		break;
-	case WORD_LENGTH_6:
-		*word_length = 6;
-		break;
-	case WORD_LENGTH_7:
-		*word_length = 7;
-		break;
-	case WORD_LENGTH_8:
-		*word_length = 8;
-		break;
-	}
-	
-	if ((val >> 2) & 1)
-		*stop_bits = 2;
-	else
-		*stop_bits = 1;
-}
-
-/** Set the parameters of the serial communication on the serial port device.
- *
- * @param parity	The parity to be used.
- * @param word_length	The length of one data unit in bits.
- * @param stop_bits	The number of stop bits used (one or two).
- * @return		Zero on success, EINVAL if some of the specified values
- *			is invalid.
- */
-static int ns8250_port_set_com_props(ioport8_t *port, unsigned int parity,
-    unsigned int word_length, unsigned int stop_bits)
-{
-	uint8_t val;
-	
-	switch (word_length) {
-	case 5:
-		val = WORD_LENGTH_5;
-		break;
-	case 6:
-		val = WORD_LENGTH_6;
-		break;
-	case 7:
-		val = WORD_LENGTH_7;
-		break;
-	case 8:
-		val = WORD_LENGTH_8;
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	switch (stop_bits) {
-	case 1:
-		val |= ONE_STOP_BIT << 2;
-		break;
-	case 2:
-		val |= TWO_STOP_BITS << 2;
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	switch (parity) {
-	case SERIAL_NO_PARITY:
-	case SERIAL_ODD_PARITY:
-	case SERIAL_EVEN_PARITY:
-	case SERIAL_MARK_PARITY:
-	case SERIAL_SPACE_PARITY:
-		val |= parity << 3;
-		break;
-	default:
-		return EINVAL;
-	}
-	
-	pio_write_8(port + 3, val);
-	
-	return EOK;
-}
-
-/** Initialize the serial port device.
- *
- * Set the default parameters of the serial communication.
- *
- * @param ns		Serial port device
- */
-static void ns8250_initialize_port(ns8250_t *ns)
-{
-	ioport8_t *port = ns->port;
-	
-	/* Disable interrupts. */
-	ns8250_port_interrupts_disable(port);
-	/* Set baud rate. */
-	ns8250_port_set_baud_rate(port, 38400);
-	/* 8 bits, no parity, two stop bits. */
-	ns8250_port_set_com_props(port, SERIAL_NO_PARITY, 8, 2);
-	/* Enable FIFO, clear them, with 14-byte threshold. */
-	pio_write_8(port + 2, 0xC7);
-	/*
-	 * RTS/DSR set (Request to Send and Data Terminal Ready lines enabled),
-	 * Aux Output2 set - needed for interrupts.
-	 */
-	pio_write_8(port + 4, 0x0B);
-}
-
-/** Read the data from the serial port device and store them to the input
- * buffer.
- *
- * @param ns		Serial port device
- */
-static void ns8250_read_from_device(ns8250_t *ns)
-{
-	ioport8_t *port = ns->port;
-	bool cont = true;
-	
-	while (cont) {
-		fibril_mutex_lock(&ns->mutex);
-		
-		cont = ns8250_received(port);
-		if (cont) {
-			uint8_t val = ns8250_read_8(port);
-			
-			if (ns->client_connected) {
-				if (!buf_push_back(&ns->input_buffer, val)) {
-					printf(NAME ": buffer overflow on "
-					    "%s.\n", ns->dev->name);
-				} else {
-					printf(NAME ": the character %c saved "
-					    "to the buffer of %s.\n",
-					    val, ns->dev->name);
-				}
-			}
-		}
-		
-		fibril_mutex_unlock(&ns->mutex);
-		fibril_yield();
-	}
-}
-
-/** The interrupt handler.
- *
- * The serial port is initialized to interrupt when some data come, so the
- * interrupt is handled by reading the incomming data.
- *
- * @param dev		The serial port device.
- */
-static inline void ns8250_interrupt_handler(ddf_dev_t *dev, ipc_callid_t iid,
-    ipc_call_t *icall)
-{
-	ns8250_read_from_device(NS8250_FROM_DEV(dev));
-}
-
-/** Register the interrupt handler for the device.
- *
- * @param ns		Serial port device
- */
-static inline int ns8250_register_interrupt_handler(ns8250_t *ns)
-{
-	return register_interrupt_handler(ns->dev, ns->irq,
-	    ns8250_interrupt_handler, NULL);
-}
-
-/** Unregister the interrupt handler for the device.
- *
- * @param ns		Serial port device
- */
-static inline int ns8250_unregister_interrupt_handler(ns8250_t *ns)
-{
-	return unregister_interrupt_handler(ns->dev, ns->irq);
-}
-
-/** The add_device callback method of the serial port driver.
- *
- * Probe and initialize the newly added device.
- *
- * @param dev		The serial port device.
- */
-static int ns8250_add_device(ddf_dev_t *dev)
-{
-	ns8250_t *ns = NULL;
-	ddf_fun_t *fun = NULL;
-	bool need_cleanup = false;
-	int rc;
-	
-	printf(NAME ": ns8250_add_device %s (handle = %d)\n",
-	    dev->name, (int) dev->handle);
-	
-	/* Allocate soft-state for the device */
-	ns = ns8250_new();
-	if (ns == NULL) {
-		rc = ENOMEM;
-		goto fail;
-	}
-	
-	ns->dev = dev;
-	dev->driver_data = ns;
-	
-	rc = ns8250_dev_initialize(ns);
-	if (rc != EOK)
-		goto fail;
-	
-	need_cleanup = true;
-	
-	if (!ns8250_pio_enable(ns)) {
-		rc = EADDRNOTAVAIL;
-		goto fail;
-	}
-	
-	/* Find out whether the device is present. */
-	if (!ns8250_dev_probe(ns)) {
-		rc = ENOENT;
-		goto fail;
-	}
-	
-	/* Serial port initialization (baud rate etc.). */
-	ns8250_initialize_port(ns);
-	
-	/* Register interrupt handler. */
-	if (ns8250_register_interrupt_handler(ns) != EOK) {
-		printf(NAME ": failed to register interrupt handler.\n");
-		rc = EADDRNOTAVAIL;
-		goto fail;
-	}
-	
-	/* Enable interrupt. */
-	rc = ns8250_interrupt_enable(ns);
-	if (rc != EOK) {
-		printf(NAME ": failed to enable the interrupt. Error code = "
-		    "%d.\n", rc);
-		goto fail;
-	}
-	
-	fun = ddf_fun_create(dev, fun_exposed, "a");
-	if (fun == NULL) {
-		printf(NAME ": error creating function.\n");
-		goto fail;
-	}
-	
-	/* Set device operations. */
-	fun->ops = &ns8250_dev_ops;
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		printf(NAME ": error binding function.\n");
-		goto fail;
-	}
-
-	ns->fun = fun;
-	
-	ddf_fun_add_to_class(fun, "serial");
-	
-	printf(NAME ": the %s device has been successfully initialized.\n",
-	    dev->name);
-	
-	return EOK;
-fail:
-	if (fun != NULL)
-		ddf_fun_destroy(fun);
-	if (need_cleanup)
-		ns8250_dev_cleanup(ns);
-	if (ns != NULL)
-		ns8250_delete(ns);
-	return rc;
-}
-
-/** Open the device.
- *
- * This is a callback function called when a client tries to connect to the
- * device.
- *
- * @param dev		The device.
- */
-static int ns8250_open(ddf_fun_t *fun)
-{
-	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
-	int res;
-	
-	fibril_mutex_lock(&data->mutex);
-	if (data->client_connected) {
-		res = ELIMIT;
-	} else {
-		res = EOK;
-		data->client_connected = true;
-	}
-	fibril_mutex_unlock(&data->mutex);
-	
-	return res;
-}
-
-/** Close the device.
- *
- * This is a callback function called when a client tries to disconnect from
- * the device.
- *
- * @param dev		The device.
- */
-static void ns8250_close(ddf_fun_t *fun)
-{
-	ns8250_t *data = (ns8250_t *) fun->dev->driver_data;
-	
-	fibril_mutex_lock(&data->mutex);
-	
-	assert(data->client_connected);
-	
-	data->client_connected = false;
-	buf_clear(&data->input_buffer);
-	
-	fibril_mutex_unlock(&data->mutex);
-}
-
-/** Get parameters of the serial communication which are set to the specified
- * device.
- *
- * @param dev		The serial port device.
- * @param baud_rate	The baud rate used by the device.
- * @param parity	The type of parity used by the device.
- * @param word_length	The size of one data unit in bits.
- * @param stop_bits	The number of stop bits used.
- */
-static void
-ns8250_get_props(ddf_dev_t *dev, unsigned int *baud_rate, unsigned int *parity,
-    unsigned int *word_length, unsigned int* stop_bits)
-{
-	ns8250_t *data = (ns8250_t *) dev->driver_data;
-	ioport8_t *port = data->port;
-	
-	fibril_mutex_lock(&data->mutex);
-	ns8250_port_interrupts_disable(port);
-	*baud_rate = ns8250_port_get_baud_rate(port);
-	ns8250_port_get_com_props(port, parity, word_length, stop_bits);
-	ns8250_port_interrupts_enable(port);
-	fibril_mutex_unlock(&data->mutex);
-	
-	printf(NAME ": ns8250_get_props: baud rate %d, parity 0x%x, word "
-	    "length %d, stop bits %d\n", *baud_rate, *parity, *word_length,
-	    *stop_bits);
-}
-
-/** Set parameters of the serial communication to the specified serial port
- * device.
- *
- * @param dev		The serial port device.
- * @param baud_rate	The baud rate to be used by the device.
- * @param parity	The type of parity to be used by the device.
- * @param word_length	The size of one data unit in bits.
- * @param stop_bits	The number of stop bits to be used.
- */
-static int ns8250_set_props(ddf_dev_t *dev, unsigned int baud_rate,
-    unsigned int parity, unsigned int word_length, unsigned int stop_bits)
-{
-	printf(NAME ": ns8250_set_props: baud rate %d, parity 0x%x, word "
-	    "length %d, stop bits %d\n", baud_rate, parity, word_length,
-	    stop_bits);
-	
-	ns8250_t *data = (ns8250_t *) dev->driver_data;
-	ioport8_t *port = data->port;
-	int ret;
-	
-	fibril_mutex_lock(&data->mutex);
-	ns8250_port_interrupts_disable(port);
-	ret = ns8250_port_set_baud_rate(port, baud_rate);
-	if (ret == EOK)
-		ret = ns8250_port_set_com_props(port, parity, word_length, stop_bits);
-	ns8250_port_interrupts_enable(port);
-	fibril_mutex_unlock(&data->mutex);
-	
-	return ret;
-}
-
-/** Default handler for client requests which are not handled by the standard
- * interfaces.
- *
- * Configure the parameters of the serial communication.
- */
-static void ns8250_default_handler(ddf_fun_t *fun, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	sysarg_t method = IPC_GET_IMETHOD(*call);
-	int ret;
-	unsigned int baud_rate, parity, word_length, stop_bits;
-	
-	switch (method) {
-	case SERIAL_GET_COM_PROPS:
-		ns8250_get_props(fun->dev, &baud_rate, &parity, &word_length,
-		    &stop_bits);
-		async_answer_4(callid, EOK, baud_rate, parity, word_length,
-		    stop_bits);
-		break;
-		
-	case SERIAL_SET_COM_PROPS:
- 		baud_rate = IPC_GET_ARG1(*call);
-		parity = IPC_GET_ARG2(*call);
-		word_length = IPC_GET_ARG3(*call);
-		stop_bits = IPC_GET_ARG4(*call);
-		ret = ns8250_set_props(fun->dev, baud_rate, parity, word_length,
-		    stop_bits);
-		async_answer_0(callid, ret);
-		break;
-		
-	default:
-		async_answer_0(callid, ENOTSUP);
-	}
-}
-
-/** Initialize the serial port driver.
- *
- * Initialize device operations structures with callback methods for handling
- * client requests to the serial port devices.
- */
-static void ns8250_init(void)
-{
-	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;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS serial port driver\n");
-	ns8250_init();
-	return ddf_driver_main(&ns8250_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/ns8250/ns8250.ma
===================================================================
--- uspace/drv/ns8250/ns8250.ma	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 isa/ns8250
Index: pace/drv/pciintel/Makefile
===================================================================
--- uspace/drv/pciintel/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = pciintel
-
-SOURCES = \
-	pci.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,640 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @defgroup pciintel pci bus driver for intel method 1.
- * @brief HelenOS root pci bus driver for intel method 1.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <str.h>
-#include <ctype.h>
-#include <macros.h>
-#include <str_error.h>
-
-#include <ddf/driver.h>
-#include <devman.h>
-#include <ipc/devman.h>
-#include <ipc/dev_iface.h>
-#include <ops/hw_res.h>
-#include <device/hw_res.h>
-#include <ddi.h>
-#include <libarch/ddi.h>
-
-#include "pci.h"
-
-#define NAME "pciintel"
-
-#define CONF_ADDR(bus, dev, fn, reg) \
-	((1 << 31) | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
-
-/** Obtain PCI function soft-state from DDF function node */
-#define PCI_FUN(fnode) ((pci_fun_t *) (fnode)->driver_data)
-
-/** Obtain PCI bus soft-state from DDF device node */
-#define PCI_BUS(dnode) ((pci_bus_t *) (dnode)->driver_data)
-
-/** Obtain PCI bus soft-state from function soft-state */
-#define PCI_BUS_FROM_FUN(fun) ((fun)->busptr)
-
-static hw_resource_list_t *pciintel_get_resources(ddf_fun_t *fnode)
-{
-	pci_fun_t *fun = PCI_FUN(fnode);
-	
-	if (fun == NULL)
-		return NULL;
-	return &fun->hw_resources;
-}
-
-static bool pciintel_enable_interrupt(ddf_fun_t *fnode)
-{
-	/* TODO */
-	
-	return false;
-}
-
-static hw_res_ops_t pciintel_hw_res_ops = {
-	&pciintel_get_resources,
-	&pciintel_enable_interrupt
-};
-
-static ddf_dev_ops_t pci_fun_ops;
-
-static int pci_add_device(ddf_dev_t *);
-
-/** PCI bus driver standard operations */
-static driver_ops_t pci_ops = {
-	.add_device = &pci_add_device
-};
-
-/** PCI bus driver structure */
-static driver_t pci_driver = {
-	.name = NAME,
-	.driver_ops = &pci_ops
-};
-
-static pci_bus_t *pci_bus_new(void)
-{
-	pci_bus_t *bus;
-	
-	bus = (pci_bus_t *) calloc(1, sizeof(pci_bus_t));
-	if (bus == NULL)
-		return NULL;
-	
-	fibril_mutex_initialize(&bus->conf_mutex);
-	return bus;
-}
-
-static void pci_bus_delete(pci_bus_t *bus)
-{
-	assert(bus != NULL);
-	free(bus);
-}
-
-static void pci_conf_read(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
-{
-	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
-	
-	fibril_mutex_lock(&bus->conf_mutex);
-	
-	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
-	void *addr = bus->conf_data_port + (reg & 3);
-	
-	pio_write_32(bus->conf_addr_port, conf_addr);
-	
-	switch (len) {
-	case 1:
-		buf[0] = pio_read_8(addr);
-		break;
-	case 2:
-		((uint16_t *) buf)[0] = pio_read_16(addr);
-		break;
-	case 4:
-		((uint32_t *) buf)[0] = pio_read_32(addr);
-		break;
-	}
-	
-	fibril_mutex_unlock(&bus->conf_mutex);
-}
-
-static void pci_conf_write(pci_fun_t *fun, int reg, uint8_t *buf, size_t len)
-{
-	pci_bus_t *bus = PCI_BUS_FROM_FUN(fun);
-	
-	fibril_mutex_lock(&bus->conf_mutex);
-	
-	uint32_t conf_addr;
-	conf_addr = CONF_ADDR(fun->bus, fun->dev, fun->fn, reg);
-	void *addr = bus->conf_data_port + (reg & 3);
-	
-	pio_write_32(bus->conf_addr_port, conf_addr);
-	
-	switch (len) {
-	case 1:
-		pio_write_8(addr, buf[0]);
-		break;
-	case 2:
-		pio_write_16(addr, ((uint16_t *) buf)[0]);
-		break;
-	case 4:
-		pio_write_32(addr, ((uint32_t *) buf)[0]);
-		break;
-	}
-	
-	fibril_mutex_unlock(&bus->conf_mutex);
-}
-
-uint8_t pci_conf_read_8(pci_fun_t *fun, int reg)
-{
-	uint8_t res;
-	pci_conf_read(fun, reg, &res, 1);
-	return res;
-}
-
-uint16_t pci_conf_read_16(pci_fun_t *fun, int reg)
-{
-	uint16_t res;
-	pci_conf_read(fun, reg, (uint8_t *) &res, 2);
-	return res;
-}
-
-uint32_t pci_conf_read_32(pci_fun_t *fun, int reg)
-{
-	uint32_t res;
-	pci_conf_read(fun, reg, (uint8_t *) &res, 4);
-	return res;
-}
-
-void pci_conf_write_8(pci_fun_t *fun, int reg, uint8_t val)
-{
-	pci_conf_write(fun, reg, (uint8_t *) &val, 1);
-}
-
-void pci_conf_write_16(pci_fun_t *fun, int reg, uint16_t val)
-{
-	pci_conf_write(fun, reg, (uint8_t *) &val, 2);
-}
-
-void pci_conf_write_32(pci_fun_t *fun, int reg, uint32_t val)
-{
-	pci_conf_write(fun, reg, (uint8_t *) &val, 4);
-}
-
-void pci_fun_create_match_ids(pci_fun_t *fun)
-{
-	char *match_id_str;
-	int rc;
-	
-	asprintf(&match_id_str, "pci/ven=%04x&dev=%04x",
-	    fun->vendor_id, fun->device_id);
-
-	if (match_id_str == NULL) {
-		printf(NAME ": out of memory creating match ID.\n");
-		return;
-	}
-
-	rc = ddf_fun_add_match_id(fun->fnode, match_id_str, 90);
-	if (rc != EOK) {
-		printf(NAME ": error adding match ID: %s\n",
-		    str_error(rc));
-	}
-	
-	/* TODO add more ids (with subsys ids, using class id etc.) */
-}
-
-void pci_add_range(pci_fun_t *fun, uint64_t range_addr, size_t range_size,
-    bool io)
-{
-	hw_resource_list_t *hw_res_list = &fun->hw_resources;
-	hw_resource_t *hw_resources =  hw_res_list->resources;
-	size_t count = hw_res_list->count;
-	
-	assert(hw_resources != NULL);
-	assert(count < PCI_MAX_HW_RES);
-	
-	if (io) {
-		hw_resources[count].type = IO_RANGE;
-		hw_resources[count].res.io_range.address = range_addr;
-		hw_resources[count].res.io_range.size = range_size;
-		hw_resources[count].res.io_range.endianness = LITTLE_ENDIAN;
-	} else {
-		hw_resources[count].type = MEM_RANGE;
-		hw_resources[count].res.mem_range.address = range_addr;
-		hw_resources[count].res.mem_range.size = range_size;
-		hw_resources[count].res.mem_range.endianness = LITTLE_ENDIAN;
-	}
-	
-	hw_res_list->count++;
-}
-
-/** Read the base address register (BAR) of the device and if it contains valid
- * address add it to the devices hw resource list.
- *
- * @param fun	PCI function
- * @param addr	The address of the BAR in the PCI configuration address space of
- *		the device
- * @return	The addr the address of the BAR which should be read next
- */
-int pci_read_bar(pci_fun_t *fun, int addr)
-{
-	/* Value of the BAR */
-	uint32_t val, mask;
-	/* IO space address */
-	bool io;
-	/* 64-bit wide address */
-	bool addrw64;
-	
-	/* Size of the io or memory range specified by the BAR */
-	size_t range_size;
-	/* Beginning of the io or memory range specified by the BAR */
-	uint64_t range_addr;
-	
-	/* Get the value of the BAR. */
-	val = pci_conf_read_32(fun, addr);
-	
-	io = (bool) (val & 1);
-	if (io) {
-		addrw64 = false;
-	} else {
-		switch ((val >> 1) & 3) {
-		case 0:
-			addrw64 = false;
-			break;
-		case 2:
-			addrw64 = true;
-			break;
-		default:
-			/* reserved, go to the next BAR */
-			return addr + 4;
-		}
-	}
-	
-	/* Get the address mask. */
-	pci_conf_write_32(fun, addr, 0xffffffff);
-	mask = pci_conf_read_32(fun, addr);
-	
-	/* Restore the original value. */
-	pci_conf_write_32(fun, addr, val);
-	val = pci_conf_read_32(fun, addr);
-	
-	range_size = pci_bar_mask_to_size(mask);
-	
-	if (addrw64) {
-		range_addr = ((uint64_t)pci_conf_read_32(fun, addr + 4) << 32) |
-		    (val & 0xfffffff0);
-	} else {
-		range_addr = (val & 0xfffffff0);
-	}
-	
-	if (range_addr != 0) {
-		printf(NAME ": function %s : ", fun->fnode->name);
-		printf("address = %" PRIx64, range_addr);
-		printf(", size = %x\n", (unsigned int) range_size);
-	}
-	
-	pci_add_range(fun, range_addr, range_size, io);
-	
-	if (addrw64)
-		return addr + 8;
-	
-	return addr + 4;
-}
-
-void pci_add_interrupt(pci_fun_t *fun, int irq)
-{
-	hw_resource_list_t *hw_res_list = &fun->hw_resources;
-	hw_resource_t *hw_resources = hw_res_list->resources;
-	size_t count = hw_res_list->count;
-	
-	assert(NULL != hw_resources);
-	assert(count < PCI_MAX_HW_RES);
-	
-	hw_resources[count].type = INTERRUPT;
-	hw_resources[count].res.interrupt.irq = irq;
-	
-	hw_res_list->count++;
-	
-	printf(NAME ": function %s uses irq %x.\n", fun->fnode->name, irq);
-}
-
-void pci_read_interrupt(pci_fun_t *fun)
-{
-	uint8_t irq = pci_conf_read_8(fun, PCI_BRIDGE_INT_LINE);
-	if (irq != 0xff)
-		pci_add_interrupt(fun, irq);
-}
-
-/** Enumerate (recursively) and register the devices connected to a pci bus.
- *
- * @param bus		Host-to-PCI bridge
- * @param bus_num	Bus number
- */
-void pci_bus_scan(pci_bus_t *bus, int bus_num) 
-{
-	ddf_fun_t *fnode;
-	pci_fun_t *fun;
-	
-	int child_bus = 0;
-	int dnum, fnum;
-	bool multi;
-	uint8_t header_type;
-	
-	fun = pci_fun_new(bus);
-	
-	for (dnum = 0; dnum < 32; dnum++) {
-		multi = true;
-		for (fnum = 0; multi && fnum < 8; fnum++) {
-			pci_fun_init(fun, bus_num, dnum, fnum);
-			fun->vendor_id = pci_conf_read_16(fun,
-			    PCI_VENDOR_ID);
-			fun->device_id = pci_conf_read_16(fun,
-			    PCI_DEVICE_ID);
-			if (fun->vendor_id == 0xffff) {
-				/*
-				 * The device is not present, go on scanning the
-				 * bus.
-				 */
-				if (fnum == 0)
-					break;
-				else
-					continue;
-			}
-			
-			header_type = pci_conf_read_8(fun, PCI_HEADER_TYPE);
-			if (fnum == 0) {
-				/* Is the device multifunction? */
-				multi = header_type >> 7;
-			}
-			/* Clear the multifunction bit. */
-			header_type = header_type & 0x7F;
-			
-			char *fun_name = pci_fun_create_name(fun);
-			if (fun_name == NULL) {
-				printf(NAME ": out of memory.\n");
-				return;
-			}
-			
-			fnode = ddf_fun_create(bus->dnode, fun_inner, fun_name);
-			if (fnode == NULL) {
-				printf(NAME ": error creating function.\n");
-				return;
-			}
-			
-			free(fun_name);
-			fun->fnode = fnode;
-			
-			pci_alloc_resource_list(fun);
-			pci_read_bars(fun);
-			pci_read_interrupt(fun);
-			
-			fnode->ops = &pci_fun_ops;
-			fnode->driver_data = fun;
-			
-			printf(NAME ": adding new function %s.\n",
-			    fnode->name);
-			
-			pci_fun_create_match_ids(fun);
-			
-			if (ddf_fun_bind(fnode) != EOK) {
-				pci_clean_resource_list(fun);
-				clean_match_ids(&fnode->match_ids);
-				free((char *) fnode->name);
-				fnode->name = NULL;
-				continue;
-			}
-			
-			if (header_type == PCI_HEADER_TYPE_BRIDGE ||
-			    header_type == PCI_HEADER_TYPE_CARDBUS) {
-				child_bus = pci_conf_read_8(fun,
-				    PCI_BRIDGE_SEC_BUS_NUM);
-				printf(NAME ": device is pci-to-pci bridge, "
-				    "secondary bus number = %d.\n", bus_num);
-				if (child_bus > bus_num)
-					pci_bus_scan(bus, child_bus);
-			}
-			
-			fun = pci_fun_new(bus);
-		}
-	}
-	
-	if (fun->vendor_id == 0xffff) {
-		/* Free the auxiliary function structure. */
-		pci_fun_delete(fun);
-	}
-}
-
-static int pci_add_device(ddf_dev_t *dnode)
-{
-	pci_bus_t *bus = NULL;
-	ddf_fun_t *ctl = NULL;
-	bool got_res = false;
-	int rc;
-	
-	printf(NAME ": pci_add_device\n");
-	dnode->parent_phone = -1;
-	
-	bus = pci_bus_new();
-	if (bus == NULL) {
-		printf(NAME ": pci_add_device allocation failed.\n");
-		rc = ENOMEM;
-		goto fail;
-	}
-	bus->dnode = dnode;
-	dnode->driver_data = bus;
-	
-	dnode->parent_phone = devman_parent_device_connect(dnode->handle,
-	    IPC_FLAG_BLOCKING);
-	if (dnode->parent_phone < 0) {
-		printf(NAME ": pci_add_device failed to connect to the "
-		    "parent's driver.\n");
-		rc = dnode->parent_phone;
-		goto fail;
-	}
-	
-	hw_resource_list_t hw_resources;
-	
-	rc = hw_res_get_resource_list(dnode->parent_phone, &hw_resources);
-	if (rc != EOK) {
-		printf(NAME ": pci_add_device failed to get hw resources for "
-		    "the device.\n");
-		goto fail;
-	}
-	got_res = true;
-	
-	printf(NAME ": conf_addr = %" PRIx64 ".\n",
-	    hw_resources.resources[0].res.io_range.address);
-	
-	assert(hw_resources.count > 0);
-	assert(hw_resources.resources[0].type == IO_RANGE);
-	assert(hw_resources.resources[0].res.io_range.size == 8);
-	
-	bus->conf_io_addr =
-	    (uint32_t) hw_resources.resources[0].res.io_range.address;
-	
-	if (pio_enable((void *)(uintptr_t)bus->conf_io_addr, 8,
-	    &bus->conf_addr_port)) {
-		printf(NAME ": failed to enable configuration ports.\n");
-		rc = EADDRNOTAVAIL;
-		goto fail;
-	}
-	bus->conf_data_port = (char *) bus->conf_addr_port + 4;
-	
-	/* Make the bus device more visible. It has no use yet. */
-	printf(NAME ": adding a 'ctl' function\n");
-	
-	ctl = ddf_fun_create(bus->dnode, fun_exposed, "ctl");
-	if (ctl == NULL) {
-		printf(NAME ": error creating control function.\n");
-		rc = ENOMEM;
-		goto fail;
-	}
-	
-	rc = ddf_fun_bind(ctl);
-	if (rc != EOK) {
-		printf(NAME ": error binding control function.\n");
-		goto fail;
-	}
-	
-	/* Enumerate functions. */
-	printf(NAME ": scanning the bus\n");
-	pci_bus_scan(bus, 0);
-	
-	hw_res_clean_resource_list(&hw_resources);
-	
-	return EOK;
-	
-fail:
-	if (bus != NULL)
-		pci_bus_delete(bus);
-	if (dnode->parent_phone >= 0)
-		async_hangup(dnode->parent_phone);
-	if (got_res)
-		hw_res_clean_resource_list(&hw_resources);
-	if (ctl != NULL)
-		ddf_fun_destroy(ctl);
-
-	return rc;
-}
-
-static void pciintel_init(void)
-{
-	pci_fun_ops.interfaces[HW_RES_DEV_IFACE] = &pciintel_hw_res_ops;
-}
-
-pci_fun_t *pci_fun_new(pci_bus_t *bus)
-{
-	pci_fun_t *fun;
-	
-	fun = (pci_fun_t *) calloc(1, sizeof(pci_fun_t));
-	if (fun == NULL)
-		return NULL;
-
-	fun->busptr = bus;
-	return fun;
-}
-
-void pci_fun_init(pci_fun_t *fun, int bus, int dev, int fn)
-{
-	fun->bus = bus;
-	fun->dev = dev;
-	fun->fn = fn;
-}
-
-void pci_fun_delete(pci_fun_t *fun)
-{
-	assert(fun != NULL);
-	hw_res_clean_resource_list(&fun->hw_resources);
-	free(fun);
-}
-
-char *pci_fun_create_name(pci_fun_t *fun)
-{
-	char *name = NULL;
-	
-	asprintf(&name, "%02x:%02x.%01x", fun->bus, fun->dev,
-	    fun->fn);
-	return name;
-}
-
-bool pci_alloc_resource_list(pci_fun_t *fun)
-{
-	fun->hw_resources.resources =
-	    (hw_resource_t *) malloc(PCI_MAX_HW_RES * sizeof(hw_resource_t));
-	return fun->hw_resources.resources != NULL;
-}
-
-void pci_clean_resource_list(pci_fun_t *fun)
-{
-	if (fun->hw_resources.resources != NULL) {
-		free(fun->hw_resources.resources);
-		fun->hw_resources.resources = NULL;
-	}
-}
-
-/** Read the base address registers (BARs) of the function and add the addresses
- * to its HW resource list.
- *
- * @param fun	PCI function
- */
-void pci_read_bars(pci_fun_t *fun)
-{
-	/*
-	 * Position of the BAR in the PCI configuration address space of the
-	 * device.
-	 */
-	int addr = PCI_BASE_ADDR_0;
-	
-	while (addr <= PCI_BASE_ADDR_5)
-		addr = pci_read_bar(fun, addr);
-}
-
-size_t pci_bar_mask_to_size(uint32_t mask)
-{
-	return ((mask & 0xfffffff0) ^ 0xffffffff) + 1;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS pci bus driver (intel method 1).\n");
-	pciintel_init();
-	return ddf_driver_main(&pci_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/pciintel/pci.h
===================================================================
--- uspace/drv/pciintel/pci.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,96 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup pciintel
- * @{
- */
-/** @file
- */
-
-#ifndef PCI_H_
-#define PCI_H_
-
-#include <ddf/driver.h>
-#include "pci_regs.h"
-
-#define PCI_MAX_HW_RES 8
-
-typedef struct pciintel_bus {
-	/** DDF device node */
-	ddf_dev_t *dnode;
-	uint32_t conf_io_addr;
-	void *conf_data_port;
-	void *conf_addr_port;
-	fibril_mutex_t conf_mutex;
-} pci_bus_t;
-
-typedef struct pci_fun_data {
-	pci_bus_t *busptr;
-	ddf_fun_t *fnode;
-
-	int bus;
-	int dev;
-	int fn;
-	int vendor_id;
-	int device_id;
-	hw_resource_list_t hw_resources;
-} pci_fun_t;
-
-extern void pci_fun_create_match_ids(pci_fun_t *);
-
-extern uint8_t pci_conf_read_8(pci_fun_t *, int);
-extern uint16_t pci_conf_read_16(pci_fun_t *, int);
-extern uint32_t pci_conf_read_32(pci_fun_t *, int);
-extern void pci_conf_write_8(pci_fun_t *, int, uint8_t);
-extern void pci_conf_write_16(pci_fun_t *, int, uint16_t);
-extern void pci_conf_write_32(pci_fun_t *, int, uint32_t);
-
-extern void pci_add_range(pci_fun_t *, uint64_t, size_t, bool);
-extern int pci_read_bar(pci_fun_t *, int);
-extern void pci_read_interrupt(pci_fun_t *);
-extern void pci_add_interrupt(pci_fun_t *, int);
-
-extern pci_fun_t *pci_fun_new(pci_bus_t *);
-extern void pci_fun_init(pci_fun_t *, int, int, int);
-extern void pci_fun_delete(pci_fun_t *);
-extern char *pci_fun_create_name(pci_fun_t *);
-
-extern void pci_bus_scan(pci_bus_t *, int);
-
-extern bool pci_alloc_resource_list(pci_fun_t *);
-extern void pci_clean_resource_list(pci_fun_t *);
-
-extern void pci_read_bars(pci_fun_t *);
-extern size_t pci_bar_mask_to_size(uint32_t);
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/pciintel/pci_regs.h
===================================================================
--- uspace/drv/pciintel/pci_regs.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,101 +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 pciintel
- * @{
- */
-/** @file
- */
-
-#ifndef PCI_REGS_H_
-#define PCI_REGS_H_
-
-/* Header types */
-#define PCI_HEADER_TYPE_DEV	0
-#define PCI_HEADER_TYPE_BRIDGE	1
-#define PCI_HEADER_TYPE_CARDBUS	2
-
-/* Header type 0 and 1 */
-#define PCI_VENDOR_ID		0x00
-#define PCI_DEVICE_ID		0x02
-#define PCI_COMMAND		0x04
-#define PCI_STATUS		0x06
-#define PCI_REVISION_ID		0x08
-#define PCI_PROG_IF		0x09
-#define PCI_SUB_CLASS		0x0A
-#define PCI_BASE_CLASS		0x0B
-#define PCI_CACHE_LINE_SIZE	0x0C
-#define PCI_LATENCY_TIMER	0x0D
-#define PCI_HEADER_TYPE		0x0E
-#define PCI_BIST		0x0F
-
-#define PCI_BASE_ADDR_0		0x10
-#define PCI_BASE_ADDR_1		0x14
-
-/* Header type 0 */
-#define PCI_BASE_ADDR_2			0x18
-#define PCI_BASE_ADDR_3			0x1B
-#define PCI_BASE_ADDR_4			0x20
-#define PCI_BASE_ADDR_5			0x24
-
-#define PCI_CARDBUS_CIS_PTR		0x28
-#define PCI_SUBSYSTEM_VENDOR_ID		0x2C
-#define PCI_SUBSYSTEM_ID		0x2E
-#define PCI_EXP_ROM_BASE		0x30
-#define PCI_CAP_PTR			0x34
-#define PCI_INT_LINE			0x3C
-#define PCI_INT_PIN			0x3D
-#define PCI_MIN_GNT			0x3E
-#define PCI_MAX_LAT			0x3F
-
-/* Header type 1 */
-#define PCI_BRIDGE_PRIM_BUS_NUM		0x18
-#define PCI_BRIDGE_SEC_BUS_NUM		0x19
-#define PCI_BRIDGE_SUBORD_BUS_NUM	0x1A
-#define PCI_BRIDGE_SEC_LATENCY_TIMER	0x1B
-#define PCI_BRIDGE_IO_BASE		0x1C
-#define PCI_BRIDGE_IO_LIMIT		0x1D
-#define PCI_BRIDGE_SEC_STATUS		0x1E
-#define PCI_BRIDGE_MEMORY_BASE		0x20
-#define PCI_BRIDGE_MEMORY_LIMIT		0x22
-#define PCI_BRIDGE_PREF_MEMORY_BASE	0x24
-#define PCI_BRIDGE_PREF_MEMORY_LIMIT	0x26
-#define PCI_BRIDGE_PREF_MEMORY_BASE_UP	0x28
-#define PCI_BRIDGE_PREF_MEMORY_LIMIT_UP	0x2C
-#define PCI_BRIDGE_IO_BASE_UP		0x30
-#define PCI_BRIDGE_IO_LIMIT_UP		0x32
-#define PCI_BRIDGE_EXP_ROM_BASE		0x38
-#define PCI_BRIDGE_INT_LINE		0x3C
-#define PCI_BRIDGE_INT_PIN		0x3D
-#define PCI_BRIDGE_CTL			0x3E
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/pciintel/pciintel.ma
===================================================================
--- uspace/drv/pciintel/pciintel.ma	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 intel_pci
Index: pace/drv/root/Makefile
===================================================================
--- uspace/drv/root/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = root
-
-SOURCES = \
-	root.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/root/root.c
===================================================================
--- uspace/drv/root/root.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,220 +1,0 @@
-/*
- * Copyright (c) 2010 Lenka Trochtova
- * Copyright (c) 2010 Vojtech Horky
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @defgroup root Root device driver.
- * @brief HelenOS root device driver.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <str_error.h>
-#include <ctype.h>
-#include <macros.h>
-#include <inttypes.h>
-#include <sysinfo.h>
-
-#include <ddf/driver.h>
-#include <devman.h>
-#include <ipc/devman.h>
-
-#define NAME "root"
-
-#define PLATFORM_FUN_NAME "hw"
-#define PLATFORM_FUN_MATCH_ID_FMT "platform/%s"
-#define PLATFORM_FUN_MATCH_SCORE 100
-
-#define VIRTUAL_FUN_NAME "virt"
-#define VIRTUAL_FUN_MATCH_ID "rootvirt"
-#define VIRTUAL_FUN_MATCH_SCORE 100
-
-static int root_add_device(ddf_dev_t *dev);
-
-/** The root device driver's standard operations. */
-static driver_ops_t root_ops = {
-	.add_device = &root_add_device
-};
-
-/** The root device driver structure. */
-static driver_t root_driver = {
-	.name = NAME,
-	.driver_ops = &root_ops
-};
-
-/** Create the function which represents the root of virtual device tree.
- *
- * @param dev	Device
- * @return	EOK on success or negative error code
- */
-static int add_virtual_root_fun(ddf_dev_t *dev)
-{
-	const char *name = VIRTUAL_FUN_NAME;
-	ddf_fun_t *fun;
-	int rc;
-
-	printf(NAME ": adding new function for virtual devices.\n");
-	printf(NAME ":   function node is `%s' (%d %s)\n", name,
-	    VIRTUAL_FUN_MATCH_SCORE, VIRTUAL_FUN_MATCH_ID);
-
-	fun = ddf_fun_create(dev, fun_inner, name);
-	if (fun == NULL) {
-		printf(NAME ": error creating function %s\n", name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, VIRTUAL_FUN_MATCH_ID,
-	    VIRTUAL_FUN_MATCH_SCORE);
-	if (rc != EOK) {
-		printf(NAME ": error adding match IDs to function %s\n", name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		printf(NAME ": error binding function %s: %s\n", name,
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Create the function which represents the root of HW device tree.
- *
- * @param dev	Device
- * @return	EOK on success or negative error code
- */
-static int add_platform_fun(ddf_dev_t *dev)
-{
-	char *match_id;
-	char *platform;
-	size_t platform_size;
-
-	const char *name = PLATFORM_FUN_NAME;
-	ddf_fun_t *fun;
-	int rc;
-
-	/* Get platform name from sysinfo. */
-	platform = sysinfo_get_data("platform", &platform_size);
-	if (platform == NULL) {
-		printf(NAME ": Failed to obtain platform name.\n");
-		return ENOENT;
-	}
-
-	/* Null-terminate string. */
-	platform = realloc(platform, platform_size + 1);
-	if (platform == NULL) {
-		printf(NAME ": Memory allocation failed.\n");
-		return ENOMEM;
-	}
-
-	platform[platform_size] = '\0';
-
-	/* Construct match ID. */
-	if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
-		printf(NAME ": Memory allocation failed.\n");
-		return ENOMEM;
-	}
-
-	/* Add function. */
-	printf(NAME ": adding platform function\n");
-	printf(NAME ":   function node is `%s' (%d %s)\n", PLATFORM_FUN_NAME,
-	    PLATFORM_FUN_MATCH_SCORE, match_id);
-
-	fun = ddf_fun_create(dev, fun_inner, name);
-	if (fun == NULL) {
-		printf(NAME ": error creating function %s\n", name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, match_id, PLATFORM_FUN_MATCH_SCORE);
-	if (rc != EOK) {
-		printf(NAME ": error adding match IDs to function %s\n", name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		printf(NAME ": error binding function %s: %s\n", name,
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Get the root device.
- *
- * @param dev		The device which is root of the whole device tree (both
- *			of HW and pseudo devices).
- */
-static int root_add_device(ddf_dev_t *dev)
-{
-	printf(NAME ": root_add_device, device handle=%" PRIun "\n",
-	    dev->handle);
-
-	/*
-	 * Register virtual devices root.
-	 * We ignore error occurrence because virtual devices shall not be
-	 * vital for the system.
-	 */
-	add_virtual_root_fun(dev);
-
-	/* Register root device's children. */
-	int res = add_platform_fun(dev);
-	if (EOK != res)
-		printf(NAME ": failed to add child device for platform.\n");
-
-	return res;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS root device driver\n");
-	return ddf_driver_main(&root_driver);
-}
-
-/**
- * @}
- */
-
Index: pace/drv/root/root.ma
===================================================================
--- uspace/drv/root/root.ma	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 root
Index: pace/drv/rootpc/Makefile
===================================================================
--- uspace/drv/rootpc/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = rootpc
-
-SOURCES = \
-	rootpc.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/rootpc/rootpc.c
===================================================================
--- uspace/drv/rootpc/rootpc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,203 +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.
- */
-
-/**
- * @defgroup root_pc PC platform driver.
- * @brief HelenOS PC platform driver.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <ctype.h>
-#include <macros.h>
-
-#include <ddf/driver.h>
-#include <devman.h>
-#include <ipc/devman.h>
-#include <ipc/dev_iface.h>
-#include <ops/hw_res.h>
-#include <device/hw_res.h>
-
-#define NAME "rootpc"
-
-/** Obtain function soft-state from DDF function node */
-#define ROOTPC_FUN(fnode) ((rootpc_fun_t *) (fnode)->driver_data)
-
-typedef struct rootpc_fun {
-	hw_resource_list_t hw_resources;
-} rootpc_fun_t;
-
-static int rootpc_add_device(ddf_dev_t *dev);
-static void root_pc_init(void);
-
-/** The root device driver's standard operations. */
-static driver_ops_t rootpc_ops = {
-	.add_device = &rootpc_add_device
-};
-
-/** The root device driver structure. */
-static driver_t rootpc_driver = {
-	.name = NAME,
-	.driver_ops = &rootpc_ops
-};
-
-static hw_resource_t pci_conf_regs = {
-	.type = IO_RANGE,
-	.res.io_range = {
-		.address = 0xCF8,
-		.size = 8,
-		.endianness = LITTLE_ENDIAN
-	}
-};
-
-static rootpc_fun_t pci_data = {
-	.hw_resources = {
-		1,
-		&pci_conf_regs
-	}
-};
-
-static hw_resource_list_t *rootpc_get_resources(ddf_fun_t *fnode)
-{
-	rootpc_fun_t *fun = ROOTPC_FUN(fnode);
-	
-	assert(fun != NULL);
-	return &fun->hw_resources;
-}
-
-static bool rootpc_enable_interrupt(ddf_fun_t *fun)
-{
-	/* TODO */
-	
-	return false;
-}
-
-static hw_res_ops_t fun_hw_res_ops = {
-	&rootpc_get_resources,
-	&rootpc_enable_interrupt
-};
-
-/* Initialized in root_pc_init() function. */
-static ddf_dev_ops_t rootpc_fun_ops;
-
-static bool
-rootpc_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id,
-    rootpc_fun_t *fun)
-{
-	printf(NAME ": adding new function '%s'.\n", name);
-	
-	ddf_fun_t *fnode = NULL;
-	match_id_t *match_id = NULL;
-	
-	/* Create new device. */
-	fnode = ddf_fun_create(dev, fun_inner, name);
-	if (fnode == NULL)
-		goto failure;
-	
-	fnode->driver_data = fun;
-	
-	/* Initialize match id list */
-	match_id = create_match_id();
-	if (match_id == NULL)
-		goto failure;
-	
-	match_id->id = str_match_id;
-	match_id->score = 100;
-	add_match_id(&fnode->match_ids, match_id);
-	
-	/* Set provided operations to the device. */
-	fnode->ops = &rootpc_fun_ops;
-	
-	/* Register function. */
-	if (ddf_fun_bind(fnode) != EOK) {
-		printf(NAME ": error binding function %s.\n", name);
-		goto failure;
-	}
-	
-	return true;
-	
-failure:
-	if (match_id != NULL)
-		match_id->id = NULL;
-	
-	if (fnode != NULL)
-		ddf_fun_destroy(fnode);
-	
-	printf(NAME ": failed to add function '%s'.\n", name);
-	
-	return false;
-}
-
-static bool rootpc_add_functions(ddf_dev_t *dev)
-{
-	return rootpc_add_fun(dev, "pci0", "intel_pci", &pci_data);
-}
-
-/** Get the root device.
- *
- * @param dev		The device which is root of the whole device tree (both
- *			of HW and pseudo devices).
- * @return		Zero on success, negative error number otherwise.
- */
-static int rootpc_add_device(ddf_dev_t *dev)
-{
-	printf(NAME ": rootpc_add_device, device handle = %d\n",
-	    (int)dev->handle);
-	
-	/* Register functions. */
-	if (!rootpc_add_functions(dev)) {
-		printf(NAME ": failed to add functions for PC platform.\n");
-	}
-	
-	return EOK;
-}
-
-static void root_pc_init(void)
-{
-	rootpc_fun_ops.interfaces[HW_RES_DEV_IFACE] = &fun_hw_res_ops;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS PC platform driver\n");
-	root_pc_init();
-	return ddf_driver_main(&rootpc_driver);
-}
-
-/**
- * @}
- */
Index: pace/drv/rootpc/rootpc.ma
===================================================================
--- uspace/drv/rootpc/rootpc.ma	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 platform/pc
Index: pace/drv/rootvirt/Makefile
===================================================================
--- uspace/drv/rootvirt/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = rootvirt
-
-SOURCES = \
-	rootvirt.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/rootvirt/devices.def
===================================================================
--- uspace/drv/rootvirt/devices.def	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,23 +1,0 @@
-/*
- * Add list of virtual devices you want to launch driver for here.
- *
- * Unless the list is empty, the last item shall be followed by a comma.
- */
-#ifdef CONFIG_TEST_DRIVERS
-{
-	.name = "test1",
-	.match_id = "virtual&test1"
-},
-{
-	.name = "test2alpha",
-	.match_id = "virtual&test2"
-},
-{
-	.name = "test2bravo",
-	.match_id = "virtual&test2"
-},
-{
-	.name = "null",
-	.match_id = "virtual&test1"
-},
-#endif
Index: pace/drv/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/rootvirt/rootvirt.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,150 +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.
- */
-
-/**
- * @defgroup rootvirt Root device driver for virtual devices.
- * @{
- */
-
-/** @file
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/driver.h>
-
-#define NAME "rootvirt"
-
-/** Virtual function entry */
-typedef struct {
-	/** Function name */
-	const char *name;
-	/** Function match ID */
-	const char *match_id;
-} virtual_function_t;
-
-/** List of existing virtual functions */
-virtual_function_t virtual_functions[] = {
-#include "devices.def"
-	/* Terminating item */
-	{
-		.name = NULL,
-		.match_id = NULL
-	}
-};
-
-static int rootvirt_add_device(ddf_dev_t *dev);
-
-static driver_ops_t rootvirt_ops = {
-	.add_device = &rootvirt_add_device
-};
-
-static driver_t rootvirt_driver = {
-	.name = NAME,
-	.driver_ops = &rootvirt_ops
-};
-
-/** Add function to the virtual device.
- *
- * @param vdev		The virtual device
- * @param vfun		Virtual function description
- * @return		EOK on success or negative error code.
- */
-static int rootvirt_add_fun(ddf_dev_t *vdev, virtual_function_t *vfun)
-{
-	ddf_fun_t *fun;
-	int rc;
-
-	printf(NAME ": registering function `%s' (match \"%s\")\n",
-	    vfun->name, vfun->match_id);
-
-	fun = ddf_fun_create(vdev, fun_inner, vfun->name);
-	if (fun == NULL) {
-		printf(NAME ": error creating function %s\n", vfun->name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
-	if (rc != EOK) {
-		printf(NAME ": error adding match IDs to function %s\n",
-		    vfun->name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		printf(NAME ": error binding function %s: %s\n", vfun->name,
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	printf(NAME ": registered child device `%s'\n", vfun->name);
-	return EOK;
-}
-
-static int rootvirt_add_device(ddf_dev_t *dev)
-{
-	static int instances = 0;
-
-	/*
-	 * Allow only single instance of root virtual device.
-	 */
-	instances++;
-	if (instances > 1) {
-		return ELIMIT;
-	}
-
-	printf(NAME ": add_device(handle=%d)\n", (int)dev->handle);
-
-	/*
-	 * Go through all virtual functions and try to add them.
-	 * We silently ignore failures.
-	 */
-	virtual_function_t *vfun = virtual_functions;
-	while (vfun->name != NULL) {
-		(void) rootvirt_add_fun(dev, vfun);
-		vfun++;
-	}
-
-	return EOK;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS virtual devices root driver\n");
-	return ddf_driver_main(&rootvirt_driver);
-}
-
-/**
- * @}
- */
-
Index: pace/drv/rootvirt/rootvirt.ma
===================================================================
--- uspace/drv/rootvirt/rootvirt.ma	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 rootvirt
Index: uspace/drv/test/test1/Makefile
===================================================================
--- uspace/drv/test/test1/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test1/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = test1
+
+SOURCES = \
+	char.c \
+	test1.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/test/test1/char.c
===================================================================
--- uspace/drv/test/test1/char.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test1/char.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,56 @@
+/*
+ * 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 abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test1/test1.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,174 @@
+/*
+ * 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 <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#include "test1.h"
+
+static int test1_add_device(ddf_dev_t *dev);
+
+static driver_ops_t driver_ops = {
+	.add_device = &test1_add_device
+};
+
+static driver_t test1_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+/** Register child and inform user about it.
+ *
+ * @param parent Parent device.
+ * @param message Message for the user.
+ * @param name Device name.
+ * @param match_id Device match id.
+ * @param score Device match score.
+ */
+static int register_fun_verbose(ddf_dev_t *parent, const char *message,
+    const char *name, const char *match_id, int match_score,
+    int expected_rc)
+{
+	ddf_fun_t *fun = NULL;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);
+
+	fun = ddf_fun_create(parent, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, match_score);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		goto leave;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		goto leave;
+	}
+
+	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
+	rc = EOK;
+
+leave:
+	if (rc != expected_rc) {
+		fprintf(stderr,
+		    NAME ": Unexpected error registering function `%s'.\n" 
+		    NAME ":     Expected \"%s\" but got \"%s\".\n",
+		    name, str_error(expected_rc), str_error(rc));
+	}
+
+	if ((rc != EOK) && (fun != NULL)) {
+		ddf_fun_destroy(fun);
+	}
+
+	return rc;
+}
+
+/** Callback when new device is passed to this driver.
+ * This function is the body of the test: it shall register new child
+ * (named `clone') that shall be driven by the same task. When the clone
+ * is added, it registers another child (named `child') that is also driven
+ * by this task. The conditions ensure that we do not recurse indefinitely.
+ * When successful, the device tree shall contain following fragment:
+ *
+ * /virtual/test1
+ * /virtual/test1/clone
+ * /virtual/test1/clone/child
+ *
+ * and devman shall not deadlock.
+ *
+ *
+ * @param dev New device.
+ * @return Error code reporting success of the operation.
+ */
+static int test1_add_device(ddf_dev_t *dev)
+{
+	ddf_fun_t *fun_a;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)",
+	    dev->name, (int) dev->handle);
+
+	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
+		return rc;
+	}
+
+	ddf_fun_add_to_category(fun_a, "virtual");
+
+	if (str_cmp(dev->name, "null") == 0) {
+		fun_a->ops = &char_device_ops;
+		ddf_fun_add_to_category(fun_a, "virt-null");
+	} else if (str_cmp(dev->name, "test1") == 0) {
+		(void) register_fun_verbose(dev,
+		    "cloning myself ;-)", "clone",
+		    "virtual&test1", 10, EOK);
+		(void) register_fun_verbose(dev,
+		    "cloning myself twice ;-)", "clone",
+		    "virtual&test1", 10, EEXISTS);
+	} else if (str_cmp(dev->name, "clone") == 0) {
+		(void) register_fun_verbose(dev,
+		    "run by the same task", "child",
+		    "virtual&test1&child", 10, EOK);
+	}
+
+	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev->name);
+
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS test1 virtual device driver\n");
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&test1_driver);
+}
+
Index: uspace/drv/test/test1/test1.h
===================================================================
--- uspace/drv/test/test1/test1.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test1/test1.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,40 @@
+/*
+ * 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
+ */
+#ifndef DRV_TEST1_TEST1_H_
+#define DRV_TEST1_TEST1_H_
+
+#include <ddf/driver.h>
+
+#define NAME "test1"
+
+extern ddf_dev_ops_t char_device_ops;
+
+#endif
Index: uspace/drv/test/test1/test1.ma
===================================================================
--- uspace/drv/test/test1/test1.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test1/test1.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,2 @@
+10 virtual&test1
+10 virtual&test1&child
Index: uspace/drv/test/test2/Makefile
===================================================================
--- uspace/drv/test/test2/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test2/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = test2
+
+SOURCES = \
+	test2.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/test/test2/test2.c
===================================================================
--- uspace/drv/test/test2/test2.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test2/test2.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,157 @@
+/*
+ * 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 <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#define NAME "test2"
+
+static int test2_add_device(ddf_dev_t *dev);
+
+static driver_ops_t driver_ops = {
+	.add_device = &test2_add_device
+};
+
+static driver_t test2_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+/** Register child and inform user about it.
+ *
+ * @param parent Parent device.
+ * @param message Message for the user.
+ * @param name Device name.
+ * @param match_id Device match id.
+ * @param score Device match score.
+ */
+static int register_fun_verbose(ddf_dev_t *parent, const char *message,
+    const char *name, const char *match_id, int match_score)
+{
+	ddf_fun_t *fun;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);
+
+	fun = ddf_fun_create(parent, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, match_score);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
+	return EOK;
+}
+
+/** Add child devices after some sleep.
+ *
+ * @param arg Parent device structure (ddf_dev_t *).
+ * @return Always EOK.
+ */
+static int postponed_birth(void *arg)
+{
+	ddf_dev_t *dev = (ddf_dev_t *) arg;
+	ddf_fun_t *fun_a;
+	int rc;
+
+	async_usleep(1000);
+
+	(void) register_fun_verbose(dev, "child driven by the same task",
+	    "child", "virtual&test2", 10);
+	(void) register_fun_verbose(dev, "child driven by test1",
+	    "test1", "virtual&test1", 10);
+
+	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	if (fun_a == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_bind(fun_a);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
+		return rc;
+	}
+
+	ddf_fun_add_to_category(fun_a, "virtual");
+
+	return EOK;
+}
+
+static int test2_add_device(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "test2_add_device(name=\"%s\", handle=%d)",
+	    dev->name, (int) dev->handle);
+
+	if (str_cmp(dev->name, "child") != 0) {
+		fid_t postpone = fibril_create(postponed_birth, dev);
+		if (postpone == 0) {
+			ddf_msg(LVL_ERROR, "fibril_create() failed.");
+			return ENOMEM;
+		}
+		fibril_add_ready(postpone);
+	} else {
+		(void) register_fun_verbose(dev, "child without available driver",
+		    "ERROR", "non-existent.match.id", 10);
+	}
+
+	return EOK;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS test2 virtual device driver\n");
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&test2_driver);
+}
+
+
Index: uspace/drv/test/test2/test2.ma
===================================================================
--- uspace/drv/test/test2/test2.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test2/test2.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 virtual&test2
Index: uspace/drv/test/test3/Makefile
===================================================================
--- uspace/drv/test/test3/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test3/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = test3
+
+SOURCES = \
+	test3.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/test/test3/test3.c
===================================================================
--- uspace/drv/test/test3/test3.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test3/test3.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 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 <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#define NAME "test3"
+
+static int test3_add_device(ddf_dev_t *dev);
+
+static driver_ops_t driver_ops = {
+	.add_device = &test3_add_device
+};
+
+static driver_t test3_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+static int register_fun_and_add_to_category(ddf_dev_t *parent,
+     const char *base_name, size_t index, const char *class_name)
+{
+	ddf_fun_t *fun = NULL;
+	int rc;
+	char *fun_name = NULL;
+	
+	rc = asprintf(&fun_name, "%s%zu", base_name, index);
+	if (rc < 0) {
+		ddf_msg(LVL_ERROR, "Failed to format string: %s", str_error(rc));
+		goto leave;
+	}
+	
+	fun = ddf_fun_create(parent, fun_exposed, fun_name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", fun_name);
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", fun_name,
+		    str_error(rc));
+		goto leave;
+	}
+	
+	ddf_fun_add_to_category(fun, class_name);
+
+	ddf_msg(LVL_NOTE, "Registered exposed function `%s'.", fun_name);
+
+leave:	
+	free(fun_name);
+	
+	if ((rc != EOK) && (fun != NULL)) {
+		ddf_fun_destroy(fun);
+	}
+	
+	return rc;
+}
+
+static int test3_add_device(ddf_dev_t *dev)
+{
+	int rc = EOK;
+
+	ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)",
+	    dev->name, (int) dev->handle);
+
+	size_t i;
+	for (i = 0; i < 20; i++) {
+		rc = register_fun_and_add_to_category(dev,
+		    "test3_", i, "test3");
+		if (rc != EOK) {
+			break;
+		}
+	}
+	
+	return rc;
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS test3 virtual device driver\n");
+	ddf_log_init(NAME, LVL_ERROR);
+	return ddf_driver_main(&test3_driver);
+}
+
Index: uspace/drv/test/test3/test3.ma
===================================================================
--- uspace/drv/test/test3/test3.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/drv/test/test3/test3.ma	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+10 virtual&test3
Index: pace/drv/test1/Makefile
===================================================================
--- uspace/drv/test1/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,38 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = test1
-
-SOURCES = \
-	char.c \
-	test1.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/test1/char.c
===================================================================
--- uspace/drv/test1/char.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(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: pace/drv/test1/test1.c
===================================================================
--- uspace/drv/test1/test1.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,152 +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 <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/driver.h>
-
-#include "test1.h"
-
-static int test1_add_device(ddf_dev_t *dev);
-
-static driver_ops_t driver_ops = {
-	.add_device = &test1_add_device
-};
-
-static driver_t test1_driver = {
-	.name = NAME,
-	.driver_ops = &driver_ops
-};
-
-/** Register child and inform user about it.
- *
- * @param parent Parent device.
- * @param message Message for the user.
- * @param name Device name.
- * @param match_id Device match id.
- * @param score Device match score.
- */
-static int register_fun_verbose(ddf_dev_t *parent, const char *message,
-    const char *name, const char *match_id, int match_score)
-{
-	ddf_fun_t *fun;
-	int rc;
-
-	printf(NAME ": registering function `%s': %s.\n", name, message);
-
-	fun = ddf_fun_create(parent, fun_inner, name);
-	if (fun == NULL) {
-		printf(NAME ": error creating function %s\n", name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, match_id, match_score);
-	if (rc != EOK) {
-		printf(NAME ": error adding match IDs to function %s\n", name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		printf(NAME ": error binding function %s: %s\n", name,
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	printf(NAME ": registered child device `%s'\n", name);
-	return EOK;
-}
-
-/** Callback when new device is passed to this driver.
- * This function is the body of the test: it shall register new child
- * (named `clone') that shall be driven by the same task. When the clone
- * is added, it registers another child (named `child') that is also driven
- * by this task. The conditions ensure that we do not recurse indefinitely.
- * When successful, the device tree shall contain following fragment:
- *
- * /virtual/test1
- * /virtual/test1/clone
- * /virtual/test1/clone/child
- *
- * and devman shall not deadlock.
- *
- *
- * @param dev New device.
- * @return Error code reporting success of the operation.
- */
-static int test1_add_device(ddf_dev_t *dev)
-{
-	ddf_fun_t *fun_a;
-	int rc;
-
-	printf(NAME ": add_device(name=\"%s\", handle=%d)\n",
-	    dev->name, (int) dev->handle);
-
-	fun_a = ddf_fun_create(dev, fun_exposed, "a");
-	if (fun_a == NULL) {
-		printf(NAME ": error creating function 'a'.\n");
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_bind(fun_a);
-	if (rc != EOK) {
-		printf(NAME ": error binding function 'a'.\n");
-		return rc;
-	}
-
-	ddf_fun_add_to_class(fun_a, "virtual");
-
-	if (str_cmp(dev->name, "null") == 0) {
-		fun_a->ops = &char_device_ops;
-		ddf_fun_add_to_class(fun_a, "virt-null");
-	} else if (str_cmp(dev->name, "test1") == 0) {
-		(void) register_fun_verbose(dev, "cloning myself ;-)", "clone",
-		    "virtual&test1", 10);
-	} else if (str_cmp(dev->name, "clone") == 0) {
-		(void) register_fun_verbose(dev, "run by the same task", "child",
-		    "virtual&test1&child", 10);
-	}
-
-	printf(NAME ": device `%s' accepted.\n", dev->name);
-
-	return EOK;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS test1 virtual device driver\n");
-	return ddf_driver_main(&test1_driver);
-}
-
Index: pace/drv/test1/test1.h
===================================================================
--- uspace/drv/test1/test1.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,40 +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
- */
-#ifndef DRV_TEST1_TEST1_H_
-#define DRV_TEST1_TEST1_H_
-
-#include <ddf/driver.h>
-
-#define NAME "test1"
-
-extern ddf_dev_ops_t char_device_ops;
-
-#endif
Index: pace/drv/test1/test1.ma
===================================================================
--- uspace/drv/test1/test1.ma	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,2 +1,0 @@
-10 virtual&test1
-10 virtual&test1&child
Index: pace/drv/test2/Makefile
===================================================================
--- uspace/drv/test2/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,37 +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.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBDRV_PREFIX)/libdrv.a
-EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
-BINARY = test2
-
-SOURCES = \
-	test2.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/drv/test2/test2.c
===================================================================
--- uspace/drv/test2/test2.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,154 +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 <async.h>
-#include <stdio.h>
-#include <errno.h>
-#include <str_error.h>
-#include <ddf/driver.h>
-
-#define NAME "test2"
-
-static int test2_add_device(ddf_dev_t *dev);
-
-static driver_ops_t driver_ops = {
-	.add_device = &test2_add_device
-};
-
-static driver_t test2_driver = {
-	.name = NAME,
-	.driver_ops = &driver_ops
-};
-
-/** Register child and inform user about it.
- *
- * @param parent Parent device.
- * @param message Message for the user.
- * @param name Device name.
- * @param match_id Device match id.
- * @param score Device match score.
- */
-static int register_fun_verbose(ddf_dev_t *parent, const char *message,
-    const char *name, const char *match_id, int match_score)
-{
-	ddf_fun_t *fun;
-	int rc;
-
-	printf(NAME ": registering function `%s': %s.\n", name, message);
-
-	fun = ddf_fun_create(parent, fun_inner, name);
-	if (fun == NULL) {
-		printf(NAME ": error creating function %s\n", name);
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_add_match_id(fun, match_id, match_score);
-	if (rc != EOK) {
-		printf(NAME ": error adding match IDs to function %s\n", name);
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	rc = ddf_fun_bind(fun);
-	if (rc != EOK) {
-		printf(NAME ": error binding function %s: %s\n", name,
-		    str_error(rc));
-		ddf_fun_destroy(fun);
-		return rc;
-	}
-
-	printf(NAME ": registered child device `%s'\n", name);
-	return EOK;
-}
-
-/** Add child devices after some sleep.
- *
- * @param arg Parent device structure (ddf_dev_t *).
- * @return Always EOK.
- */
-static int postponed_birth(void *arg)
-{
-	ddf_dev_t *dev = (ddf_dev_t *) arg;
-	ddf_fun_t *fun_a;
-	int rc;
-
-	async_usleep(1000);
-
-	(void) register_fun_verbose(dev, "child driven by the same task",
-	    "child", "virtual&test2", 10);
-	(void) register_fun_verbose(dev, "child driven by test1",
-	    "test1", "virtual&test1", 10);
-
-	fun_a = ddf_fun_create(dev, fun_exposed, "a");
-	if (fun_a == NULL) {
-		printf(NAME ": error creating function 'a'.\n");
-		return ENOMEM;
-	}
-
-	rc = ddf_fun_bind(fun_a);
-	if (rc != EOK) {
-		printf(NAME ": error binding function 'a'.\n");
-		return rc;
-	}
-
-	ddf_fun_add_to_class(fun_a, "virtual");
-
-	return EOK;
-}
-
-static int test2_add_device(ddf_dev_t *dev)
-{
-	printf(NAME ": test2_add_device(name=\"%s\", handle=%d)\n",
-	    dev->name, (int) dev->handle);
-
-	if (str_cmp(dev->name, "child") != 0) {
-		fid_t postpone = fibril_create(postponed_birth, dev);
-		if (postpone == 0) {
-			printf(NAME ": fibril_create() error\n");
-			return ENOMEM;
-		}
-		fibril_add_ready(postpone);
-	} else {
-		(void) register_fun_verbose(dev, "child without available driver",
-		    "ERROR", "non-existent.match.id", 10);
-	}
-
-	return EOK;
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS test2 virtual device driver\n");
-	return ddf_driver_main(&test2_driver);
-}
-
-
Index: pace/drv/test2/test2.ma
===================================================================
--- uspace/drv/test2/test2.ma	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1 +1,0 @@
-10 virtual&test2
Index: uspace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/block/libblock.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -2,4 +2,5 @@
  * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
@@ -38,5 +39,5 @@
 #include "libblock.h"
 #include "../../srv/vfs/vfs.h"
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <ipc/bd.h>
 #include <ipc/services.h>
@@ -51,4 +52,6 @@
 #include <macros.h>
 #include <mem.h>
+#include <malloc.h>
+#include <stdio.h>
 #include <sys/typefmt.h>
 #include <stacktrace.h>
@@ -57,17 +60,17 @@
 static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
 /** Device connection list head. */
-static LIST_INITIALIZE(dcl_head);
-
-#define CACHE_BUCKETS_LOG2		10
-#define CACHE_BUCKETS			(1 << CACHE_BUCKETS_LOG2)
+static LIST_INITIALIZE(dcl);
+
+#define CACHE_BUCKETS_LOG2  10
+#define CACHE_BUCKETS       (1 << CACHE_BUCKETS_LOG2)
 
 typedef struct {
 	fibril_mutex_t lock;
-	size_t lblock_size;		/**< Logical block size. */
-	unsigned blocks_cluster;	/**< Physical blocks per block_t */
-	unsigned block_count;		/**< Total number of blocks. */
-	unsigned blocks_cached;		/**< Number of cached blocks. */
+	size_t lblock_size;       /**< Logical block size. */
+	unsigned blocks_cluster;  /**< Physical blocks per block_t */
+	unsigned block_count;     /**< Total number of blocks. */
+	unsigned blocks_cached;   /**< Number of cached blocks. */
 	hash_table_t block_hash;
-	link_t free_head;
+	list_t free_list;
 	enum cache_mode mode;
 } cache_t;
@@ -75,6 +78,6 @@
 typedef struct {
 	link_t link;
-	devmap_handle_t devmap_handle;
-	int dev_phone;
+	service_id_t service_id;
+	async_sess_t *sess;
 	fibril_mutex_t comm_area_lock;
 	void *comm_area;
@@ -82,39 +85,38 @@
 	void *bb_buf;
 	aoff64_t bb_addr;
-	size_t pblock_size;		/**< Physical block size. */
+	size_t pblock_size;  /**< Physical block size. */
 	cache_t *cache;
 } devcon_t;
 
-static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt);
-static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt);
-static int get_block_size(int dev_phone, size_t *bsize);
-static int get_num_blocks(int dev_phone, aoff64_t *nblocks);
-static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba);
-
-static devcon_t *devcon_search(devmap_handle_t devmap_handle)
-{
-	link_t *cur;
-
+static int read_blocks(devcon_t *, aoff64_t, size_t);
+static int write_blocks(devcon_t *, aoff64_t, size_t);
+static int get_block_size(async_sess_t *, size_t *);
+static int get_num_blocks(async_sess_t *, aoff64_t *);
+static aoff64_t ba_ltop(devcon_t *, aoff64_t);
+
+static devcon_t *devcon_search(service_id_t service_id)
+{
 	fibril_mutex_lock(&dcl_lock);
-	for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
+	
+	list_foreach(dcl, cur) {
 		devcon_t *devcon = list_get_instance(cur, devcon_t, link);
-		if (devcon->devmap_handle == devmap_handle) {
+		if (devcon->service_id == service_id) {
 			fibril_mutex_unlock(&dcl_lock);
 			return devcon;
 		}
 	}
+	
 	fibril_mutex_unlock(&dcl_lock);
 	return NULL;
 }
 
-static int devcon_add(devmap_handle_t devmap_handle, int dev_phone, size_t bsize,
-    void *comm_area, size_t comm_size)
-{
-	link_t *cur;
+static int devcon_add(service_id_t service_id, async_sess_t *sess,
+    size_t bsize, void *comm_area, size_t comm_size)
+{
 	devcon_t *devcon;
-
+	
 	if (comm_size < bsize)
 		return EINVAL;
-
+	
 	devcon = malloc(sizeof(devcon_t));
 	if (!devcon)
@@ -122,6 +124,6 @@
 	
 	link_initialize(&devcon->link);
-	devcon->devmap_handle = devmap_handle;
-	devcon->dev_phone = dev_phone;
+	devcon->service_id = service_id;
+	devcon->sess = sess;
 	fibril_mutex_initialize(&devcon->comm_area_lock);
 	devcon->comm_area = comm_area;
@@ -131,9 +133,9 @@
 	devcon->pblock_size = bsize;
 	devcon->cache = NULL;
-
+	
 	fibril_mutex_lock(&dcl_lock);
-	for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
+	list_foreach(dcl, cur) {
 		devcon_t *d = list_get_instance(cur, devcon_t, link);
-		if (d->devmap_handle == devmap_handle) {
+		if (d->service_id == service_id) {
 			fibril_mutex_unlock(&dcl_lock);
 			free(devcon);
@@ -141,5 +143,5 @@
 		}
 	}
-	list_append(&devcon->link, &dcl_head);
+	list_append(&devcon->link, &dcl);
 	fibril_mutex_unlock(&dcl_lock);
 	return EOK;
@@ -153,72 +155,74 @@
 }
 
-int block_init(devmap_handle_t devmap_handle, size_t comm_size)
-{
-	int rc;
-	int dev_phone;
-	void *comm_area;
-	size_t bsize;
-
-	comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
+int block_init(exch_mgmt_t mgmt, service_id_t service_id,
+    size_t comm_size)
+{
+	void *comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE,
 	    MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
-	if (!comm_area) {
+	if (!comm_area)
 		return ENOMEM;
-	}
-
-	dev_phone = devmap_device_connect(devmap_handle, IPC_FLAG_BLOCKING);
-	if (dev_phone < 0) {
+	
+	async_sess_t *sess = loc_service_connect(mgmt, service_id,
+	    IPC_FLAG_BLOCKING);
+	if (!sess) {
 		munmap(comm_area, comm_size);
-		return dev_phone;
-	}
-
-	rc = async_share_out_start(dev_phone, comm_area,
+		return ENOENT;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_share_out_start(exch, comm_area,
 	    AS_AREA_READ | AS_AREA_WRITE);
-	if (rc != EOK) {
-	    	munmap(comm_area, comm_size);
-		async_hangup(dev_phone);
-		return rc;
-	}
-
-	if (get_block_size(dev_phone, &bsize) != EOK) {
-		munmap(comm_area, comm_size);
-		async_hangup(dev_phone);
-		return rc;
-	}
-	
-	rc = devcon_add(devmap_handle, dev_phone, bsize, comm_area, comm_size);
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
 		munmap(comm_area, comm_size);
-		async_hangup(dev_phone);
+		async_hangup(sess);
 		return rc;
 	}
-
+	
+	size_t bsize;
+	rc = get_block_size(sess, &bsize);
+	
+	if (rc != EOK) {
+		munmap(comm_area, comm_size);
+		async_hangup(sess);
+		return rc;
+	}
+	
+	rc = devcon_add(service_id, sess, bsize, comm_area, comm_size);
+	if (rc != EOK) {
+		munmap(comm_area, comm_size);
+		async_hangup(sess);
+		return rc;
+	}
+	
 	return EOK;
 }
 
-void block_fini(devmap_handle_t devmap_handle)
-{
-	devcon_t *devcon = devcon_search(devmap_handle);
+void block_fini(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
 	assert(devcon);
 	
 	if (devcon->cache)
-		(void) block_cache_fini(devmap_handle);
-
+		(void) block_cache_fini(service_id);
+	
 	devcon_remove(devcon);
-
+	
 	if (devcon->bb_buf)
 		free(devcon->bb_buf);
-
+	
 	munmap(devcon->comm_area, devcon->comm_size);
-	async_hangup(devcon->dev_phone);
-
-	free(devcon);	
-}
-
-int block_bb_read(devmap_handle_t devmap_handle, aoff64_t ba)
+	async_hangup(devcon->sess);
+	
+	free(devcon);
+}
+
+int block_bb_read(service_id_t service_id, aoff64_t ba)
 {
 	void *bb_buf;
 	int rc;
 
-	devcon_t *devcon = devcon_search(devmap_handle);
+	devcon_t *devcon = devcon_search(service_id);
 	if (!devcon)
 		return ENOENT;
@@ -245,7 +249,7 @@
 }
 
-void *block_bb_get(devmap_handle_t devmap_handle)
-{
-	devcon_t *devcon = devcon_search(devmap_handle);
+void *block_bb_get(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
 	assert(devcon);
 	return devcon->bb_buf;
@@ -254,5 +258,5 @@
 static hash_index_t cache_hash(unsigned long *key)
 {
-	return *key & (CACHE_BUCKETS - 1);
+	return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1);
 }
 
@@ -260,5 +264,5 @@
 {
 	block_t *b = hash_table_get_instance(item, block_t, hash_link);
-	return b->lba == *key;
+	return b->lba == MERGE_LOUP32(key[0], key[1]);
 }
 
@@ -273,8 +277,8 @@
 };
 
-int block_cache_init(devmap_handle_t devmap_handle, size_t size, unsigned blocks,
+int block_cache_init(service_id_t service_id, size_t size, unsigned blocks,
     enum cache_mode mode)
 {
-	devcon_t *devcon = devcon_search(devmap_handle);
+	devcon_t *devcon = devcon_search(service_id);
 	cache_t *cache;
 	if (!devcon)
@@ -287,5 +291,5 @@
 	
 	fibril_mutex_initialize(&cache->lock);
-	list_initialize(&cache->free_head);
+	list_initialize(&cache->free_list);
 	cache->lblock_size = size;
 	cache->block_count = blocks;
@@ -301,5 +305,5 @@
 	cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
 
-	if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
+	if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2,
 	    &cache_ops)) {
 		free(cache);
@@ -311,7 +315,7 @@
 }
 
-int block_cache_fini(devmap_handle_t devmap_handle)
-{
-	devcon_t *devcon = devcon_search(devmap_handle);
+int block_cache_fini(service_id_t service_id)
+{
+	devcon_t *devcon = devcon_search(service_id);
 	cache_t *cache;
 	int rc;
@@ -328,6 +332,6 @@
 	 * bother with the cache and block locks because we are single-threaded.
 	 */
-	while (!list_empty(&cache->free_head)) {
-		block_t *b = list_get_instance(cache->free_head.next,
+	while (!list_empty(&cache->free_list)) {
+		block_t *b = list_get_instance(list_first(&cache->free_list),
 		    block_t, free_link);
 
@@ -340,6 +344,9 @@
 		}
 
-		unsigned long key = b->lba;
-		hash_table_remove(&cache->block_hash, &key, 1);
+		unsigned long key[2] = {
+			LOWER32(b->lba),
+			UPPER32(b->lba)
+		};
+		hash_table_remove(&cache->block_hash, key, 2);
 		
 		free(b->data);
@@ -360,5 +367,5 @@
 	if (cache->blocks_cached < CACHE_LO_WATERMARK)
 		return true;
-	if (!list_empty(&cache->free_head))
+	if (!list_empty(&cache->free_list))
 		return false;
 	return true;
@@ -380,5 +387,5 @@
  * @param block			Pointer to where the function will store the
  * 				block pointer on success.
- * @param devmap_handle		Device handle of the block device.
+ * @param service_id		Service ID of the block device.
  * @param ba			Block address (logical).
  * @param flags			If BLOCK_FLAGS_NOREAD is specified, block_get()
@@ -388,5 +395,5 @@
  * @return			EOK on success or a negative error code.
  */
-int block_get(block_t **block, devmap_handle_t devmap_handle, aoff64_t ba, int flags)
+int block_get(block_t **block, service_id_t service_id, aoff64_t ba, int flags)
 {
 	devcon_t *devcon;
@@ -394,8 +401,12 @@
 	block_t *b;
 	link_t *l;
-	unsigned long key = ba;
+	unsigned long key[2] = {
+		LOWER32(ba),
+		UPPER32(ba)
+	};
+
 	int rc;
 	
-	devcon = devcon_search(devmap_handle);
+	devcon = devcon_search(service_id);
 
 	assert(devcon);
@@ -409,5 +420,5 @@
 
 	fibril_mutex_lock(&cache->lock);
-	l = hash_table_find(&cache->block_hash, &key);
+	l = hash_table_find(&cache->block_hash, key);
 	if (l) {
 found:
@@ -447,12 +458,11 @@
 			 * Try to recycle a block from the free list.
 			 */
-			unsigned long temp_key;
 recycle:
-			if (list_empty(&cache->free_head)) {
+			if (list_empty(&cache->free_list)) {
 				fibril_mutex_unlock(&cache->lock);
 				rc = ENOMEM;
 				goto out;
 			}
-			l = cache->free_head.next;
+			l = list_first(&cache->free_list);
 			b = list_get_instance(l, block_t, free_link);
 
@@ -469,5 +479,5 @@
 				 */
 				list_remove(&b->free_link);
-				list_append(&b->free_link, &cache->free_head);
+				list_append(&b->free_link, &cache->free_list);
 				fibril_mutex_unlock(&cache->lock);
 				fibril_mutex_lock(&devcon->comm_area_lock);
@@ -495,5 +505,5 @@
 					goto retry;
 				}
-				l = hash_table_find(&cache->block_hash, &key);
+				l = hash_table_find(&cache->block_hash, key);
 				if (l) {
 					/*
@@ -518,14 +528,17 @@
 			 */
 			list_remove(&b->free_link);
-			temp_key = b->lba;
-			hash_table_remove(&cache->block_hash, &temp_key, 1);
+			unsigned long temp_key[2] = {
+				LOWER32(b->lba),
+				UPPER32(b->lba)
+			};
+			hash_table_remove(&cache->block_hash, temp_key, 2);
 		}
 
 		block_initialize(b);
-		b->devmap_handle = devmap_handle;
+		b->service_id = service_id;
 		b->size = cache->lblock_size;
 		b->lba = ba;
 		b->pba = ba_ltop(devcon, b->lba);
-		hash_table_insert(&cache->block_hash, &key, &b->hash_link);
+		hash_table_insert(&cache->block_hash, key, &b->hash_link);
 
 		/*
@@ -573,5 +586,5 @@
 int block_put(block_t *block)
 {
-	devcon_t *devcon = devcon_search(block->devmap_handle);
+	devcon_t *devcon = devcon_search(block->service_id);
 	cache_t *cache;
 	unsigned blocks_cached;
@@ -639,6 +652,9 @@
 			 * Take the block out of the cache and free it.
 			 */
-			unsigned long key = block->lba;
-			hash_table_remove(&cache->block_hash, &key, 1);
+			unsigned long key[2] = {
+				LOWER32(block->lba),
+				UPPER32(block->lba)
+			};
+			hash_table_remove(&cache->block_hash, key, 2);
 			fibril_mutex_unlock(&block->lock);
 			free(block->data);
@@ -661,5 +677,5 @@
 			goto retry;
 		}
-		list_append(&block->free_link, &cache->free_head);
+		list_append(&block->free_link, &cache->free_list);
 	}
 	fibril_mutex_unlock(&block->lock);
@@ -671,5 +687,5 @@
 /** Read sequential data from a block device.
  *
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param bufpos	Pointer to the first unread valid offset within the
  * 			communication buffer.
@@ -683,5 +699,5 @@
  * @return		EOK on success or a negative return code on failure.
  */
-int block_seqread(devmap_handle_t devmap_handle, size_t *bufpos, size_t *buflen,
+int block_seqread(service_id_t service_id, size_t *bufpos, size_t *buflen,
     aoff64_t *pos, void *dst, size_t size)
 {
@@ -691,5 +707,5 @@
 	devcon_t *devcon;
 
-	devcon = devcon_search(devmap_handle);
+	devcon = devcon_search(service_id);
 	assert(devcon);
 	block_size = devcon->pblock_size;
@@ -737,5 +753,5 @@
 /** Read blocks directly from device (bypass cache).
  *
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param ba		Address of first block (physical).
  * @param cnt		Number of blocks.
@@ -744,10 +760,10 @@
  * @return		EOK on success or negative error code on failure.
  */
-int block_read_direct(devmap_handle_t devmap_handle, aoff64_t ba, size_t cnt, void *buf)
+int block_read_direct(service_id_t service_id, aoff64_t ba, size_t cnt, void *buf)
 {
 	devcon_t *devcon;
 	int rc;
 
-	devcon = devcon_search(devmap_handle);
+	devcon = devcon_search(service_id);
 	assert(devcon);
 	
@@ -765,5 +781,5 @@
 /** Write blocks directly to device (bypass cache).
  *
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param ba		Address of first block (physical).
  * @param cnt		Number of blocks.
@@ -772,5 +788,5 @@
  * @return		EOK on success or negative error code on failure.
  */
-int block_write_direct(devmap_handle_t devmap_handle, aoff64_t ba, size_t cnt,
+int block_write_direct(service_id_t service_id, aoff64_t ba, size_t cnt,
     const void *data)
 {
@@ -778,5 +794,5 @@
 	int rc;
 
-	devcon = devcon_search(devmap_handle);
+	devcon = devcon_search(service_id);
 	assert(devcon);
 	
@@ -793,34 +809,84 @@
 /** Get device block size.
  *
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param bsize		Output block size.
  *
  * @return		EOK on success or negative error code on failure.
  */
-int block_get_bsize(devmap_handle_t devmap_handle, size_t *bsize)
+int block_get_bsize(service_id_t service_id, size_t *bsize)
 {
 	devcon_t *devcon;
 
-	devcon = devcon_search(devmap_handle);
-	assert(devcon);
-	
-	return get_block_size(devcon->dev_phone, bsize);
+	devcon = devcon_search(service_id);
+	assert(devcon);
+	
+	return get_block_size(devcon->sess, bsize);
 }
 
 /** Get number of blocks on device.
  *
- * @param devmap_handle	Device handle of the block device.
+ * @param service_id	Service ID of the block device.
  * @param nblocks	Output number of blocks.
  *
  * @return		EOK on success or negative error code on failure.
  */
-int block_get_nblocks(devmap_handle_t devmap_handle, aoff64_t *nblocks)
-{
-	devcon_t *devcon;
-
-	devcon = devcon_search(devmap_handle);
-	assert(devcon);
-	
-	return get_num_blocks(devcon->dev_phone, nblocks);
+int block_get_nblocks(service_id_t service_id, aoff64_t *nblocks)
+{
+	devcon_t *devcon = devcon_search(service_id);
+	assert(devcon);
+	
+	return get_num_blocks(devcon->sess, nblocks);
+}
+
+/** Read bytes directly from the device (bypass cache)
+ * 
+ * @param service_id	Service ID of the block device.
+ * @param abs_offset	Absolute offset in bytes where to start reading
+ * @param bytes			Number of bytes to read
+ * @param data			Buffer that receives the data
+ * 
+ * @return		EOK on success or negative error code on failure.
+ */
+int block_read_bytes_direct(service_id_t service_id, aoff64_t abs_offset,
+    size_t bytes, void *data)
+{
+	int rc;
+	size_t phys_block_size;
+	size_t buf_size;
+	void *buffer;
+	aoff64_t first_block;
+	aoff64_t last_block;
+	size_t blocks;
+	size_t offset;
+	
+	rc = block_get_bsize(service_id, &phys_block_size);
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	/* calculate data position and required space */
+	first_block = abs_offset / phys_block_size;
+	offset = abs_offset % phys_block_size;
+	last_block = (abs_offset + bytes - 1) / phys_block_size;
+	blocks = last_block - first_block + 1;
+	buf_size = blocks * phys_block_size;
+	
+	/* read the data into memory */
+	buffer = malloc(buf_size);
+	if (buffer == NULL) {
+		return ENOMEM;
+	}
+	
+	rc = block_read_direct(service_id, first_block, blocks, buffer);
+	if (rc != EOK) {
+		free(buffer);
+		return rc;
+	}
+	
+	/* copy the data from the buffer */
+	memcpy(data, buffer + offset, bytes);
+	free(buffer);
+	
+	return EOK;
 }
 
@@ -836,17 +902,20 @@
 static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
 {
-	int rc;
-
-	assert(devcon);
-	rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
+	assert(devcon);
+	
+	async_exch_t *exch = async_exchange_begin(devcon->sess);
+	int rc = async_req_3_0(exch, BD_READ_BLOCKS, LOWER32(ba),
 	    UPPER32(ba), cnt);
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
 		printf("Error %d reading %zu blocks starting at block %" PRIuOFF64
 		    " from device handle %" PRIun "\n", rc, cnt, ba,
-		    devcon->devmap_handle);
+		    devcon->service_id);
 #ifndef NDEBUG
 		stacktrace_print();
 #endif
 	}
+	
 	return rc;
 }
@@ -863,43 +932,50 @@
 static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
 {
-	int rc;
-
-	assert(devcon);
-	rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
+	assert(devcon);
+	
+	async_exch_t *exch = async_exchange_begin(devcon->sess);
+	int rc = async_req_3_0(exch, BD_WRITE_BLOCKS, LOWER32(ba),
 	    UPPER32(ba), cnt);
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
 		printf("Error %d writing %zu blocks starting at block %" PRIuOFF64
-		    " to device handle %" PRIun "\n", rc, cnt, ba, devcon->devmap_handle);
+		    " to device handle %" PRIun "\n", rc, cnt, ba, devcon->service_id);
 #ifndef NDEBUG
 		stacktrace_print();
 #endif
 	}
+	
 	return rc;
 }
 
 /** Get block size used by the device. */
-static int get_block_size(int dev_phone, size_t *bsize)
+static int get_block_size(async_sess_t *sess, size_t *bsize)
 {
 	sysarg_t bs;
-	int rc;
-
-	rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs);
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bs);
+	async_exchange_end(exch);
+	
 	if (rc == EOK)
 		*bsize = (size_t) bs;
-
+	
 	return rc;
 }
 
 /** Get total number of blocks on block device. */
-static int get_num_blocks(int dev_phone, aoff64_t *nblocks)
-{
-	sysarg_t nb_l, nb_h;
-	int rc;
-
-	rc = async_req_0_2(dev_phone, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
-	if (rc == EOK) {
+static int get_num_blocks(async_sess_t *sess, aoff64_t *nblocks)
+{
+	sysarg_t nb_l;
+	sysarg_t nb_h;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
+	async_exchange_end(exch);
+	
+	if (rc == EOK)
 		*nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
-	}
-
+	
 	return rc;
 }
Index: uspace/lib/block/libblock.h
===================================================================
--- uspace/lib/block/libblock.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/block/libblock.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2008 Jakub Jermar
- * Copyright (c) 2008 Martin Decky 
+ * Copyright (c) 2008 Martin Decky
+ * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
  *
@@ -39,4 +40,5 @@
 
 #include <stdint.h>
+#include <async.h>
 #include "../../srv/vfs/vfs.h"
 #include <fibril_synch.h>
@@ -71,6 +73,6 @@
 	/** Readers / Writer lock protecting the contents of the block. */
 	fibril_rwlock_t contents_lock;
-	/** Handle of the device where the block resides. */
-	devmap_handle_t devmap_handle;
+	/** Service ID of service providing the block device. */
+	service_id_t service_id;
 	/** Logical block address */
 	aoff64_t lba;
@@ -95,23 +97,24 @@
 };
 
-extern int block_init(devmap_handle_t, size_t);
-extern void block_fini(devmap_handle_t);
+extern int block_init(exch_mgmt_t, service_id_t, size_t);
+extern void block_fini(service_id_t);
 
-extern int block_bb_read(devmap_handle_t, aoff64_t);
-extern void *block_bb_get(devmap_handle_t);
+extern int block_bb_read(service_id_t, aoff64_t);
+extern void *block_bb_get(service_id_t);
 
-extern int block_cache_init(devmap_handle_t, size_t, unsigned, enum cache_mode);
-extern int block_cache_fini(devmap_handle_t);
+extern int block_cache_init(service_id_t, size_t, unsigned, enum cache_mode);
+extern int block_cache_fini(service_id_t);
 
-extern int block_get(block_t **, devmap_handle_t, aoff64_t, int);
+extern int block_get(block_t **, service_id_t, aoff64_t, int);
 extern int block_put(block_t *);
 
-extern int block_seqread(devmap_handle_t, size_t *, size_t *, aoff64_t *, void *,
+extern int block_seqread(service_id_t, size_t *, size_t *, aoff64_t *, void *,
     size_t);
 
-extern int block_get_bsize(devmap_handle_t, size_t *);
-extern int block_get_nblocks(devmap_handle_t, aoff64_t *);
-extern int block_read_direct(devmap_handle_t, aoff64_t, size_t, void *);
-extern int block_write_direct(devmap_handle_t, aoff64_t, size_t, const void *);
+extern int block_get_bsize(service_id_t, size_t *);
+extern int block_get_nblocks(service_id_t, aoff64_t *);
+extern int block_read_direct(service_id_t, aoff64_t, size_t, void *);
+extern int block_read_bytes_direct(service_id_t, aoff64_t, size_t, void *);
+extern int block_write_direct(service_id_t, aoff64_t, size_t, const void *);
 
 #endif
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -31,6 +31,5 @@
 ROOT_PATH = $(USPACE_PREFIX)/..
 
-INCLUDE_KERNEL = include/kernel
-INCLUDE_ARCH = include/arch
+INCLUDE_ABI = include/abi
 INCLUDE_LIBARCH = include/libarch
 
@@ -41,8 +40,17 @@
 CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
 
-PRE_DEPEND = $(INCLUDE_KERNEL) $(INCLUDE_ARCH) $(INCLUDE_LIBARCH) $(COMMON_HEADER_ARCH)
-EXTRA_OUTPUT = $(LINKER_SCRIPT)
-EXTRA_CLEAN = $(INCLUDE_KERNEL) $(INCLUDE_ARCH) $(INCLUDE_LIBARCH) $(COMMON_HEADER_ARCH) $(LINKER_SCRIPT)
+LINKER_SCRIPTS = \
+	$(LIBC_PREFIX)/arch/$(UARCH)/_link.ld \
+	$(LIBC_PREFIX)/arch/$(UARCH)/_link-loader.ld \
+	$(LIBC_PREFIX)/arch/$(UARCH)/_link-shlib.ld \
+	$(LIBC_PREFIX)/arch/$(UARCH)/_link-dlexe.ld
+
+PRE_DEPEND = $(INCLUDE_ABI) $(INCLUDE_LIBARCH) $(COMMON_HEADER_ARCH)
+EXTRA_OUTPUT = $(LINKER_SCRIPTS)
+EXTRA_CLEAN = $(INCLUDE_ABI) $(INCLUDE_LIBARCH) $(COMMON_HEADER_ARCH) $(LINKER_SCRIPTS)
 LIBRARY = libc
+SLIBRARY = libc.so.0.0
+LSONAME = libc.so0
+
 
 -include $(COMMON_MAKEFILE)
@@ -56,13 +64,15 @@
 	generic/cap.c \
 	generic/clipboard.c \
-	generic/devmap.c \
 	generic/devman.c \
 	generic/device/hw_res.c \
 	generic/device/char_dev.c \
+	generic/elf/elf_load.c \
 	generic/event.c \
 	generic/errno.c \
+	generic/loc.c \
 	generic/mem.c \
 	generic/str.c \
 	generic/str_error.c \
+	generic/l18n/langs.c \
 	generic/fibril.c \
 	generic/fibril_synch.c \
@@ -76,4 +86,5 @@
 	generic/io/io.c \
 	generic/io/printf.c \
+	generic/io/log.c \
 	generic/io/klog.c \
 	generic/io/snprintf.c \
@@ -83,10 +94,11 @@
 	generic/io/console.c \
 	generic/io/screenbuffer.c \
-	generic/ipc/ns.c \
 	generic/malloc.c \
 	generic/sysinfo.c \
 	generic/ipc.c \
+	generic/ns.c \
+	generic/ns_obsolete.c \
 	generic/async.c \
-	generic/async_sess.c \
+	generic/async_obsolete.c \
 	generic/loader.c \
 	generic/getopt.c \
@@ -96,4 +108,5 @@
 	generic/adt/measured_strings.c \
 	generic/adt/char_map.c \
+	generic/adt/prodcons.c \
 	generic/time.c \
 	generic/stdlib.c \
@@ -112,5 +125,15 @@
 	generic/arg_parse.c \
 	generic/sort.c \
-	generic/stats.c
+	generic/stats.c \
+	generic/assert.c
+
+ifeq ($(CONFIG_RTLD),y)
+	GENERIC_SOURCES += \
+		generic/dlfcn.c \
+		generic/rtld/rtld.c \
+		generic/rtld/dynamic.c \
+		generic/rtld/module.c \
+		generic/rtld/symbol.c
+endif
 
 SOURCES = \
@@ -120,17 +143,21 @@
 include $(USPACE_PREFIX)/Makefile.common
 
-$(INCLUDE_ARCH): $(INCLUDE_KERNEL) $(INCLUDE_KERNEL)/arch
-	ln -sfn kernel/arch $@
-
 $(INCLUDE_LIBARCH): arch/$(UARCH)/include
 	ln -sfn ../$< $@
 
-$(INCLUDE_KERNEL)/arch: ../../../kernel/generic/include/arch $(INCLUDE_KERNEL)
-
-$(INCLUDE_KERNEL): ../../../kernel/generic/include/
+$(INCLUDE_ABI): ../../../abi/include/
 	ln -sfn ../$< $@
 
-$(LINKER_SCRIPT): $(LINKER_SCRIPT).in
+$(LIBC_PREFIX)/arch/$(UARCH)/_link.ld: $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld.in
 	$(GCC) $(DEFS) $(CFLAGS) -DLIBC_PATH=$(CURDIR) -E -x c $< | grep -v "^\#" > $@
+
+$(LIBC_PREFIX)/arch/$(UARCH)/_link-loader.ld: $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld.in
+	$(GCC) $(DEFS) $(CFLAGS) -DLIBC_PATH=$(CURDIR) -DLOADER -E -x c $< | grep -v "^\#" > $@
+
+$(LIBC_PREFIX)/arch/$(UARCH)/_link-shlib.ld: $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld.in
+	$(GCC) $(DEFS) $(CFLAGS) -DLIBC_PATH=$(CURDIR) -DSHLIB -E -x c $< | grep -v "^\#" > $@
+
+$(LIBC_PREFIX)/arch/$(UARCH)/_link-dlexe.ld: $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld.in
+	$(GCC) $(DEFS) $(CFLAGS) -DLIBC_PATH=$(CURDIR) -DDLEXE -E -x c $< | grep -v "^\#" > $@
 
 $(COMMON_HEADER_ARCH): $(COMMON_HEADER)
Index: uspace/lib/c/arch/abs32le/Makefile.inc
===================================================================
--- uspace/lib/c/arch/abs32le/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/abs32le/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,4 +29,5 @@
 ARCH_SOURCES = \
 	arch/$(UARCH)/src/entry.c \
+	arch/$(UARCH)/src/entryjmp.c \
 	arch/$(UARCH)/src/thread_entry.c \
 	arch/$(UARCH)/src/fibril.c \
Index: uspace/lib/c/arch/abs32le/_link.ld.in
===================================================================
--- uspace/lib/c/arch/abs32le/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/abs32le/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -3,14 +3,26 @@
 
 PHDRS {
+#ifdef LOADER
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+#else
 	text PT_LOAD FLAGS(5);
+#endif
 	data PT_LOAD FLAGS(6);
 }
 
 SECTIONS {
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x70001000 + SIZEOF_HEADERS;
+#else
 	. = 0x1000 + SIZEOF_HEADERS;
-	
+#endif
 	.text : {
-		*(.text);
-		*(.rodata*);
+		*(.text .text.*);
+		*(.rodata .rodata.*);
 	} :text
 	
Index: uspace/lib/c/arch/abs32le/include/barrier.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/abs32le/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/abs32le/include/barrier.h
Index: uspace/lib/c/arch/abs32le/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/abs32le/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/abs32le/include/context_offset.h
Index: uspace/lib/c/arch/abs32le/include/ddi.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/ddi.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/abs32le/include/ddi.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,4 +33,7 @@
 #define LIBC_abs32le_DDI_H_
 
+#include <sys/types.h>
+#include <libarch/types.h>
+
 static inline void pio_write_8(ioport8_t *port, uint8_t v)
 {
Index: uspace/lib/c/arch/abs32le/include/elf.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/abs32le/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/abs32le/include/elf.h
Index: uspace/lib/c/arch/abs32le/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/abs32le/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcabs32le
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_abs32le_ELF_LINUX_H_
+#define LBIC_abs32le_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+typedef struct {
+} elf_regs_t;
+
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	(void) istate; (void) elf_regs;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/abs32le/include/istate.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/abs32le/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 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.
- */
-
-/** @addtogroup debug
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_abs32le__ISTATE_H_
-#define LIBC_abs32le__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/abs32le/include/istate.h
Index: uspace/lib/c/arch/abs32le/include/syscall.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/syscall.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/abs32le/include/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 
 #define __syscall0  __syscall
Index: uspace/lib/c/arch/abs32le/src/entryjmp.c
===================================================================
--- uspace/lib/c/arch/abs32le/src/entryjmp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/abs32le/src/entryjmp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010 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 <bool.h>
+#include <entry_point.h>
+
+/** Jump to program entry point. */
+void entry_point_jmp(void *entry_point, void *pcb)
+{
+	while (true);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/c/arch/amd64/Makefile.inc
===================================================================
--- uspace/lib/c/arch/amd64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/amd64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,4 +29,5 @@
 ARCH_SOURCES = \
 	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
 	arch/$(UARCH)/src/syscall.S \
Index: uspace/lib/c/arch/amd64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/amd64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/amd64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -3,5 +3,10 @@
 
 PHDRS {
+#ifdef LOADER
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+#else
 	text PT_LOAD FLAGS(5);
+#endif
 	data PT_LOAD FLAGS(6);
 	debug PT_NOTE;
@@ -9,6 +14,13 @@
 
 SECTIONS {
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x70001000 + SIZEOF_HEADERS;
+#else
 	. = 0x1000 + SIZEOF_HEADERS;
-	
+#endif
 	.init : {
 		*(.init);
@@ -16,6 +28,6 @@
 	
 	.text : {
-		*(.text);
-		*(.rodata*);
+		*(.text .text.*);
+		*(.rodata .rodata.*);
 	} :text
 	
Index: uspace/lib/c/arch/amd64/include/barrier.h
===================================================================
--- uspace/lib/c/arch/amd64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/amd64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/amd64/include/barrier.h
Index: uspace/lib/c/arch/amd64/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/amd64/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/amd64/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/amd64/include/context_offset.h
Index: uspace/lib/c/arch/amd64/include/elf.h
===================================================================
--- uspace/lib/c/arch/amd64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/amd64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/amd64/include/elf.h
Index: uspace/lib/c/arch/amd64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/amd64/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/amd64/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcamd64
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_amd64_ELF_LINUX_H_
+#define LBIC_amd64_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint64_t r15;
+	uint64_t r14;
+	uint64_t r13;
+	uint64_t r12;
+	uint64_t rbp;
+	uint64_t rbx;
+	uint64_t r11;
+	uint64_t r10;
+	uint64_t r9;
+	uint64_t r8;
+	uint64_t rax;
+	uint64_t rcx;
+	uint64_t rdx;
+	uint64_t rsi;
+	uint64_t rdi;
+	uint64_t old_rax;
+	uint64_t rip;
+	uint64_t cs;
+	uint64_t rflags;
+	uint64_t rsp;
+	uint64_t ss;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->r15 = istate->r15;
+	elf_regs->r14 = istate->r14;
+	elf_regs->r13 = istate->r13;
+	elf_regs->r12 = istate->r12;
+	elf_regs->rbp = istate->rbp;
+	elf_regs->rbx = istate->rbx;
+	elf_regs->r11 = istate->r11;
+	elf_regs->r10 = istate->r10;
+	elf_regs->r9 = istate->r9;
+	elf_regs->r8 = istate->r8;
+	elf_regs->rax = istate->rax;
+	elf_regs->rcx = istate->rcx;
+	elf_regs->rdx = istate->rdx;
+	elf_regs->rsi = istate->rsi;
+	elf_regs->rdi = istate->rdi;
+	elf_regs->rip = istate->rip;
+	elf_regs->cs = istate->cs;
+	elf_regs->rflags = istate->rflags;
+	elf_regs->rsp = istate->rsp;
+	elf_regs->ss = istate->ss;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/amd64/include/istate.h
===================================================================
--- uspace/lib/c/arch/amd64/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/amd64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libcamd64
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_amd64_ISTATE_H_
-#define LIBC_amd64_ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/amd64/include/istate.h
Index: uspace/lib/c/arch/amd64/src/entryjmp.s
===================================================================
--- uspace/lib/c/arch/amd64/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/amd64/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+
+.globl entry_point_jmp
+
+## void entry_point_jmp(void *entry_point, void *pcb);
+#
+# %rdi	contains entry_point
+# %rsi	contains pcb
+#
+# Jump to program entry point
+entry_point_jmp:
+	# pcb must be passed in %rdi, use %rdx as a scratch register
+	mov %rdi, %rdx
+	mov %rsi, %rdi
+
+	# jump to entry point
+	jmp %rdx
Index: uspace/lib/c/arch/amd64/src/fibril.S
===================================================================
--- uspace/lib/c/arch/amd64/src/fibril.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/amd64/src/fibril.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,5 +32,5 @@
 .global context_restore
 
-#include <kernel/arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 ## Save current CPU context
Index: uspace/lib/c/arch/arm32/Makefile.inc
===================================================================
--- uspace/lib/c/arch/arm32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/arm32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,4 +30,5 @@
 ARCH_SOURCES = \
 	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
 	arch/$(UARCH)/src/syscall.c \
Index: uspace/lib/c/arch/arm32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/arm32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/arm32/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -3,11 +3,23 @@
 
 PHDRS {
+#ifdef LOADER
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+#else
 	text PT_LOAD FLAGS(5);
+#endif
 	data PT_LOAD FLAGS(6);
 }
 
 SECTIONS {
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x70001000 + SIZEOF_HEADERS;
+#else
 	. = 0x1000 + SIZEOF_HEADERS;
-	
+#endif
 	.init : {
 		*(.init);
@@ -15,6 +27,6 @@
 	
 	.text : {
-		*(.text);
-		*(.rodata*);
+		*(.text .text.*);
+		*(.rodata .rodata.*);
 	} :text
 	
Index: uspace/lib/c/arch/arm32/include/barrier.h
===================================================================
--- uspace/lib/c/arch/arm32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/arm32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/arm32/include/barrier.h
Index: uspace/lib/c/arch/arm32/include/elf.h
===================================================================
--- uspace/lib/c/arch/arm32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/arm32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/arm32/include/elf.h
Index: uspace/lib/c/arch/arm32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/arm32/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/arm32/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcarm32
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_arm32_ELF_LINUX_H_
+#define LBIC_arm32_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint32_t r0;
+	uint32_t r1;
+	uint32_t r2;
+	uint32_t r3;
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
+	uint32_t r9;
+	uint32_t r10;
+	uint32_t fp;
+	uint32_t r12;
+	uint32_t sp;
+	uint32_t lr;
+	uint32_t pc;
+	uint32_t cpsr;
+	uint32_t old_r0;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->r0 = istate->r0;
+	elf_regs->r1 = istate->r1;
+	elf_regs->r2 = istate->r2;
+	elf_regs->r3 = istate->r3;
+	elf_regs->r4 = istate->r4;
+	elf_regs->r5 = istate->r5;
+	elf_regs->r6 = istate->r6;
+	elf_regs->r7 = istate->r7;
+	elf_regs->r8 = istate->r8;
+	elf_regs->r9 = istate->r9;
+	elf_regs->r10 = istate->r10;
+
+	elf_regs->fp = istate->fp;
+	elf_regs->r12 = istate->r12;
+	elf_regs->sp = istate->sp;
+	elf_regs->lr = istate->lr;
+	elf_regs->pc = istate->pc;
+	elf_regs->cpsr = istate->spsr;
+	elf_regs->old_r0 = 0;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/arm32/include/istate.h
===================================================================
--- uspace/lib/c/arch/arm32/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/arm32/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libcarm32
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_arm32__ISTATE_H_
-#define LIBC_arm32__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/arm32/include/istate.h
Index: uspace/lib/c/arch/arm32/include/regutils.h
===================================================================
--- uspace/lib/c/arch/arm32/include/regutils.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/arm32/include/regutils.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/arm32/include/regutils.h
Index: uspace/lib/c/arch/arm32/src/entryjmp.s
===================================================================
--- uspace/lib/c/arch/arm32/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/arm32/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+.globl entry_point_jmp
+
+## void entry_point_jmp(void *entry_point, void *pcb);
+#
+# r0	contains entry_point
+# r1	contains pcb
+#
+# Jump to program entry point
+entry_point_jmp:
+	# load ras_page address to r2
+	ldr r2, =ras_page
+	ldr r2, [r2]
+	# pcb is passed to the entry point in r1 (where it already is)
+	mov r15, r0
Index: uspace/lib/c/arch/ia32/Makefile.common
===================================================================
--- uspace/lib/c/arch/ia32/Makefile.common	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/Makefile.common	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -28,5 +28,10 @@
 
 CLANG_ARCH = i386
-GCC_CFLAGS += -march=pentium
+
+ifeq ($(PROCESSOR),i486)
+	GCC_CFLAGS += -march=i486 -fno-omit-frame-pointer
+else
+	GCC_CFLAGS += -march=pentium -fno-omit-frame-pointer
+endif
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/ia32/Makefile.inc
===================================================================
--- uspace/lib/c/arch/ia32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -28,5 +28,6 @@
 
 ARCH_SOURCES = \
-	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entry.S \
+	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
 	arch/$(UARCH)/src/syscall.S \
@@ -35,5 +36,7 @@
 	arch/$(UARCH)/src/setjmp.S \
 	arch/$(UARCH)/src/stacktrace.c \
-	arch/$(UARCH)/src/stacktrace_asm.S
+	arch/$(UARCH)/src/stacktrace_asm.S \
+	arch/$(UARCH)/src/rtld/dynamic.c \
+	arch/$(UARCH)/src/rtld/reloc.c
 
 .PRECIOUS: arch/$(UARCH)/src/entry.o
Index: uspace/lib/c/arch/ia32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,14 +1,32 @@
+#ifndef SHLIB
 STARTUP(LIBC_PATH/arch/UARCH/src/entry.o)
 ENTRY(__entry)
+#endif
 
 PHDRS {
+#if defined(LOADER) || defined(DLEXE)
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+#else
 	text PT_LOAD FLAGS(5);
+#endif
 	data PT_LOAD FLAGS(6);
+#if defined(SHLIB) || defined(DLEXE)
+	dynamic PT_DYNAMIC;
+#endif
 	debug PT_NOTE;
 }
 
 SECTIONS {
+#if defined(LOADER) || defined(DLEXE)
+	.interp : {
+		*(.interp);
+	} :interp
+#endif
+#ifdef LOADER
+	. = 0x70001000 + SIZEOF_HEADERS;
+#else
 	. = 0x1000 + SIZEOF_HEADERS;
-	
+#endif
 	.init : {
 		*(.init);
@@ -16,9 +34,43 @@
 	
 	.text : {
-		*(.text);
-		*(.rodata*);
+		*(.text .text.*);
+		*(.rodata .rodata.*);
+	} :text
+
+#if defined(SHLIB) || defined(DLEXE)
+	.rel.plt : {
+		*(.rel.plt);
+	}
+	/* 
+	 *.rel.dyn MUST FOLLOW IMMEDIATELY after .rel.plt 
+	 * without alignment gap or DT_REL will be broken
+	 */
+	.rel.dyn : {
+		*(.rel.*);
 	} :text
 	
+	.plt : {
+		*(.plt);
+	} :text
+	
+	.dynsym : {
+		*(.dynsym);
+	} :text
+	
+	.dynstr : {
+		*(.dynstr);
+	} :text
+	
+	.hash : {
+		*(.hash);
+	} :text
+#endif
 	. = . + 0x1000;
+	
+#if defined(SHLIB) || defined(DLEXE)
+	.dynamic : {
+		*(.dynamic);
+	} :data :dynamic
+#endif
 	
 	.data : {
@@ -26,4 +78,18 @@
 	} :data
 	
+#if defined(SHLIB) || defined(DLEXE)
+	.data.rel : {
+                *(.data.rel .data.rel.*);
+	} :data
+
+	.got : {
+                *(.got);
+	} :data
+	.got.plt : {
+                *(.got.plt);
+	} :data
+#endif
+	
+#ifndef DLEXE
 	.tdata : {
 		_tdata_start = .;
@@ -37,6 +103,8 @@
 	
 	_tls_alignment = ALIGNOF(.tdata);
+#endif
 	
 	.bss : {
+		*(.dynbss);
 		*(COMMON);
 		*(.bss);
Index: uspace/lib/c/arch/ia32/include/barrier.h
===================================================================
--- uspace/lib/c/arch/ia32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia32/include/barrier.h
Index: uspace/lib/c/arch/ia32/include/config.h
===================================================================
--- uspace/lib/c/arch/ia32/include/config.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/include/config.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,9 @@
 #define LIBC_ia32_CONFIG_H_
 
-#define PAGE_WIDTH	12
-#define PAGE_SIZE	(1 << PAGE_WIDTH)
+#define PAGE_WIDTH  12
+#define PAGE_SIZE   (1 << PAGE_WIDTH)
+
+#define USER_ADDRESS_SPACE_START_ARCH  UINT32_C(0x00000000)
+#define USER_ADDRESS_SPACE_END_ARCH    UINT32_C(0x7fffffff)
 
 #endif
Index: uspace/lib/c/arch/ia32/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/ia32/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia32/include/context_offset.h
Index: uspace/lib/c/arch/ia32/include/ddi.h
===================================================================
--- uspace/lib/c/arch/ia32/include/ddi.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/include/ddi.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,9 +37,9 @@
 #include <libarch/types.h>
 
-#define IO_SPACE_BOUNDARY	((void *) (64 * 1024))
+#define IO_SPACE_BOUNDARY  ((void *) (64 * 1024))
 
 static inline uint8_t pio_read_8(ioport8_t *port)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
 		uint8_t val;
 		asm volatile (
@@ -56,5 +56,5 @@
 static inline uint16_t pio_read_16(ioport16_t *port)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
 		uint16_t val;
 		asm volatile (
@@ -71,5 +71,5 @@
 static inline uint32_t pio_read_32(ioport32_t *port)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
 		uint32_t val;
 		asm volatile (
@@ -86,5 +86,5 @@
 static inline void pio_write_8(ioport8_t *port, uint8_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outb %b[val], %w[port]\n"
@@ -92,5 +92,5 @@
 		);	
 	} else {
-		*((uint8_t *) port) = val;
+		*port = val;
 	}
 }
@@ -98,5 +98,5 @@
 static inline void pio_write_16(ioport16_t *port, uint16_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outw %w[val], %w[port]\n"
@@ -104,5 +104,5 @@
 		);
 	} else {
-		*((uint16_t *) port) = val;
+		*port = val;
 	}
 }
@@ -110,5 +110,5 @@
 static inline void pio_write_32(ioport32_t *port, uint32_t val)
 {
-	if (((void *)port) < IO_SPACE_BOUNDARY) {
+	if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
 		asm volatile (
 			"outl %[val], %w[port]\n"
@@ -116,5 +116,5 @@
 		);
 	} else {
-		*((uint32_t *) port) = val;
+		*port = val;
 	}
 }
Index: uspace/lib/c/arch/ia32/include/elf.h
===================================================================
--- uspace/lib/c/arch/ia32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia32/include/elf.h
Index: uspace/lib/c/arch/ia32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ia32/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcia32
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_ia32_ELF_LINUX_H_
+#define LBIC_ia32_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint32_t ebx;
+	uint32_t ecx;
+	uint32_t edx;
+	uint32_t esi;
+	uint32_t edi;
+	uint32_t ebp;
+	uint32_t eax;
+	uint32_t ds;
+	uint32_t es;
+	uint32_t fs;
+	uint32_t gs;
+	uint32_t old_eax;
+	uint32_t eip;
+	uint32_t cs;
+	uint32_t eflags;
+	uint32_t esp;
+	uint32_t ss;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->ebx = istate->ebx;
+	elf_regs->ecx = istate->ecx;
+	elf_regs->edx = istate->edx;
+	elf_regs->esi = istate->esi;
+	elf_regs->edi = istate->edi;
+	elf_regs->ebp = istate->ebp;
+	elf_regs->eax = istate->eax;
+
+	elf_regs->ds = istate->ds;
+	elf_regs->es = istate->es;
+	elf_regs->fs = istate->fs;
+	elf_regs->gs = istate->gs;
+
+	elf_regs->old_eax = 0;
+	elf_regs->eip = istate->eip;
+	elf_regs->cs = istate->cs;
+	elf_regs->eflags = istate->eflags;
+	elf_regs->esp = istate->esp;
+	elf_regs->ss = istate->ss;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/ia32/include/faddr.h
===================================================================
--- uspace/lib/c/arch/ia32/include/faddr.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/include/faddr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 #include <libarch/types.h>
 
-#define FADDR(fptr)		((uintptr_t) (fptr))
+#define FADDR(fptr)  ((uintptr_t) (fptr))
 
 #endif
Index: uspace/lib/c/arch/ia32/include/fibril.h
===================================================================
--- uspace/lib/c/arch/ia32/include/fibril.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/include/fibril.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,5 +42,5 @@
  * panic sooner or later
  */
-#define SP_DELTA     (12)
+#define SP_DELTA  12
 
 #define context_set(c, _pc, stack, size, ptls) \
@@ -51,6 +51,7 @@
 		(c)->ebp = 0; \
 	} while (0)
-	
-/* We include only registers that must be preserved
+
+/*
+ * We include only registers that must be preserved
  * during function call
  */
Index: uspace/lib/c/arch/ia32/include/istate.h
===================================================================
--- uspace/lib/c/arch/ia32/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup debug
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ia32__ISTATE_H_
-#define LIBC_ia32__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/ia32/include/istate.h
Index: uspace/lib/c/arch/ia32/include/rtld/dynamic.h
===================================================================
--- uspace/lib/c/arch/ia32/include/rtld/dynamic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/include/rtld/dynamic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,47 @@
+/*
+ * 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 generic	
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ia32_RTLD_DYNAMIC_H_
+#define LIBC_ia32_RTLD_DYNAMIC_H_
+
+#include <sys/types.h>
+
+typedef struct {
+	/* Empty. */
+} dyn_info_arch_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/ia32/include/rtld/elf_dyn.h
===================================================================
--- uspace/lib/c/arch/ia32/include/rtld/elf_dyn.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/include/rtld/elf_dyn.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * 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 generic	
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ia32_RTLD_ELF_DYN_H_
+#define LIBC_ia32_RTLD_ELF_DYN_H_
+
+/* 
+ * ia32 dynamic relocation types
+ */
+
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JUMP_SLOT	7
+#define R_386_RELATIVE	8
+
+#define R_386_TLS_DTPMOD32 35
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/ia32/include/syscall.h
===================================================================
--- uspace/lib/c/arch/ia32/include/syscall.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/include/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 
 #define __syscall0  __syscall_fast_func
Index: uspace/lib/c/arch/ia32/src/entry.S
===================================================================
--- uspace/lib/c/arch/ia32/src/entry.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/src/entry.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2005 Martin Decky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+INTEL_CPUID_STANDARD = 1
+INTEL_SEP = 11
+
+.section .init, "ax"
+
+.org 0
+
+.globl __entry
+
+## User-space task entry point
+#
+# %edi contains the PCB pointer
+#
+__entry:
+	mov %ss, %ax
+	mov %ax, %ds
+	mov %ax, %es
+	mov %ax, %fs
+	# Do not set %gs, it contains descriptor that can see TLS
+	
+#ifndef PROCESSOR_i486	
+	# Detect the mechanism used for making syscalls
+	movl $(INTEL_CPUID_STANDARD), %eax
+	cpuid
+	bt $(INTEL_SEP), %edx
+	jnc 0f
+		leal __syscall_fast_func, %eax
+		movl $__syscall_fast, (%eax)
+	0:
+#endif
+	
+	#
+	# Create the first stack frame.
+	#
+	pushl $0
+	movl %esp, %ebp
+	
+	# Pass the PCB pointer to __main as the first argument
+	pushl %edi
+	call __main
Index: pace/lib/c/arch/ia32/src/entry.s
===================================================================
--- uspace/lib/c/arch/ia32/src/entry.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,65 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-INTEL_CPUID_STANDARD = 1
-INTEL_SEP = 11
-
-.section .init, "ax"
-
-.org 0
-
-.globl __entry
-
-## User-space task entry point
-#
-# %edi contains the PCB pointer
-#
-__entry:
-	mov %ss, %ax
-	mov %ax, %ds
-	mov %ax, %es
-	mov %ax, %fs
-	# Do not set %gs, it contains descriptor that can see TLS
-	
-	# Detect the mechanism used for making syscalls
-	movl $(INTEL_CPUID_STANDARD), %eax
-	cpuid
-	bt $(INTEL_SEP), %edx
-	jnc 0f
-	leal __syscall_fast_func, %eax
-	movl $__syscall_fast, (%eax)
-0:
-	#
-	# Create the first stack frame.
-	#
-	pushl $0
-	movl %esp, %ebp
-	
-	# Pass the PCB pointer to __main as the first argument
-	pushl %edi
-	call __main
Index: uspace/lib/c/arch/ia32/src/entryjmp.s
===================================================================
--- uspace/lib/c/arch/ia32/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+.globl entry_point_jmp
+
+## void entry_point_jmp(void *entry_point, void *pcb);
+#
+# Jump to program entry point
+entry_point_jmp:
+	# Use standard ia32 prologue not to confuse anybody
+	push %ebp
+	movl %esp, %ebp
+
+	# %eax := entry_point
+	movl 0x8(%ebp), %eax
+
+	# %edi := pcb
+	# pcb is passed to the entry point in %edi
+	mov 0xc(%ebp), %edi
+
+	# Save a tiny bit of stack space
+	pop %ebp
+
+	jmp *%eax
Index: uspace/lib/c/arch/ia32/src/fibril.S
===================================================================
--- uspace/lib/c/arch/ia32/src/fibril.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/src/fibril.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
 #
 
-#include <kernel/arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 .text
Index: uspace/lib/c/arch/ia32/src/rtld/dynamic.c
===================================================================
--- uspace/lib/c/arch/ia32/src/rtld/dynamic.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/src/rtld/dynamic.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+/*
+ * 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 libcia32
+ * @brief
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtld/elf_dyn.h>
+#include <rtld/dynamic.h>
+
+void dyn_parse_arch(elf_dyn_t *dp, size_t bias, dyn_info_t *info)
+{
+	(void) dp;
+	(void) bias;
+	(void) info;
+}
+
+/** @}
+ */
Index: uspace/lib/c/arch/ia32/src/rtld/reloc.c
===================================================================
--- uspace/lib/c/arch/ia32/src/rtld/reloc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia32/src/rtld/reloc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,182 @@
+/*
+ * 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 libcia32
+ * @brief
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libarch/rtld/elf_dyn.h>
+#include <rtld/symbol.h>
+#include <rtld/rtld.h>
+#include <rtld/rtld_debug.h>
+#include <rtld/rtld_arch.h>
+
+void module_process_pre_arch(module_t *m)
+{
+	/* Unused */
+}
+
+
+/**
+ * Process (fixup) all relocations in a relocation table.
+ */
+void rel_table_process(module_t *m, elf_rel_t *rt, size_t rt_size)
+{
+	unsigned i;
+
+	size_t rt_entries;
+	size_t r_offset;
+	elf_word r_info;
+	unsigned rel_type;
+	elf_word sym_idx;
+	uint32_t sym_addr;
+	
+	elf_symbol_t *sym_table;
+	elf_symbol_t *sym;
+	uint32_t *r_ptr;
+	uint32_t sym_size;
+	char *str_tab;
+	
+	elf_symbol_t *sym_def;
+	module_t *dest;
+
+	DPRINTF("parse relocation table\n");
+
+	sym_table = m->dyn.sym_tab;
+	rt_entries = rt_size / sizeof(elf_rel_t);
+	str_tab = m->dyn.str_tab;
+
+	DPRINTF("address: 0x%x, entries: %d\n", (uintptr_t)rt, rt_entries);
+	
+	for (i = 0; i < rt_entries; ++i) {
+//		DPRINTF("symbol %d: ", i);
+		r_offset = rt[i].r_offset;
+		r_info = rt[i].r_info;
+
+		sym_idx = ELF32_R_SYM(r_info);
+		sym = &sym_table[sym_idx];
+
+/*		DPRINTF("name '%s', value 0x%x, size 0x%x\n",
+		    str_tab + sym->st_name,
+		    sym->st_value,
+		    sym->st_size);
+*/
+		rel_type = ELF32_R_TYPE(r_info);
+		r_ptr = (uint32_t *)(r_offset + m->bias);
+
+		if (sym->st_name != 0) {
+//			DPRINTF("rel_type: %x, rel_offset: 0x%x\n", rel_type, r_offset);
+			sym_def = symbol_def_find(str_tab + sym->st_name,
+			    m, &dest);
+//			DPRINTF("dest name: '%s'\n", dest->dyn.soname);
+//			DPRINTF("dest bias: 0x%x\n", dest->bias);
+			if (sym_def) {
+				sym_addr = (uint32_t)
+				    symbol_get_addr(sym_def, dest);
+//				DPRINTF("symbol definition found, addr=0x%x\n", sym_addr);
+			} else {
+				printf("Definition of '%s' not found.\n",
+				    str_tab + sym->st_name);
+				continue;
+			}
+		} else {
+			sym_addr = 0;
+			sym_def = NULL;
+		}
+
+		switch (rel_type) {
+		case R_386_GLOB_DAT:
+		case R_386_JUMP_SLOT:
+			DPRINTF("fixup R_386_GLOB_DAT/JUMP_SLOT (b+v)\n");
+			*r_ptr = sym_addr;
+			break;
+
+		case R_386_32:
+			DPRINTF("fixup R_386_32 (b+v+a)\n");
+			*r_ptr += sym_addr;
+			break;
+
+		case R_386_PC32:
+			DPRINTF("fixup R_386_PC32 (b+v+a-p)\n");
+			*r_ptr += sym_addr - (uint32_t) r_ptr;
+			break;
+
+		case R_386_COPY:
+			/*
+			 * Copy symbol data from shared object to specified
+			 * location.
+			 */
+			DPRINTF("fixup R_386_COPY (s)\n");
+			sym_size = sym->st_size;
+			if (sym_size != sym_def->st_size) {
+				printf("Warning: Mismatched symbol sizes.\n");
+				/* Take the lower value. */
+				if (sym_size > sym_def->st_size)
+					sym_size = sym_def->st_size;
+			}
+			memcpy(r_ptr, (const void *)sym_addr, sym_size);
+			break;
+			
+		case R_386_RELATIVE:
+			DPRINTF("fixup R_386_RELATIVE (b+a)\n");
+			*r_ptr += m->bias;
+			break;
+
+		case R_386_TLS_DTPMOD32:
+			/*
+			 * We can ignore this as long as the only module
+			 * with TLS variables is libc.so.
+			 */
+			DPRINTF("Ignoring R_386_TLS_DTPMOD32\n");
+			break;
+
+		default:
+			printf("Error: Unknown relocation type %d\n",
+			    rel_type);
+			exit(1);
+		}
+
+	}
+
+}
+
+void rela_table_process(module_t *m, elf_rela_t *rt, size_t rt_size)
+{
+	/* Unused */
+	(void)m; (void)rt; (void)rt_size;
+}
+
+/** @}
+ */
Index: uspace/lib/c/arch/ia32/src/setjmp.S
===================================================================
--- uspace/lib/c/arch/ia32/src/setjmp.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/src/setjmp.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
 #
 
-#include <kernel/arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 .text
Index: uspace/lib/c/arch/ia32/src/stacktrace.c
===================================================================
--- uspace/lib/c/arch/ia32/src/stacktrace.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/src/stacktrace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,16 +35,16 @@
  */
 
+#include <libarch/config.h>
 #include <sys/types.h>
 #include <bool.h>
-
 #include <stacktrace.h>
 
-#define FRAME_OFFSET_FP_PREV	0
-#define FRAME_OFFSET_RA		4
+#define FRAME_OFFSET_FP_PREV  0
+#define FRAME_OFFSET_RA       4
 
 bool stacktrace_fp_valid(stacktrace_t *st, uintptr_t fp)
 {
 	(void) st;
-	return fp != 0;
+	return (fp != 0) && (fp <= USER_ADDRESS_SPACE_END_ARCH);
 }
 
Index: uspace/lib/c/arch/ia32/src/syscall.S
===================================================================
--- uspace/lib/c/arch/ia32/src/syscall.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/src/syscall.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,4 +32,5 @@
 __syscall_fast_func:
 	.long __syscall_slow
+	.size __syscall_fast_func, . - __syscall_fast_func
 
 .text
@@ -71,4 +72,6 @@
  */
 .global __syscall_fast
+	.type __syscall_fast, @function
+
 __syscall_fast:
 	pushl %ebx
@@ -95,2 +98,4 @@
 	popl %ebx
 	ret
+
+	.size __syscall_fast, . - __syscall_fast
Index: uspace/lib/c/arch/ia32/src/tls.c
===================================================================
--- uspace/lib/c/arch/ia32/src/tls.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia32/src/tls.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,5 @@
 #include <tls.h>
 #include <sys/types.h>
+#include <align.h>
 
 tcb_t * __alloc_tls(void **data, size_t size)
@@ -48,4 +49,31 @@
 }
 
+/*
+ * Rtld TLS support
+ */
+
+typedef struct {
+	unsigned long int ti_module;
+	unsigned long int ti_offset;
+} tls_index;
+
+void __attribute__ ((__regparm__ (1)))
+    *___tls_get_addr(tls_index *ti);
+
+void __attribute__ ((__regparm__ (1)))
+    *___tls_get_addr(tls_index *ti)
+{
+	size_t tls_size;
+	uint8_t *tls;
+
+	/* Calculate size of TLS block */
+	tls_size = ALIGN_UP(&_tbss_end - &_tdata_start, &_tls_alignment);
+
+	/* The TLS block is just before TCB */
+	tls = (uint8_t *)__tcb_get() - tls_size;
+
+	return tls + ti->ti_offset;
+}
+
 /** @}
  */
Index: uspace/lib/c/arch/ia64/Makefile.inc
===================================================================
--- uspace/lib/c/arch/ia64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,4 +29,5 @@
 ARCH_SOURCES = \
 	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
 	arch/$(UARCH)/src/syscall.S \
Index: uspace/lib/c/arch/ia64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ia64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -3,11 +3,29 @@
 
 PHDRS {
+#ifdef LOADER
+	interp PT_INTERP;
 	text PT_LOAD FLAGS(5);
+#else
+	text PT_LOAD FLAGS(5);
+#endif
 	data PT_LOAD FLAGS(6);
 }
 
 SECTIONS {
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x800000000 + SIZEOF_HEADERS;
+#else
 	. = 0x4000 + SIZEOF_HEADERS;
-	
+#endif
+	/*
+	 * XXX This is just a work around. Problem: .init section does not
+	 * have the proper alignment.
+	 */
+	. = ALIGN(., 16);
+
 	.init : {
 		*(.init);
@@ -15,6 +33,6 @@
 	
 	.text : {
-		*(.text);
-		*(.rodata*);
+		*(.text .text.*);
+		*(.rodata .rodata.*);
 	} :text
 	
@@ -22,6 +40,7 @@
 	
 	.got : {
-		_gp = .;
-		*(.got*);
+		/* Tell the linker where we expect GP to point. */
+		__gp = .;
+		*(.got .got.*);
 	} :data
 	
Index: uspace/lib/c/arch/ia64/include/barrier.h
===================================================================
--- uspace/lib/c/arch/ia64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia64/include/barrier.h
Index: uspace/lib/c/arch/ia64/include/elf.h
===================================================================
--- uspace/lib/c/arch/ia64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia64/include/elf.h
Index: uspace/lib/c/arch/ia64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ia64/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia64/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcia64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ia64_ELF_LINUX_H_
+#define LBIC_ia64_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+typedef struct {
+	/* TODO */
+	uint64_t pad[16];
+} elf_regs_t;
+
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	/* TODO */
+	(void) istate; (void) elf_regs;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/ia64/include/istate.h
===================================================================
--- uspace/lib/c/arch/ia64/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libcsparc64
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ia64_ISTATE_H_
-#define LIBC_ia64_ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/ia64/include/istate.h
Index: uspace/lib/c/arch/ia64/include/register.h
===================================================================
--- uspace/lib/c/arch/ia64/include/register.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia64/include/register.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ia64/include/register.h
Index: uspace/lib/c/arch/ia64/src/entry.s
===================================================================
--- uspace/lib/c/arch/ia64/src/entry.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia64/src/entry.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,5 @@
 __entry:
 	alloc loc0 = ar.pfs, 0, 1, 2, 0
-	movl gp = _gp
+	movl gp = __gp
 	
 	# Pass PCB pointer as the first argument to __main
Index: uspace/lib/c/arch/ia64/src/entryjmp.s
===================================================================
--- uspace/lib/c/arch/ia64/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ia64/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+
+.text
+.globl entry_point_jmp
+
+## void entry_point_jmp(void *entry_point, void *pcb);
+#
+# in0 (r32)	contains entry_point
+# in1 (r33)	contains pcb
+#
+# Jump to program entry point
+entry_point_jmp:
+	# Pass pcb to the entry point in r2
+
+	mov b6 = r32
+	mov r2 = r33 ;;
+	br b6 ;;
Index: uspace/lib/c/arch/ia64/src/thread_entry.s
===================================================================
--- uspace/lib/c/arch/ia64/src/thread_entry.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ia64/src/thread_entry.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 	alloc loc0 = ar.pfs, 0, 1, 1, 0
 
-	movl gp = _gp
+	movl gp = __gp
 	
 	#
Index: uspace/lib/c/arch/mips32/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips32/Makefile.common	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/Makefile.common	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
 #
 
-GCC_CFLAGS += -mips3
+GCC_CFLAGS += -mips3 -mabi=32
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/mips32/Makefile.inc
===================================================================
--- uspace/lib/c/arch/mips32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,4 +29,5 @@
 ARCH_SOURCES = \
 	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
 	arch/$(UARCH)/src/syscall.c \
Index: uspace/lib/c/arch/mips32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -3,11 +3,23 @@
 
 PHDRS {
+#ifdef LOADER
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+#else
 	text PT_LOAD FLAGS(5);
+#endif
 	data PT_LOAD FLAGS(6);
 }
 
 SECTIONS {
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x70004000 + SIZEOF_HEADERS;
+#else
 	. = 0x4000 + SIZEOF_HEADERS;
-	
+#endif
 	.init : {
 		*(.init);
@@ -15,6 +27,6 @@
 	
 	.text : {
-		*(.text);
-		*(.rodata*);
+		*(.text .text.*);
+		*(.rodata .rodata.*);
 	} :text
 	
Index: uspace/lib/c/arch/mips32/include/atomic.h
===================================================================
--- uspace/lib/c/arch/mips32/include/atomic.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/include/atomic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @ingroup libcmips32eb
+ * @ingroup libcmips32
  */
 
@@ -70,5 +70,4 @@
 		"	sc %0, %1\n"
 		"	beq %0, %4, 1b\n"	/* if the atomic operation failed, try again */
-		/*	nop	*/		/* nop is inserted automatically by compiler */
 		"	nop\n"
 		: "=&r" (tmp),
Index: uspace/lib/c/arch/mips32/include/barrier.h
===================================================================
--- uspace/lib/c/arch/mips32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/barrier.h
Index: uspace/lib/c/arch/mips32/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/mips32/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/context_offset.h
Index: uspace/lib/c/arch/mips32/include/cp0.h
===================================================================
--- uspace/lib/c/arch/mips32/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/cp0.h
Index: uspace/lib/c/arch/mips32/include/elf.h
===================================================================
--- uspace/lib/c/arch/mips32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/elf.h
Index: uspace/lib/c/arch/mips32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/mips32/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips32
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_mips32_ELF_LINUX_H_
+#define LBIC_mips32_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint32_t pad0[6];
+
+	uint32_t r0;
+	uint32_t r1;
+	uint32_t r2;
+	uint32_t r3;
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
+	uint32_t r9;
+	uint32_t r10;
+	uint32_t r11;
+	uint32_t r12;
+	uint32_t r13;
+	uint32_t r14;
+	uint32_t r15;
+	uint32_t r16;
+	uint32_t r17;
+	uint32_t r18;
+	uint32_t r19;
+	uint32_t r20;
+	uint32_t r21;
+	uint32_t r22;
+	uint32_t r23;
+	uint32_t r24;
+	uint32_t r25;
+	uint32_t r26;
+	uint32_t r27;
+	uint32_t r28;
+	uint32_t r29;
+	uint32_t r30;
+	uint32_t r31;
+
+	uint32_t cp0_status;
+	uint32_t hi;
+	uint32_t lo;
+	uint32_t cp0_badvaddr;
+	uint32_t cp0_cause;
+	uint32_t cp0_epc;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->r1 = istate->at;
+	elf_regs->r2 = istate->v0;
+	elf_regs->r3 = istate->v1;
+	elf_regs->r4 = istate->a0;
+	elf_regs->r5 = istate->a1;
+	elf_regs->r6 = istate->a2;
+	elf_regs->r7 = istate->a3;
+	elf_regs->r8 = istate->t0;
+	elf_regs->r9 = istate->t1;
+	elf_regs->r10 = istate->t2;
+	elf_regs->r11 = istate->t3;
+	elf_regs->r12 = istate->t4;
+	elf_regs->r13 = istate->t5;
+	elf_regs->r14 = istate->t6;
+	elf_regs->r15 = istate->t7;
+	elf_regs->r16 = istate->s0;
+	elf_regs->r17 = istate->s1;
+	elf_regs->r18 = istate->s2;
+	elf_regs->r19 = istate->s3;
+	elf_regs->r20 = istate->s4;
+	elf_regs->r21 = istate->s5;
+	elf_regs->r22 = istate->s6;
+	elf_regs->r23 = istate->s7;
+	elf_regs->r24 = istate->t8;
+	elf_regs->r25 = istate->t9;
+	elf_regs->r26 = istate->kt0;
+	elf_regs->r27 = istate->kt1;
+	elf_regs->r28 = istate->gp;
+	elf_regs->r29 = istate->sp;
+	elf_regs->r30 = istate->s8;
+	elf_regs->r31 = istate->ra;
+
+	elf_regs->cp0_status = istate->status;
+	elf_regs->hi = istate->hi;
+	elf_regs->lo = istate->lo;
+	elf_regs->cp0_epc = istate->epc;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips32/include/fibril.h
===================================================================
--- uspace/lib/c/arch/mips32/include/fibril.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/include/fibril.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,9 +27,9 @@
  */
 
-/** @addtogroup libcmips32	
+/** @addtogroup libcmips32
  * @{
  */
 /** @file
- * @ingroup libcmips32eb	
+ * @ingroup libcmips32
  */
 
Index: uspace/lib/c/arch/mips32/include/istate.h
===================================================================
--- uspace/lib/c/arch/mips32/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libcmips32
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_mips32__ISTATE_H_
-#define LIBC_mips32__ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/mips32/include/istate.h
Index: uspace/lib/c/arch/mips32/include/regname.h
===================================================================
--- uspace/lib/c/arch/mips32/include/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32/include/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips32/include/asm/regname.h
Index: uspace/lib/c/arch/mips32/include/thread.h
===================================================================
--- uspace/lib/c/arch/mips32/include/thread.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/include/thread.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,9 +27,9 @@
  */
 
-/** @addtogroup libcmips32	
+/** @addtogroup libcmips32
  * @{
  */
 /** @file
- * @ingroup libcmips32eb	
+ * @ingroup libcmips32
  */
 
Index: uspace/lib/c/arch/mips32/include/tls.h
===================================================================
--- uspace/lib/c/arch/mips32/include/tls.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/include/tls.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,9 +27,9 @@
  */
 
-/** @addtogroup libcmips32	
+/** @addtogroup libcmips32
  * @{
  */
 /** @file
- * @ingroup libcmips32eb	
+ * @ingroup libcmips32
  */
 
Index: uspace/lib/c/arch/mips32/include/types.h
===================================================================
--- uspace/lib/c/arch/mips32/include/types.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @ingroup libcmips32eb
+ * @ingroup libcmips32
  */
 
Index: uspace/lib/c/arch/mips32/src/entryjmp.s
===================================================================
--- uspace/lib/c/arch/mips32/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+.text
+.section .text
+.global entry_point_jmp
+.set noreorder
+
+## void entry_point_jmp(void *entry_point, void *pcb);
+#
+# $a0 (=$4)	contains entry_point
+# $a1 (=$5)	contains pcb
+#
+# Jump to program entry point
+.ent entry_point_jmp
+entry_point_jmp:
+	# tmp := entry_point
+	move $25, $a0
+
+	# Pass pcb to the entry point in $a0
+	move $a0, $a1
+	jr $25
+	nop
+.end
Index: uspace/lib/c/arch/mips32/src/fibril.S
===================================================================
--- uspace/lib/c/arch/mips32/src/fibril.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/src/fibril.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,5 +32,5 @@
 .set noreorder
 
-#include <arch/context_offset.h>
+#include <libarch/context_offset.h>
 	
 .global context_save
Index: uspace/lib/c/arch/mips32/src/syscall.c
===================================================================
--- uspace/lib/c/arch/mips32/src/syscall.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/src/syscall.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,9 +27,9 @@
  */
 
- /** @addtogroup libcmips32
+/** @addtogroup libcmips32
  * @{
  */
 /** @file
-  * @ingroup libcmips32eb	
+  * @ingroup libcmips32
  */
 
@@ -64,5 +64,4 @@
 }
 
- /** @}
+/** @}
  */
-
Index: uspace/lib/c/arch/mips32/src/tls.c
===================================================================
--- uspace/lib/c/arch/mips32/src/tls.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32/src/tls.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,9 +27,9 @@
  */
 
-/** @addtogroup libcmips32	
+/** @addtogroup libcmips32
  * @{
  */
 /** @file
- * @ingroup libcmips32eb	
+ * @ingroup libcmips32
  */
 
Index: uspace/lib/c/arch/mips32eb/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips32eb/Makefile.common	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32eb/Makefile.common	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
 #
 
-GCC_CFLAGS += -mips3
+GCC_CFLAGS += -mips3 -mabi=32
 
 ENDIANESS = BE
Index: uspace/lib/c/arch/mips32eb/Makefile.inc
===================================================================
--- uspace/lib/c/arch/mips32eb/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/mips32eb/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,4 +29,5 @@
 ARCH_SOURCES = \
 	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
 	arch/$(UARCH)/src/syscall.c \
Index: uspace/lib/c/arch/mips32eb/include/barrier.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32eb/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/barrier.h
Index: uspace/lib/c/arch/mips32eb/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32eb/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/context_offset.h
Index: uspace/lib/c/arch/mips32eb/include/cp0.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32eb/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/cp0.h
Index: uspace/lib/c/arch/mips32eb/include/elf.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32eb/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/elf.h
Index: uspace/lib/c/arch/mips32eb/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32eb/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/elf_linux.h
Index: uspace/lib/c/arch/mips32eb/include/regname.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips32eb/include/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../mips32/include/regname.h
Index: uspace/lib/c/arch/mips64/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips64/Makefile.common	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/Makefile.common	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2005 Martin Decky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+GCC_CFLAGS += -mips3 -mabi=64
+AFLAGS = -64
+
+ENDIANESS = LE
+
+BFD_ARCH = mips:4000
+BFD_NAME = elf64-tradlittlemips
Index: uspace/lib/c/arch/mips64/Makefile.inc
===================================================================
--- uspace/lib/c/arch/mips64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2005 Martin Decky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+ARCH_SOURCES = \
+	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entryjmp.s \
+	arch/$(UARCH)/src/thread_entry.s \
+	arch/$(UARCH)/src/syscall.c \
+	arch/$(UARCH)/src/fibril.S \
+	arch/$(UARCH)/src/tls.c \
+	arch/$(UARCH)/src/stacktrace.c \
+	arch/$(UARCH)/src/stacktrace_asm.S
+
+.PRECIOUS: arch/$(UARCH)/src/entry.o
Index: uspace/lib/c/arch/mips64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/mips64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,73 @@
+OUTPUT_FORMAT(elf64-tradlittlemips)
+STARTUP(LIBC_PATH/arch/UARCH/src/entry.o)
+ENTRY(__entry)
+
+PHDRS {
+#ifdef LOADER
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+#else
+	text PT_LOAD FLAGS(5);
+#endif
+	data PT_LOAD FLAGS(6);
+}
+
+SECTIONS {
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x70004000 + SIZEOF_HEADERS;
+#else
+	. = 0x4000 + SIZEOF_HEADERS;
+#endif
+	.init : {
+		*(.init);
+	} :text
+	
+	.text : {
+		*(.text .text.*);
+		*(.rodata .rodata.*);
+	} :text
+	
+	. = . + 0x4000;
+	
+	.data : {
+		*(.data);
+		*(.data.rel*);
+	} :data
+	
+	.got : {
+		_gp = .;
+		*(.got);
+	} :data
+	
+	.tdata : {
+		_tdata_start = .;
+		*(.tdata);
+		_tdata_end = .;
+	} :data
+	
+	.tbss : {
+		_tbss_start = .;
+		*(.tbss);
+		_tbss_end = .;
+	} :data
+	
+	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
+	
+	.sbss : {
+		*(.scommon);
+		*(.sbss);
+	}
+	
+	.bss : {
+		*(.bss);
+		*(COMMON);
+	} :data
+	
+	/DISCARD/ : {
+		*(*);
+	}
+}
Index: uspace/lib/c/arch/mips64/include/atomic.h
===================================================================
--- uspace/lib/c/arch/mips64/include/atomic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/atomic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+ * @ingroup libcmips64
+ */
+
+#ifndef LIBC_mips64_ATOMIC_H_
+#define LIBC_mips64_ATOMIC_H_
+
+#define LIBC_ARCH_ATOMIC_H_
+
+#include <atomicdflt.h>
+
+#define atomic_inc(x)  ((void) atomic_add(x, 1))
+#define atomic_dec(x)  ((void) atomic_add(x, -1))
+
+#define atomic_postinc(x)  (atomic_add(x, 1) - 1)
+#define atomic_postdec(x)  (atomic_add(x, -1) + 1)
+
+#define atomic_preinc(x)  atomic_add(x, 1)
+#define atomic_predec(x)  atomic_add(x, -1)
+
+/* Atomic addition of immediate value.
+ *
+ * @param val Memory location to which will be the immediate value added.
+ * @param i   Signed immediate that will be added to *val.
+ *
+ * @return Value after addition.
+ *
+ */
+static inline atomic_count_t atomic_add(atomic_t *val, atomic_count_t i)
+{
+	atomic_count_t tmp;
+	atomic_count_t v;
+	
+	asm volatile (
+		"1:\n"
+		"	lld %0, %1\n"
+		"	daddu %0, %0, %3\n"  /* same as add, but never traps on overflow */
+		"	move %2, %0\n"
+		"	scd %0, %1\n"
+		"	beq %0, %4, 1b\n"    /* if the atomic operation failed, try again */
+		"	nop\n"
+		: "=&r" (tmp),
+		  "+m" (val->count),
+		  "=&r" (v)
+		: "r" (i),
+		  "i" (0)
+	);
+	
+	return v;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/barrier.h
===================================================================
--- uspace/lib/c/arch/mips64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/barrier.h
Index: uspace/lib/c/arch/mips64/include/config.h
===================================================================
--- uspace/lib/c/arch/mips64/include/config.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/config.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2006 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 libcmips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_mips64_CONFIG_H_
+#define LIBC_mips64_CONFIG_H_
+
+#define PAGE_WIDTH  14
+#define PAGE_SIZE   (1 << PAGE_WIDTH)
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/mips64/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/context_offset.h
Index: uspace/lib/c/arch/mips64/include/cp0.h
===================================================================
--- uspace/lib/c/arch/mips64/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/cp0.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/cp0.h
Index: uspace/lib/c/arch/mips64/include/ddi.h
===================================================================
--- uspace/lib/c/arch/mips64/include/ddi.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/ddi.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+/** @file
+ * @ingroup libcmips64
+ */
+
+#ifndef LIBC_mips64_DDI_H_
+#define LIBC_mips64_DDI_H_
+
+#include <sys/types.h>
+#include <libarch/types.h>
+
+static inline void pio_write_8(ioport8_t *port, uint8_t v)
+{
+	*port = v;
+}
+
+static inline void pio_write_16(ioport16_t *port, uint16_t v)
+{
+	*port = v;
+}
+
+static inline void pio_write_32(ioport32_t *port, uint32_t v)
+{
+	*port = v;
+}
+
+static inline uint8_t pio_read_8(ioport8_t *port)
+{
+	return *port;
+}
+
+static inline uint16_t pio_read_16(ioport16_t *port)
+{
+	return *port;
+}
+
+static inline uint32_t pio_read_32(ioport32_t *port)
+{
+	return *port;
+}
+
+#endif
Index: uspace/lib/c/arch/mips64/include/elf.h
===================================================================
--- uspace/lib/c/arch/mips64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/elf.h
Index: uspace/lib/c/arch/mips64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/mips64/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_mips64_ELF_LINUX_H_
+#define LBIC_mips64_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+typedef struct {
+	/* TODO */
+	uint64_t pad[16];
+} elf_regs_t;
+
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	/* TODO */
+	(void) istate; (void) elf_regs;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/faddr.h
===================================================================
--- uspace/lib/c/arch/mips64/include/faddr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/faddr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_mips64_FADDR_H_
+#define LIBC_mips64_FADDR_H_
+
+#include <libarch/types.h>
+
+#define FADDR(fptr)  ((uintptr_t) (fptr))
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/fibril.h
===================================================================
--- uspace/lib/c/arch/mips64/include/fibril.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/fibril.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+ * @ingroup libcmips64
+ */
+
+#ifndef LIBC_mips64_FIBRIL_H_
+#define LIBC_mips64_FIBRIL_H_
+
+#include <sys/types.h>
+
+/* We define our own context_set, because we need to set
+ * the TLS pointer to the tcb+0x7000
+ *
+ * See tls_set in thread.h
+ */
+#define context_set(c, _pc, stack, size, ptls) \
+	(c)->pc = (sysarg_t) (_pc); \
+	(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
+	(c)->tls = ((sysarg_t)(ptls)) + 0x7000 + sizeof(tcb_t);
+
+/* +16 is just for sure that the called function
+ * have space to store it's arguments
+ */
+#define SP_DELTA  (8 + 16)
+
+typedef struct {
+	uint64_t sp;
+	uint64_t pc;
+	
+	uint64_t s0;
+	uint64_t s1;
+	uint64_t s2;
+	uint64_t s3;
+	uint64_t s4;
+	uint64_t s5;
+	uint64_t s6;
+	uint64_t s7;
+	uint64_t s8;
+	uint64_t gp;
+	uint64_t tls; /* Thread local storage (k1) */
+	
+	uint64_t f20;
+	uint64_t f21;
+	uint64_t f22;
+	uint64_t f23;
+	uint64_t f24;
+	uint64_t f25;
+	uint64_t f26;
+	uint64_t f27;
+	uint64_t f28;
+	uint64_t f29;
+	uint64_t f30;
+} context_t;
+
+static inline uintptr_t context_get_fp(context_t *ctx)
+{
+	return ctx->sp;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/inttypes.h
===================================================================
--- uspace/lib/c/arch/mips64/include/inttypes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/inttypes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+
+#ifndef LIBC_mips64_INTTYPES_H_
+#define LIBC_mips64_INTTYPES_H_
+
+#define PRIdn  PRId64  /**< Format for native_t. */
+#define PRIun  PRIu64  /**< Format for sysarg_t. */
+#define PRIxn  PRIx64  /**< Format for hexadecimal sysarg_t. */
+#define PRIua  PRIu64  /**< Format for atomic_count_t. */
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/istate.h
===================================================================
--- uspace/lib/c/arch/mips64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/istate.h
Index: uspace/lib/c/arch/mips64/include/regname.h
===================================================================
--- uspace/lib/c/arch/mips64/include/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/regname.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/mips64/include/asm/regname.h
Index: uspace/lib/c/arch/mips64/include/syscall.h
===================================================================
--- uspace/lib/c/arch/mips64/include/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBC_mips64_SYSCALL_H_
+#define LIBC_mips64_SYSCALL_H_
+
+#define LIBARCH_SYSCALL_GENERIC
+
+#include <syscall.h>
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/thread.h
===================================================================
--- uspace/lib/c/arch/mips64/include/thread.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/thread.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+ * @ingroup libcmips64
+ */
+
+#ifndef LIBC_mips64_THREAD_H_
+#define LIBC_mips64_THREAD_H_
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/tls.h
===================================================================
--- uspace/lib/c/arch/mips64/include/tls.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/tls.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+ * @ingroup libcmips64
+ */
+
+/* TLS for MIPS is described in http://www.linux-mips.org/wiki/NPTL */
+
+#ifndef LIBC_mips64_TLS_H_
+#define LIBC_mips64_TLS_H_
+
+/*
+ * FIXME: Note that the use of variant I contradicts the observations made in
+ * the note below. Nevertheless the scheme we have used for allocating and
+ * deallocatin TLS corresponds to TLS variant I.
+ */
+#define CONFIG_TLS_VARIANT_1
+
+/* I did not find any specification (neither MIPS nor PowerPC), but
+ * as I found it
+ * - it uses Variant II
+ * - TCB is at Address(First TLS Block)+0x7000.
+ * - DTV is at Address(First TLS Block)+0x8000
+ * - What would happen if the TLS data was larger then 0x7000?
+ * - The linker never accesses DTV directly, has the second definition any
+ *   sense?
+ * We will make it this way:
+ * - TCB is at TP-0x7000-sizeof(tcb)
+ * - No assumption about DTV etc., but it will not have a fixed address
+ */
+#define MIPS_TP_OFFSET 0x7000
+
+typedef struct {
+	void *fibril_data;
+} tcb_t;
+
+static inline void __tcb_set(tcb_t *tcb)
+{
+	void *tp = tcb;
+	tp += MIPS_TP_OFFSET + sizeof(tcb_t);
+	
+	/* Move tls to K1 */
+	asm volatile (
+		"add $27, %0, $0"
+		:: "r" (tp)
+	);
+}
+
+static inline tcb_t *__tcb_get(void)
+{
+	void *retval;
+	
+	asm volatile (
+		"add %0, $27, $0"
+		: "=r" (retval)
+	);
+	
+	return (tcb_t *) (retval - MIPS_TP_OFFSET - sizeof(tcb_t));
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/types.h
===================================================================
--- uspace/lib/c/arch/mips64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/include/types.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+ * @ingroup libcmips32
+ */
+
+#ifndef LIBC_mips64_TYPES_H_
+#define LIBC_mips64_TYPES_H_
+
+#define __64_BITS__
+
+#include <libarch/common.h>
+
+#define SIZE_MIN  UINT64_MIN
+#define SIZE_MAX  UINT64_MAX
+
+#define SSIZE_MIN  INT64_MIN
+#define SSIZE_MAX  INT64_MAX
+
+typedef uint64_t sysarg_t;
+
+typedef int64_t ssize_t;
+typedef uint64_t size_t;
+
+typedef uint64_t uintptr_t;
+typedef uint64_t atomic_count_t;
+typedef int64_t atomic_signed_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/src/entry.s
===================================================================
--- uspace/lib/c/arch/mips64/src/entry.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/src/entry.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 2005 Martin Decky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+.text
+.section .init, "ax"
+
+.global __entry
+
+.set noreorder
+.option pic2
+
+## User-space task entry point
+#
+# $a0 ($4) contains the PCB pointer
+#
+.ent __entry
+__entry:
+	.frame $sp, 32, $31
+	.cpload $25
+	
+	# FIXME: Reflect exactly ABI specs here
+	
+	addiu $sp, -32
+	.cprestore 16   # Allow PIC code
+	
+	# Pass pcb_ptr to __main() as the first argument. pcb_ptr is already
+	# in $a0. As the first argument is passed in $a0, no operation
+	# is needed.
+	
+	jal __main
+	nop
+.end
Index: uspace/lib/c/arch/mips64/src/entryjmp.s
===================================================================
--- uspace/lib/c/arch/mips64/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+.text
+.section .text
+.global entry_point_jmp
+.set noreorder
+
+## void entry_point_jmp(void *entry_point, void *pcb);
+#
+# $a0 (=$4) contains entry_point
+# $a1 (=$5) contains pcb
+#
+# Jump to program entry point
+.ent entry_point_jmp
+entry_point_jmp:
+	# tmp := entry_point
+	move $25, $a0
+	
+	# Pass pcb to the entry point in $a0
+	move $a0, $a1
+	jr $25
+	nop
+.end
Index: uspace/lib/c/arch/mips64/src/fibril.S
===================================================================
--- uspace/lib/c/arch/mips64/src/fibril.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/src/fibril.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+#
+# Copyright (c) 2003-2004 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.
+#
+
+.text
+
+.set noat
+.set noreorder
+
+#include <libarch/context_offset.h>
+
+.global context_save
+.global context_restore
+
+context_save:
+	CONTEXT_SAVE_ARCH_CORE $a0
+	
+	# context_save returns 1
+	j $ra
+	li $v0, 1
+
+context_restore:
+	CONTEXT_RESTORE_ARCH_CORE $a0
+	
+	# Just for the jump into first function,
+	# but one instruction should not bother us
+	move $t9, $ra
+	
+	# context_restore returns 0
+	j $ra
+	xor $v0, $v0
Index: uspace/lib/c/arch/mips64/src/stacktrace.c
===================================================================
--- uspace/lib/c/arch/mips64/src/stacktrace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/src/stacktrace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010 Jakub Jermar
+ * Copyright (c) 2010 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64 mips64
+ * @ingroup lc
+ * @{
+ */
+/** @file
+ */
+
+#include <sys/types.h>
+#include <bool.h>
+#include <errno.h>
+
+#include <stacktrace.h>
+
+bool stacktrace_fp_valid(stacktrace_t *st, uintptr_t fp)
+{
+	(void) st; (void) fp;
+	return false;
+}
+
+int stacktrace_fp_prev(stacktrace_t *st, uintptr_t fp, uintptr_t *prev)
+{
+	(void) st; (void) fp; (void) prev;
+	return ENOTSUP;
+}
+
+int stacktrace_ra_get(stacktrace_t *st, uintptr_t fp, uintptr_t *ra)
+{
+	(void) st; (void) fp; (void) ra;
+	return ENOTSUP;
+}
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/src/stacktrace_asm.S
===================================================================
--- uspace/lib/c/arch/mips64/src/stacktrace_asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/src/stacktrace_asm.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2009 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.
+#
+
+.text
+
+.set noat
+.set noreorder
+
+.global stacktrace_prepare
+.global stacktrace_fp_get
+.global stacktrace_pc_get
+
+stacktrace_prepare:
+stacktrace_fp_get:
+stacktrace_pc_get:
+	j $ra
+	xor $v0, $v0
Index: uspace/lib/c/arch/mips64/src/syscall.c
===================================================================
--- uspace/lib/c/arch/mips64/src/syscall.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/src/syscall.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2005 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+  * @ingroup libcmips64
+ */
+
+#include <libc.h>
+
+sysarg_t __syscall(const sysarg_t p1, const sysarg_t p2, const sysarg_t p3,
+    const sysarg_t p4, const sysarg_t p5, const sysarg_t p6, const syscall_t id)
+{
+	register sysarg_t __mips_reg_a0 asm("$4") = p1;
+	register sysarg_t __mips_reg_a1 asm("$5") = p2;
+	register sysarg_t __mips_reg_a2 asm("$6") = p3;
+	register sysarg_t __mips_reg_a3 asm("$7") = p4;
+	register sysarg_t __mips_reg_t0 asm("$8") = p5;
+	register sysarg_t __mips_reg_t1 asm("$9") = p6;
+	register sysarg_t __mips_reg_v0 asm("$2") = id;
+	
+	asm volatile (
+		"syscall\n"
+		: "=r" (__mips_reg_v0)
+		: "r" (__mips_reg_a0),
+		  "r" (__mips_reg_a1),
+		  "r" (__mips_reg_a2),
+		  "r" (__mips_reg_a3),
+		  "r" (__mips_reg_t0),
+		  "r" (__mips_reg_t1),
+		  "r" (__mips_reg_v0)
+		/*
+		 * We are a function call, although
+		 * C does not know it
+		 */
+		: "%ra"
+	);
+	
+	return __mips_reg_v0;
+}
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/src/thread_entry.s
===================================================================
--- uspace/lib/c/arch/mips64/src/thread_entry.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/src/thread_entry.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2006 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.
+#
+
+.text
+
+.set noat
+.set noreorder
+.option pic2
+
+.globl __thread_entry
+
+## User-space thread entry point for all but the first threads.
+#
+#
+.ent __thread_entry
+__thread_entry:
+	.frame $sp, 32, $31
+	.cpload $25
+	
+	#
+	# v0 contains address of uarg.
+	#
+	add $4, $2, 0
+	
+	addiu $sp, -32
+	.cprestore 16
+	
+	jal __thread_main
+	nop
+	
+	#
+	# Not reached.
+	#
+.end __thread_entry
Index: uspace/lib/c/arch/mips64/src/tls.c
===================================================================
--- uspace/lib/c/arch/mips64/src/tls.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/mips64/src/tls.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcmips64
+ * @{
+ */
+/** @file
+ * @ingroup libcmips64
+ */
+
+#include <tls.h>
+#include <sys/types.h>
+
+tcb_t * __alloc_tls(void **data, size_t size)
+{
+	return tls_alloc_variant_1(data, size);
+}
+
+void __free_tls_arch(tcb_t *tcb, size_t size)
+{
+	tls_free_variant_1(tcb, size);
+}
+
+/** @}
+ */
Index: uspace/lib/c/arch/ppc32/Makefile.inc
===================================================================
--- uspace/lib/c/arch/ppc32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ppc32/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,4 +29,5 @@
 ARCH_SOURCES = \
 	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
 	arch/$(UARCH)/src/syscall.c \
Index: uspace/lib/c/arch/ppc32/_link.ld.in
===================================================================
--- uspace/lib/c/arch/ppc32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ppc32/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -3,11 +3,24 @@
 
 PHDRS {
+#ifdef LOADER
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+#else
 	text PT_LOAD FLAGS(5);
+#endif
 	data PT_LOAD FLAGS(6);
+	debug PT_NOTE;
 }
 
 SECTIONS {
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x70001000 + SIZEOF_HEADERS;
+#else
 	. = 0x1000 + SIZEOF_HEADERS;
-	
+#endif
 	.init : {
 		*(.init);
@@ -15,6 +28,6 @@
 	
 	.text : {
-		*(.text);
-		*(.rodata*);
+		*(.text .text.*);
+		*(.rodata .rodata.*);
 	} :text
 	
@@ -43,4 +56,17 @@
 	} :data
 	
+#ifdef CONFIG_LINE_DEBUG
+	.comment 0 : { *(.comment); } :debug
+	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
+	.debug_aranges 0 : { *(.debug_aranges); } :debug
+	.debug_info 0 : { *(.debug_info); } :debug
+	.debug_line 0 : { *(.debug_line); } :debug
+	.debug_loc 0 : { *(.debug_loc); } :debug
+	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
+	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
+	.debug_ranges 0 : { *(.debug_ranges); } :debug
+	.debug_str 0 : { *(.debug_str); } :debug
+#endif
+	
 	/DISCARD/ : {
 		*(*);
Index: uspace/lib/c/arch/ppc32/include/barrier.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ppc32/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ppc32/include/barrier.h
Index: uspace/lib/c/arch/ppc32/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ppc32/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ppc32/include/context_offset.h
Index: uspace/lib/c/arch/ppc32/include/elf.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ppc32/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ppc32/include/elf.h
Index: uspace/lib/c/arch/ppc32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ppc32/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcppc32
+ * @{
+ */
+/** @file Definitions needed to write core files in Linux-ELF format.
+ */
+
+#ifndef LIBC_ppc32_ELF_LINUX_H_
+#define LBIC_ppc32_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+/** Linux kernel struct pt_regs structure.
+ *
+ * We need this to save register state to a core file in Linux format
+ * (readable by GDB configured for Linux target).
+ */
+typedef struct {
+	uint32_t r0;
+	uint32_t r1;
+	uint32_t r2;
+	uint32_t r3;
+	uint32_t r4;
+	uint32_t r5;
+	uint32_t r6;
+	uint32_t r7;
+	uint32_t r8;
+	uint32_t r9;
+	uint32_t r10;
+	uint32_t r11;
+	uint32_t r12;
+	uint32_t r13;
+	uint32_t r14;
+	uint32_t r15;
+	uint32_t r16;
+	uint32_t r17;
+	uint32_t r18;
+	uint32_t r19;
+	uint32_t r20;
+	uint32_t r21;
+	uint32_t r22;
+	uint32_t r23;
+	uint32_t r24;
+	uint32_t r25;
+	uint32_t r26;
+	uint32_t r27;
+	uint32_t r28;
+	uint32_t r29;
+	uint32_t r30;
+	uint32_t r31;
+
+	uint32_t nip;
+	uint32_t msr;
+	uint32_t old_r3;
+	uint32_t ctr;
+	uint32_t link;
+	uint32_t xer;
+	uint32_t ccr;
+	uint32_t mq;
+	uint32_t trap;
+	uint32_t dar;
+	uint32_t dsisr;
+	uint32_t result;
+} elf_regs_t;
+
+/** Convert istate_t to elf_regs_t. */
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	elf_regs->r0 = istate->r0;
+	elf_regs->r1 = istate->sp;
+	elf_regs->r2 = istate->r2;
+	elf_regs->r3 = istate->r3;
+	elf_regs->r4 = istate->r4;
+	elf_regs->r5 = istate->r5;
+	elf_regs->r6 = istate->r6;
+	elf_regs->r7 = istate->r7;
+	elf_regs->r8 = istate->r8;
+	elf_regs->r9 = istate->r9;
+	elf_regs->r10 = istate->r10;
+	elf_regs->r11 = istate->r11;
+	elf_regs->r12 = istate->r12;
+	elf_regs->r13 = istate->r13;
+	elf_regs->r14 = istate->r14;
+	elf_regs->r15 = istate->r15;
+	elf_regs->r16 = istate->r16;
+	elf_regs->r17 = istate->r17;
+	elf_regs->r18 = istate->r18;
+	elf_regs->r19 = istate->r19;
+	elf_regs->r20 = istate->r20;
+	elf_regs->r21 = istate->r21;
+	elf_regs->r22 = istate->r22;
+	elf_regs->r23 = istate->r23;
+	elf_regs->r24 = istate->r24;
+	elf_regs->r25 = istate->r25;
+	elf_regs->r26 = istate->r26;
+	elf_regs->r27 = istate->r27;
+	elf_regs->r28 = istate->r28;
+	elf_regs->r29 = istate->r29;
+	elf_regs->r30 = istate->r30;
+	elf_regs->r31 = istate->r31;
+
+	elf_regs->ctr = istate->ctr;
+	elf_regs->link = istate->lr;
+	elf_regs->xer = istate->xer;
+	elf_regs->ccr = istate->cr;
+	elf_regs->dar = istate->dar;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/ppc32/include/istate.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ppc32/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,99 +1,1 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libcppc32
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ppc32_ISTATE_H_
-#define LIBC_ppc32_ISTATE_H_
-
-#include <sys/types.h>
-
-/** Interrupt context.
- *
- * This is a copy of the kernel definition with which it must be kept in sync.
- */
-typedef struct istate {
-	uint32_t r0;
-	uint32_t r2;
-	uint32_t r3;
-	uint32_t r4;
-	uint32_t r5;
-	uint32_t r6;
-	uint32_t r7;
-	uint32_t r8;
-	uint32_t r9;
-	uint32_t r10;
-	uint32_t r11;
-	uint32_t r13;
-	uint32_t r14;
-	uint32_t r15;
-	uint32_t r16;
-	uint32_t r17;
-	uint32_t r18;
-	uint32_t r19;
-	uint32_t r20;
-	uint32_t r21;
-	uint32_t r22;
-	uint32_t r23;
-	uint32_t r24;
-	uint32_t r25;
-	uint32_t r26;
-	uint32_t r27;
-	uint32_t r28;
-	uint32_t r29;
-	uint32_t r30;
-	uint32_t r31;
-	uint32_t cr;
-	uint32_t pc;
-	uint32_t srr1;
-	uint32_t lr;
-	uint32_t ctr;
-	uint32_t xer;
-	uint32_t dar;
-	uint32_t r12;
-	uint32_t sp;
-} istate_t;
-
-static inline uintptr_t istate_get_pc(istate_t *istate)
-{
-	return istate->pc;
-}
-
-static inline uintptr_t istate_get_fp(istate_t *istate)
-{
-	return istate->sp;
-}
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/ppc32/include/istate.h
Index: uspace/lib/c/arch/ppc32/include/msr.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/msr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ppc32/include/msr.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/ppc32/include/msr.h
Index: uspace/lib/c/arch/ppc32/src/entryjmp.s
===================================================================
--- uspace/lib/c/arch/ppc32/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/ppc32/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+.globl entry_point_jmp
+
+## void entry_point_jmp(void *entry_point, void *pcb);
+#
+# %r3	contains entry_point
+# %r4	contains pcb
+#
+# Jump to program entry point
+entry_point_jmp:
+	mtctr %r3
+	mr %r6, %r4	# Pass pcb to the entry point in %r6
+	bctr
Index: uspace/lib/c/arch/ppc32/src/fibril.S
===================================================================
--- uspace/lib/c/arch/ppc32/src/fibril.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/ppc32/src/fibril.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,5 +33,5 @@
 
 #include <libarch/regname.h>
-#include <arch/context_offset.h>
+#include <libarch/context_offset.h>
 
 context_save:
Index: uspace/lib/c/arch/sparc64/Makefile.inc
===================================================================
--- uspace/lib/c/arch/sparc64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/sparc64/Makefile.inc	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,4 +29,5 @@
 ARCH_SOURCES = \
 	arch/$(UARCH)/src/entry.s \
+	arch/$(UARCH)/src/entryjmp.s \
 	arch/$(UARCH)/src/thread_entry.s \
 	arch/$(UARCH)/src/fibril.S \
Index: uspace/lib/c/arch/sparc64/_link.ld.in
===================================================================
--- uspace/lib/c/arch/sparc64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/sparc64/_link.ld.in	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -3,11 +3,23 @@
 
 PHDRS {
+#ifdef LOADER
+	interp PT_INTERP;
+	text PT_LOAD FILEHDR PHDRS FLAGS(5);
+#else
 	text PT_LOAD FLAGS(5);
+#endif
 	data PT_LOAD FLAGS(6);
 }
 
 SECTIONS {
+#ifdef LOADER
+	.interp : {
+		*(.interp);
+	} :interp
+	
+	. = 0x70004000 + SIZEOF_HEADERS;
+#else
 	. = 0x4000 + SIZEOF_HEADERS;
-	
+#endif
 	.init : {
 		*(.init);
@@ -15,6 +27,6 @@
 	
 	.text : {
-		*(.text);
-		*(.rodata*);
+		*(.text .text.*);
+		*(.rodata .rodata.*);
 	} :text
 	
Index: uspace/lib/c/arch/sparc64/include/barrier.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/sparc64/include/barrier.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/sparc64/include/barrier.h
Index: uspace/lib/c/arch/sparc64/include/context_offset.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/sparc64/include/context_offset.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/sparc64/include/context_offset.h
Index: uspace/lib/c/arch/sparc64/include/elf.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/sparc64/include/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/sparc64/include/elf.h
Index: uspace/lib/c/arch/sparc64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/sparc64/include/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcsparc64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_sparc64_ELF_LINUX_H_
+#define LBIC_sparc64_ELF_LINUX_H_
+
+#include <libarch/istate.h>
+#include <sys/types.h>
+
+typedef struct {
+	/* TODO */
+	uint64_t pad[16];
+} elf_regs_t;
+
+static inline void istate_to_elf_regs(istate_t *istate, elf_regs_t *elf_regs)
+{
+	/* TODO */
+	(void) istate; (void) elf_regs;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/sparc64/include/istate.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/istate.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/sparc64/include/istate.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,43 +1,1 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libcsparc64
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_sparc64_ISTATE_H_
-#define LIBC_sparc64_ISTATE_H_
-
-#include <arch/istate.h>
-
-#endif
-
-/** @}
- */
+../../../../../../kernel/arch/sparc64/include/istate.h
Index: uspace/lib/c/arch/sparc64/include/regdef.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/regdef.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/sparc64/include/regdef.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1 @@
+../../../../../../kernel/arch/sparc64/include/regdef.h
Index: uspace/lib/c/arch/sparc64/include/syscall.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/syscall.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/sparc64/include/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 
 #define __syscall0	__syscall
Index: uspace/lib/c/arch/sparc64/src/entryjmp.s
===================================================================
--- uspace/lib/c/arch/sparc64/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/arch/sparc64/src/entryjmp.s	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+
+.globl entry_point_jmp
+
+## void entry_point_jmp(void *entry_point, void *pcb);
+#
+# %o0	contains entry_point
+# %o1	contains pcb
+#
+# Jump to program entry point
+entry_point_jmp:
+	# Pass pcb pointer to entry point in %o1. As it is already
+	# there, no action is needed.
+	call %o0
+	nop
+	# fixme: use branch instead of call
Index: uspace/lib/c/arch/sparc64/src/fibril.S
===================================================================
--- uspace/lib/c/arch/sparc64/src/fibril.S	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/arch/sparc64/src/fibril.S	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,7 +27,7 @@
 #
 
-#include <kernel/arch/context_offset.h>
+#include <libarch/context_offset.h>
 
-.text   
+.text
 
 .global context_save
Index: uspace/lib/c/generic/adt/hash_table.c
===================================================================
--- uspace/lib/c/generic/adt/hash_table.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/adt/hash_table.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -54,5 +54,5 @@
  *
  */
-int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
+bool hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys,
     hash_table_operations_t *op)
 {
@@ -61,9 +61,9 @@
 	assert(max_keys > 0);
 	
-	h->entry = malloc(m * sizeof(link_t));
+	h->entry = malloc(m * sizeof(list_t));
 	if (!h->entry)
 		return false;
 	
-	memset((void *) h->entry, 0,  m * sizeof(link_t));
+	memset((void *) h->entry, 0,  m * sizeof(list_t));
 	
 	hash_count_t i;
@@ -123,7 +123,5 @@
 	assert(chain < h->entries);
 	
-	link_t *cur;
-	for (cur = h->entry[chain].next; cur != &h->entry[chain];
-	    cur = cur->next) {
+	list_foreach(h->entry[chain], cur) {
 		if (h->op->compare(key, h->max_keys, cur)) {
 			/*
@@ -153,7 +151,7 @@
 	assert(keys <= h->max_keys);
 	
-	link_t *cur;
-	
 	if (keys == h->max_keys) {
+		link_t *cur;
+		
 		/*
 		 * All keys are known, hash_table_find() can be used to find the
@@ -176,5 +174,7 @@
 	hash_index_t chain;
 	for (chain = 0; chain < h->entries; chain++) {
-		for (cur = h->entry[chain].next; cur != &h->entry[chain];
+		link_t *cur;
+		
+		for (cur = h->entry[chain].head.next; cur != &h->entry[chain].head;
 		    cur = cur->next) {
 			if (h->op->compare(key, keys, cur)) {
@@ -203,9 +203,7 @@
 {
 	hash_index_t bucket;
-	link_t *cur;
 	
 	for (bucket = 0; bucket < h->entries; bucket++) {
-		for (cur = h->entry[bucket].next; cur != &h->entry[bucket];
-		    cur = cur->next) {
+		list_foreach(h->entry[bucket], cur) {
 			f(cur, arg);
 		}
Index: uspace/lib/c/generic/adt/list.c
===================================================================
--- uspace/lib/c/generic/adt/list.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/adt/list.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,29 +30,35 @@
  * @{
  */
-/** @file
+
+/**
+ * @file
+ * @brief	Functions completing doubly linked circular list implementaion.
+ *
+ * This file contains some of the functions implementing doubly linked circular lists.
+ * However, this ADT is mostly implemented in @ref list.h.
  */
 
 #include <adt/list.h>
-
+#include <bool.h>
 
 /** Check for membership
  *
- * Check whether link is contained in the list head.
- * The membership is defined as pointer equivalence.
+ * Check whether link is contained in a list.
+ * Membership is defined as pointer equivalence.
  *
- * @param link Item to look for.
- * @param head List to look in.
+ * @param link	Item to look for.
+ * @param list	List to look in.
  *
  * @return true if link is contained in head, false otherwise.
  *
  */
-int list_member(const link_t *link, const link_t *head)
+int list_member(const link_t *link, const list_t *list)
 {
-	int found = 0;
-	link_t *hlp = head->next;
+	bool found = false;
+	link_t *hlp = list->head.next;
 	
-	while (hlp != head) {
+	while (hlp != &list->head) {
 		if (hlp == link) {
-			found = 1;
+			found = true;
 			break;
 		}
@@ -63,27 +69,25 @@
 }
 
-
 /** Concatenate two lists
  *
- * Concatenate lists head1 and head2, producing a single
- * list head1 containing items from both (in head1, head2
- * order) and empty list head2.
+ * Concatenate lists @a list1 and @a list2, producing a single
+ * list @a list1 containing items from both (in @a list1, @a list2
+ * order) and empty list @a list2.
  *
- * @param head1 First list and concatenated output
- * @param head2 Second list and empty output.
+ * @param list1		First list and concatenated output
+ * @param list2 	Second list and empty output.
  *
  */
-void list_concat(link_t *head1, link_t *head2)
+void list_concat(list_t *list1, list_t *list2)
 {
-	if (list_empty(head2))
+	if (list_empty(list2))
 		return;
-	
-	head2->next->prev = head1->prev;
-	head2->prev->next = head1;
-	head1->prev->next = head2->next;
-	head1->prev = head2->prev;
-	list_initialize(head2);
+
+	list2->head.next->prev = list1->head.prev;
+	list2->head.prev->next = &list1->head;
+	list1->head.prev->next = list2->head.next;
+	list1->head.prev = list2->head.prev;
+	list_initialize(list2);
 }
-
 
 /** Count list items
@@ -91,17 +95,13 @@
  * Return the number of items in the list.
  *
- * @param link List to count.
- *
- * @return Number of items in the list.
- *
+ * @param list		List to count.
+ * @return		Number of items in the list.
  */
-unsigned int list_count(const link_t *link)
+unsigned int list_count(const list_t *list)
 {
 	unsigned int count = 0;
-	link_t *hlp = link->next;
 	
-	while (hlp != link) {
+	list_foreach(*list, link) {
 		count++;
-		hlp = hlp->next;
 	}
 	
Index: uspace/lib/c/generic/adt/measured_strings.c
===================================================================
--- uspace/lib/c/generic/adt/measured_strings.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/adt/measured_strings.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -74,5 +74,5 @@
 	new->length = length;
 	new->value = ((uint8_t *) new) + sizeof(measured_string_t);
-	// append terminating zero explicitly - to be safe
+	/* Append terminating zero explicitly - to be safe */
 	memcpy(new->value, string, new->length);
 	new->value[new->length] = '\0';
@@ -297,5 +297,5 @@
  * size has to be negotiated in advance.
  *
- * @param[in] phone	The other module phone.
+ * @param[in] exch	Exchange.
  * @param[out] strings	The returned measured strings array.
  * @param[out] data	The measured strings data. This memory block stores the
@@ -304,5 +304,5 @@
  * @return		EOK on success.
  * @return		EINVAL if the strings or data parameter is NULL.
- * @return		EINVAL if the phone or count parameter is not positive.
+ * @return		EINVAL if the exch or count parameter is invalid.
  * @return		EINVAL if the sent array differs in size.
  * @return		ENOMEM if there is not enough memory left.
@@ -310,7 +310,6 @@
  *			async_data_read_start() function.
  */
-int
-measured_strings_return(int phone, measured_string_t **strings, uint8_t **data,
-    size_t count)
+int measured_strings_return(async_exch_t *exch, measured_string_t **strings,
+    uint8_t **data, size_t count)
 {
 	size_t *lengths;
@@ -319,5 +318,5 @@
 	int rc;
 
-	if ((phone < 0) || (!strings) || (!data) || (count <= 0))
+	if ((exch == NULL) || (!strings) || (!data) || (count <= 0))
 		return EINVAL;
 
@@ -326,5 +325,5 @@
 		return ENOMEM;
 
-	rc = async_data_read_start(phone, lengths,
+	rc = async_data_read_start(exch, lengths,
 	    sizeof(size_t) * (count + 1));
 	if (rc != EOK) {
@@ -351,5 +350,5 @@
 		(*strings)[index].length = lengths[index];
 		if (lengths[index] > 0) {
-			rc = async_data_read_start(phone, next, lengths[index]);
+			rc = async_data_read_start(exch, next, lengths[index]);
 			if (rc != EOK) {
 			    	free(lengths);
@@ -375,15 +374,14 @@
  * size has to be negotiated in advance.
  *
- * @param[in] phone	The other module phone.
+ * @param[in] exch	Exchange.
  * @param[in] strings	The measured strings array to be transferred.
  * @param[in] count	The measured strings array size.
  * @return		EOK on success.
  * @return		EINVAL if the strings parameter is NULL.
- * @return		EINVAL if the phone or count parameter is not positive.
+ * @return		EINVAL if the exch or count parameter is invalid.
  * @return		Other error codes as defined for the
  *			async_data_write_start() function.
  */
-int
-measured_strings_send(int phone, const measured_string_t *strings,
+int measured_strings_send(async_exch_t *exch, const measured_string_t *strings,
     size_t count)
 {
@@ -392,5 +390,5 @@
 	int rc;
 
-	if ((phone < 0) || (!strings) || (count <= 0))
+	if ((exch == NULL) || (!strings) || (count <= 0))
 		return EINVAL;
 
@@ -399,5 +397,5 @@
 		return ENOMEM;
 
-	rc = async_data_write_start(phone, lengths,
+	rc = async_data_write_start(exch, lengths,
 	    sizeof(size_t) * (count + 1));
 	if (rc != EOK) {
@@ -410,5 +408,5 @@
 	for (index = 0; index < count; index++) {
 		if (strings[index].length > 0) {
-			rc = async_data_write_start(phone, strings[index].value,
+			rc = async_data_write_start(exch, strings[index].value,
 			    strings[index].length);
 			if (rc != EOK)
@@ -422,3 +420,2 @@
 /** @}
  */
-
Index: uspace/lib/c/generic/adt/prodcons.c
===================================================================
--- uspace/lib/c/generic/adt/prodcons.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/adt/prodcons.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <adt/prodcons.h>
+#include <adt/list.h>
+#include <fibril_synch.h>
+
+void prodcons_initialize(prodcons_t *pc)
+{
+	list_initialize(&pc->list);
+	fibril_mutex_initialize(&pc->mtx);
+	fibril_condvar_initialize(&pc->cv);
+}
+
+void prodcons_produce(prodcons_t *pc, link_t *item)
+{
+	fibril_mutex_lock(&pc->mtx);
+	
+	list_append(item, &pc->list);
+	fibril_condvar_signal(&pc->cv);
+	
+	fibril_mutex_unlock(&pc->mtx);
+}
+
+link_t *prodcons_consume(prodcons_t *pc)
+{
+	fibril_mutex_lock(&pc->mtx);
+	
+	while (list_empty(&pc->list))
+		fibril_condvar_wait(&pc->cv, &pc->mtx);
+	
+	link_t *head = list_first(&pc->list);
+	list_remove(head);
+	
+	fibril_mutex_unlock(&pc->mtx);
+	
+	return head;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/as.c
===================================================================
--- uspace/lib/c/generic/as.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/as.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,4 +35,5 @@
 #include <as.h>
 #include <libc.h>
+#include <errno.h>
 #include <unistd.h>
 #include <align.h>
@@ -51,5 +52,5 @@
  *
  */
-void *as_area_create(void *address, size_t size, int flags)
+void *as_area_create(void *address, size_t size, unsigned int flags)
 {
 	return (void *) __SYSCALL3(SYS_AS_AREA_CREATE, (sysarg_t) address,
@@ -67,5 +68,5 @@
  *
  */
-int as_area_resize(void *address, size_t size, int flags)
+int as_area_resize(void *address, size_t size, unsigned int flags)
 {
 	return __SYSCALL3(SYS_AS_AREA_RESIZE, (sysarg_t) address,
@@ -95,5 +96,5 @@
  *
  */
-int as_area_change_flags(void *address, int flags)
+int as_area_change_flags(void *address, unsigned int flags)
 {
 	return __SYSCALL2(SYS_AS_AREA_CHANGE_FLAGS, (sysarg_t) address,
@@ -114,4 +115,30 @@
 }
 
+/** Find mapping to physical address.
+ *
+ * @param address Virtual address in question (virtual).
+ * @param[out] frame Frame address (physical).
+ * @return Error code.
+ * @retval EOK No error, @p frame holds the translation.
+ * @retval ENOENT Mapping not found.
+ */
+int as_get_physical_mapping(void *address, uintptr_t *frame)
+{
+	uintptr_t tmp_frame;
+	uintptr_t virt = (uintptr_t) address;
+	
+	int rc = (int) __SYSCALL2(SYS_PAGE_FIND_MAPPING,
+	    (sysarg_t) virt, (sysarg_t) &tmp_frame);
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	if (frame != NULL) {
+		*frame = tmp_frame;
+	}
+	
+	return EOK;
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/assert.c
===================================================================
--- uspace/lib/c/generic/assert.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/assert.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <io/klog.h>
+#include <stdlib.h>
+#include <atomic.h>
+#include <stacktrace.h>
+#include <stdint.h>
+
+static atomic_t failed_asserts = {0};
+
+void assert_abort(const char *cond, const char *file, unsigned int line)
+{
+	/*
+	 * Send the message safely to klog. Nested asserts should not occur.
+	 */
+	klog_printf("Assertion failed (%s) in file \"%s\", line %u.\n",
+	    cond, file, line);
+	
+	/*
+	 * Check if this is a nested or parallel assert.
+	 */
+	if (atomic_postinc(&failed_asserts))
+		abort();
+	
+	/*
+	 * Attempt to print the message to standard output and display
+	 * the stack trace. These operations can theoretically trigger nested
+	 * assertions.
+	 */
+	printf("Assertion failed (%s) in file \"%s\", line %u.\n",
+	    cond, file, line);
+	stacktrace_print();
+	
+	abort();
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/async.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,6 +40,7 @@
  * programming.
  *
- * You should be able to write very simple multithreaded programs, the async
- * framework will automatically take care of most synchronization problems.
+ * You should be able to write very simple multithreaded programs. The async
+ * framework will automatically take care of most of the synchronization
+ * problems.
  *
  * Example of use (pseudo C):
@@ -53,7 +54,14 @@
  *   int fibril1(void *arg)
  *   {
- *     conn = async_connect_me_to();
- *     c1 = async_send(conn);
- *     c2 = async_send(conn);
+ *     conn = async_connect_me_to(...);
+ *
+ *     exch = async_exchange_begin(conn);
+ *     c1 = async_send(exch);
+ *     async_exchange_end(exch);
+ *
+ *     exch = async_exchange_begin(conn);
+ *     c2 = async_send(exch);
+ *     async_exchange_end(exch);
+ *
  *     async_wait_for(c1);
  *     async_wait_for(c2);
@@ -90,9 +98,9 @@
 #include <ipc/ipc.h>
 #include <async.h>
+#include "private/async.h"
 #undef LIBC_ASYNC_C_
 
 #include <futex.h>
 #include <fibril.h>
-#include <stdio.h>
 #include <adt/hash_table.h>
 #include <adt/list.h>
@@ -100,8 +108,15 @@
 #include <errno.h>
 #include <sys/time.h>
-#include <arch/barrier.h>
+#include <libarch/barrier.h>
 #include <bool.h>
-#include "private/async.h"
-
+#include <malloc.h>
+#include <mem.h>
+#include <stdlib.h>
+#include <macros.h>
+
+#define CLIENT_HASH_TABLE_BUCKETS  32
+#define CONN_HASH_TABLE_BUCKETS    32
+
+/** Async framework global futex */
 atomic_t async_futex = FUTEX_INITIALIZER;
 
@@ -109,33 +124,25 @@
 atomic_t threads_in_ipc_wait = { 0 };
 
-typedef struct {
-	awaiter_t wdata;
-	
-	/** If reply was received. */
-	bool done;
-	
-	/** Pointer to where the answer data is stored. */
-	ipc_call_t *dataptr;
-	
-	sysarg_t retval;
-} amsg_t;
-
-/**
- * Structures of this type are used to group information about
- * a call and about a message queue link.
- */
+/** Naming service session */
+async_sess_t *session_ns;
+
+/** Call data */
 typedef struct {
 	link_t link;
+	
 	ipc_callid_t callid;
 	ipc_call_t call;
 } msg_t;
 
+/* Client connection data */
 typedef struct {
-	sysarg_t in_task_hash;
 	link_t link;
-	int refcnt;
+	
+	task_id_t in_task_id;
+	atomic_t refcnt;
 	void *data;
 } client_t;
 
+/* Server connection data */
 typedef struct {
 	awaiter_t wdata;
@@ -144,6 +151,7 @@
 	link_t link;
 	
-	/** Incoming client task hash. */
-	sysarg_t in_task_hash;
+	/** Incoming client task ID. */
+	task_id_t in_task_id;
+	
 	/** Incoming phone hash. */
 	sysarg_t in_phone_hash;
@@ -153,5 +161,5 @@
 	
 	/** Messages that should be delivered to this fibril. */
-	link_t msg_queue;
+	list_t msg_queue;
 	
 	/** Identification of the opening call. */
@@ -159,4 +167,6 @@
 	/** Call data of the opening call. */
 	ipc_call_t call;
+	/** Local argument or NULL if none. */
+	void *carg;
 	
 	/** Identification of the closing call. */
@@ -164,9 +174,9 @@
 	
 	/** Fibril function that will be used to handle the connection. */
-	void (*cfibril)(ipc_callid_t, ipc_call_t *);
+	async_client_conn_t cfibril;
 } connection_t;
 
 /** Identifier of the incoming connection handled by the current fibril. */
-static fibril_local connection_t *FIBRIL_connection;
+static fibril_local connection_t *fibril_connection;
 
 static void *default_client_data_constructor(void)
@@ -194,10 +204,4 @@
 }
 
-void *async_client_data_get(void)
-{
-	assert(FIBRIL_connection);
-	return FIBRIL_connection->client->data;
-}
-
 /** Default fibril function that gets called to handle new connection.
  *
@@ -206,15 +210,12 @@
  * @param callid Hash of the incoming call.
  * @param call   Data of the incoming call.
- *
- */
-static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
+ * @param arg    Local argument
+ *
+ */
+static void default_client_connection(ipc_callid_t callid, ipc_call_t *call,
+    void *arg)
 {
 	ipc_answer_0(callid, ENOENT);
 }
-
-/**
- * Pointer to a fibril function that will be used to handle connections.
- */
-static async_client_conn_t client_connection = default_client_connection;
 
 /** Default fibril function that gets called to handle interrupt notifications.
@@ -224,4 +225,5 @@
  * @param callid Hash of the incoming call.
  * @param call   Data of the incoming call.
+ * @param arg    Local argument.
  *
  */
@@ -230,9 +232,41 @@
 }
 
-/**
- * Pointer to a fibril function that will be used to handle interrupt
- * notifications.
- */
-static async_client_conn_t interrupt_received = default_interrupt_received;
+static async_client_conn_t client_connection = default_client_connection;
+static async_interrupt_handler_t interrupt_received = default_interrupt_received;
+
+/** Setter for client_connection function pointer.
+ *
+ * @param conn Function that will implement a new connection fibril.
+ *
+ */
+void async_set_client_connection(async_client_conn_t conn)
+{
+	client_connection = conn;
+}
+
+/** Setter for interrupt_received function pointer.
+ *
+ * @param intr Function that will implement a new interrupt
+ *             notification fibril.
+ */
+void async_set_interrupt_received(async_interrupt_handler_t intr)
+{
+	interrupt_received = intr;
+}
+
+/** Mutex protecting inactive_exch_list and avail_phone_cv.
+ *
+ */
+static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex);
+
+/** List of all currently inactive exchanges.
+ *
+ */
+static LIST_INITIALIZE(inactive_exch_list);
+
+/** Condition variable to wait for a phone to become available.
+ *
+ */
+static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
 
 static hash_table_t client_hash_table;
@@ -240,10 +274,8 @@
 static LIST_INITIALIZE(timeout_list);
 
-#define CLIENT_HASH_TABLE_BUCKETS  32
-#define CONN_HASH_TABLE_BUCKETS    32
-
 static hash_index_t client_hash(unsigned long key[])
 {
 	assert(key);
+	
 	return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
 }
@@ -251,6 +283,11 @@
 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
+	assert(key);
+	assert(keys == 2);
+	assert(item);
+	
 	client_t *client = hash_table_get_instance(item, client_t, link);
-	return (key[0] == client->in_task_hash);
+	return (key[0] == LOWER32(client->in_task_id) &&
+	    (key[1] == UPPER32(client->in_task_id)));
 }
 
@@ -276,4 +313,5 @@
 {
 	assert(key);
+	
 	return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
 }
@@ -290,4 +328,7 @@
 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
+	assert(key);
+	assert(item);
+	
 	connection_t *conn = hash_table_get_instance(item, connection_t, link);
 	return (key[0] == conn->in_phone_hash);
@@ -312,9 +353,11 @@
 void async_insert_timeout(awaiter_t *wd)
 {
+	assert(wd);
+	
 	wd->to_event.occurred = false;
 	wd->to_event.inlist = true;
 	
-	link_t *tmp = timeout_list.next;
-	while (tmp != &timeout_list) {
+	link_t *tmp = timeout_list.head.next;
+	while (tmp != &timeout_list.head) {
 		awaiter_t *cur
 		    = list_get_instance(tmp, awaiter_t, to_event.link);
@@ -326,5 +369,5 @@
 	}
 	
-	list_append(&wd->to_event.link, tmp);
+	list_insert_before(&wd->to_event.link, tmp);
 }
 
@@ -344,4 +387,6 @@
 static bool route_call(ipc_callid_t callid, ipc_call_t *call)
 {
+	assert(call);
+	
 	futex_down(&async_futex);
 	
@@ -398,4 +443,6 @@
 static int notification_fibril(void *arg)
 {
+	assert(arg);
+	
 	msg_t *msg = (msg_t *) arg;
 	interrupt_received(msg->callid, &msg->call);
@@ -418,4 +465,6 @@
 static bool process_notification(ipc_callid_t callid, ipc_call_t *call)
 {
+	assert(call);
+	
 	futex_down(&async_futex);
 	
@@ -456,13 +505,14 @@
 ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
 {
-	assert(FIBRIL_connection);
+	assert(call);
+	assert(fibril_connection);
 	
 	/* Why doing this?
-	 * GCC 4.1.0 coughs on FIBRIL_connection-> dereference.
+	 * GCC 4.1.0 coughs on fibril_connection-> dereference.
 	 * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot.
 	 *           I would never expect to find so many errors in
 	 *           a compiler.
 	 */
-	connection_t *conn = FIBRIL_connection;
+	connection_t *conn = fibril_connection;
 	
 	futex_down(&async_futex);
@@ -516,5 +566,5 @@
 	}
 	
-	msg_t *msg = list_get_instance(conn->msg_queue.next, msg_t, link);
+	msg_t *msg = list_get_instance(list_first(&conn->msg_queue), msg_t, link);
 	list_remove(&msg->link);
 	
@@ -527,4 +577,91 @@
 }
 
+static client_t *async_client_get(task_id_t client_id, bool create)
+{
+	unsigned long key[2] = {
+		LOWER32(client_id),
+		UPPER32(client_id),
+	};
+	client_t *client = NULL;
+
+	futex_down(&async_futex);
+	link_t *lnk = hash_table_find(&client_hash_table, key);
+	if (lnk) {
+		client = hash_table_get_instance(lnk, client_t, link);
+		atomic_inc(&client->refcnt);
+	} else if (create) {
+		client = malloc(sizeof(client_t));
+		if (client) {
+			client->in_task_id = client_id;
+			client->data = async_client_data_create();
+		
+			atomic_set(&client->refcnt, 1);
+			hash_table_insert(&client_hash_table, key, &client->link);
+		}
+	}
+
+	futex_up(&async_futex);
+	return client;
+}
+
+static void async_client_put(client_t *client)
+{
+	bool destroy;
+	unsigned long key[2] = {
+		LOWER32(client->in_task_id),
+		UPPER32(client->in_task_id)
+	};
+	
+	futex_down(&async_futex);
+	
+	if (atomic_predec(&client->refcnt) == 0) {
+		hash_table_remove(&client_hash_table, key, 2);
+		destroy = true;
+	} else
+		destroy = false;
+	
+	futex_up(&async_futex);
+	
+	if (destroy) {
+		if (client->data)
+			async_client_data_destroy(client->data);
+		
+		free(client);
+	}
+}
+
+void *async_get_client_data(void)
+{
+	assert(fibril_connection);
+	return fibril_connection->client->data;
+}
+
+void *async_get_client_data_by_id(task_id_t client_id)
+{
+	client_t *client = async_client_get(client_id, false);
+	if (!client)
+		return NULL;
+	if (!client->data) {
+		async_client_put(client);
+		return NULL;
+	}
+
+	return client->data;
+}
+
+void async_put_client_data_by_id(task_id_t client_id)
+{
+	client_t *client = async_client_get(client_id, false);
+
+	assert(client);
+	assert(client->data);
+
+	/* Drop the reference we got in async_get_client_data_by_hash(). */
+	async_client_put(client);
+
+	/* Drop our own reference we got at the beginning of this function. */
+	async_client_put(client);
+}
+
 /** Wrapper for client connection fibril.
  *
@@ -539,10 +676,10 @@
 static int connection_fibril(void *arg)
 {
+	assert(arg);
+	
 	/*
 	 * Setup fibril-local connection pointer.
 	 */
-	FIBRIL_connection = (connection_t *) arg;
-	
-	futex_down(&async_futex);
+	fibril_connection = (connection_t *) arg;
 	
 	/*
@@ -551,62 +688,23 @@
 	 * hash in a new tracking structure.
 	 */
-	
-	unsigned long key = FIBRIL_connection->in_task_hash;
-	link_t *lnk = hash_table_find(&client_hash_table, &key);
-	
-	client_t *client;
-	
-	if (lnk) {
-		client = hash_table_get_instance(lnk, client_t, link);
-		client->refcnt++;
-	} else {
-		client = malloc(sizeof(client_t));
-		if (!client) {
-			ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
-			futex_up(&async_futex);
-			return 0;
-		}
-		
-		client->in_task_hash = FIBRIL_connection->in_task_hash;
-		
-		async_serialize_start();
-		client->data = async_client_data_create();
-		async_serialize_end();
-		
-		client->refcnt = 1;
-		hash_table_insert(&client_hash_table, &key, &client->link);
-	}
-	
-	futex_up(&async_futex);
-	
-	FIBRIL_connection->client = client;
+
+	client_t *client = async_client_get(fibril_connection->in_task_id, true);
+	if (!client) {
+		ipc_answer_0(fibril_connection->callid, ENOMEM);
+		return 0;
+	}
+
+	fibril_connection->client = client;
 	
 	/*
 	 * Call the connection handler function.
 	 */
-	FIBRIL_connection->cfibril(FIBRIL_connection->callid,
-	    &FIBRIL_connection->call);
+	fibril_connection->cfibril(fibril_connection->callid,
+	    &fibril_connection->call, fibril_connection->carg);
 	
 	/*
 	 * Remove the reference for this client task connection.
 	 */
-	bool destroy;
-	
-	futex_down(&async_futex);
-	
-	if (--client->refcnt == 0) {
-		hash_table_remove(&client_hash_table, &key, 1);
-		destroy = true;
-	} else
-		destroy = false;
-	
-	futex_up(&async_futex);
-	
-	if (destroy) {
-		if (client->data)
-			async_client_data_destroy(client->data);
-		
-		free(client);
-	}
+	async_client_put(client);
 	
 	/*
@@ -614,5 +712,5 @@
 	 */
 	futex_down(&async_futex);
-	key = FIBRIL_connection->in_phone_hash;
+	unsigned long key = fibril_connection->in_phone_hash;
 	hash_table_remove(&conn_hash_table, &key, 1);
 	futex_up(&async_futex);
@@ -621,8 +719,8 @@
 	 * Answer all remaining messages with EHANGUP.
 	 */
-	while (!list_empty(&FIBRIL_connection->msg_queue)) {
+	while (!list_empty(&fibril_connection->msg_queue)) {
 		msg_t *msg =
-		    list_get_instance(FIBRIL_connection->msg_queue.next, msg_t,
-		    link);
+		    list_get_instance(list_first(&fibril_connection->msg_queue),
+		    msg_t, link);
 		
 		list_remove(&msg->link);
@@ -635,8 +733,8 @@
 	 * i.e. IPC_M_PHONE_HUNGUP.
 	 */
-	if (FIBRIL_connection->close_callid)
-		ipc_answer_0(FIBRIL_connection->close_callid, EOK);
-	
-	free(FIBRIL_connection);
+	if (fibril_connection->close_callid)
+		ipc_answer_0(fibril_connection->close_callid, EOK);
+	
+	free(fibril_connection);
 	return 0;
 }
@@ -644,9 +742,9 @@
 /** Create a new fibril for a new connection.
  *
- * Create new fibril for connection, fill in connection structures and inserts
+ * 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_hash  Identification of the incoming connection.
+ * @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.
@@ -657,11 +755,12 @@
  * @param cfibril       Fibril function that should be called upon opening the
  *                      connection.
+ * @param carg          Extra argument to pass to the connection fibril
  *
  * @return New fibril id or NULL on failure.
  *
  */
-fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
+fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash,
     ipc_callid_t callid, ipc_call_t *call,
-    void (*cfibril)(ipc_callid_t, ipc_call_t *))
+    async_client_conn_t cfibril, void *carg)
 {
 	connection_t *conn = malloc(sizeof(*conn));
@@ -673,9 +772,10 @@
 	}
 	
-	conn->in_task_hash = in_task_hash;
+	conn->in_task_id = in_task_id;
 	conn->in_phone_hash = in_phone_hash;
 	list_initialize(&conn->msg_queue);
 	conn->callid = callid;
 	conn->close_callid = 0;
+	conn->carg = carg;
 	
 	if (call)
@@ -719,4 +819,6 @@
 static void handle_call(ipc_callid_t callid, ipc_call_t *call)
 {
+	assert(call);
+	
 	/* Unrouted call - take some default action */
 	if ((callid & IPC_CALLID_NOTIFICATION)) {
@@ -729,6 +831,6 @@
 	case IPC_M_CONNECT_ME_TO:
 		/* Open new connection with fibril, etc. */
-		async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call),
-		    callid, call, client_connection);
+		async_new_connection(call->in_task_id, IPC_GET_ARG5(*call),
+		    callid, call, client_connection, NULL);
 		return;
 	}
@@ -750,6 +852,6 @@
 	futex_down(&async_futex);
 	
-	link_t *cur = timeout_list.next;
-	while (cur != &timeout_list) {
+	link_t *cur = list_first(&timeout_list);
+	while (cur != NULL) {
 		awaiter_t *waiter =
 		    list_get_instance(cur, awaiter_t, to_event.link);
@@ -757,6 +859,4 @@
 		if (tv_gt(&waiter->to_event.expires, &tv))
 			break;
-		
-		cur = cur->next;
 		
 		list_remove(&waiter->to_event.link);
@@ -772,4 +872,6 @@
 			fibril_add_ready(waiter->fid);
 		}
+		
+		cur = list_first(&timeout_list);
 	}
 	
@@ -798,6 +900,6 @@
 		suseconds_t timeout;
 		if (!list_empty(&timeout_list)) {
-			awaiter_t *waiter = list_get_instance(timeout_list.next,
-			    awaiter_t, to_event.link);
+			awaiter_t *waiter = list_get_instance(
+			    list_first(&timeout_list), awaiter_t, to_event.link);
 			
 			struct timeval tv;
@@ -876,11 +978,28 @@
 void __async_init(void)
 {
-	if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
-	    &client_hash_table_ops))
+	if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
+	    2, &client_hash_table_ops))
 		abort();
 	
-	if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,
-	    &conn_hash_table_ops))
+	if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS,
+	    1, &conn_hash_table_ops))
 		abort();
+	
+	session_ns = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (session_ns == NULL)
+		abort();
+	
+	session_ns->mgmt = EXCHANGE_ATOMIC;
+	session_ns->phone = PHONE_NS;
+	session_ns->arg1 = 0;
+	session_ns->arg2 = 0;
+	session_ns->arg3 = 0;
+	
+	fibril_mutex_initialize(&session_ns->remote_state_mtx);
+	session_ns->remote_state_data = NULL;
+	
+	list_initialize(&session_ns->exch_list);
+	fibril_mutex_initialize(&session_ns->mutex);
+	atomic_set(&session_ns->refcnt, 0);
 }
 
@@ -897,6 +1016,8 @@
  *
  */
-static void reply_received(void *arg, int retval, ipc_call_t *data)
-{
+void reply_received(void *arg, int retval, ipc_call_t *data)
+{
+	assert(arg);
+	
 	futex_down(&async_futex);
 	
@@ -928,6 +1049,6 @@
  * completion.
  *
- * @param phoneid Handle of the phone that will be used for the send.
- * @param method  Service-defined method.
+ * @param exch    Exchange for sending the message.
+ * @param imethod Service-defined interface and method.
  * @param arg1    Service-defined payload argument.
  * @param arg2    Service-defined payload argument.
@@ -940,10 +1061,12 @@
  *
  */
-aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
 {
+	if (exch == NULL)
+		return 0;
+	
 	amsg_t *msg = malloc(sizeof(amsg_t));
-	
-	if (!msg)
+	if (msg == NULL)
 		return 0;
 	
@@ -959,5 +1082,5 @@
 	msg->wdata.active = true;
 	
-	ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
+	ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg,
 	    reply_received, true);
 	
@@ -970,6 +1093,6 @@
  * completion.
  *
- * @param phoneid Handle of the phone that will be used for the send.
- * @param method  Service-defined method.
+ * @param exch    Exchange for sending the message.
+ * @param imethod Service-defined interface and method.
  * @param arg1    Service-defined payload argument.
  * @param arg2    Service-defined payload argument.
@@ -983,11 +1106,14 @@
  *
  */
-aid_t async_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
     ipc_call_t *dataptr)
 {
+	if (exch == NULL)
+		return 0;
+	
 	amsg_t *msg = malloc(sizeof(amsg_t));
 	
-	if (!msg)
+	if (msg == NULL)
 		return 0;
 	
@@ -1003,6 +1129,6 @@
 	msg->wdata.active = true;
 	
-	ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
-	    reply_received, true);
+	ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,
+	    msg, reply_received, true);
 	
 	return (aid_t) msg;
@@ -1018,4 +1144,6 @@
 void async_wait_for(aid_t amsgid, sysarg_t *retval)
 {
+	assert(amsgid);
+	
 	amsg_t *msg = (amsg_t *) amsgid;
 	
@@ -1054,4 +1182,6 @@
 int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout)
 {
+	assert(amsgid);
+	
 	amsg_t *msg = (amsg_t *) amsgid;
 	
@@ -1122,24 +1252,4 @@
 }
 
-/** Setter for client_connection function pointer.
- *
- * @param conn Function that will implement a new connection fibril.
- *
- */
-void async_set_client_connection(async_client_conn_t conn)
-{
-	client_connection = conn;
-}
-
-/** Setter for interrupt_received function pointer.
- *
- * @param intr Function that will implement a new interrupt
- *             notification fibril.
- */
-void async_set_interrupt_received(async_client_conn_t intr)
-{
-	interrupt_received = intr;
-}
-
 /** Pseudo-synchronous message sending - fast version.
  *
@@ -1149,6 +1259,6 @@
  * transferring more arguments, see the slower async_req_slow().
  *
- * @param phoneid Hash of the phone through which to make the call.
- * @param method  Method of the call.
+ * @param exch    Exchange for sending the message.
+ * @param imethod Interface and method of the call.
  * @param arg1    Service-defined payload argument.
  * @param arg2    Service-defined payload argument.
@@ -1164,14 +1274,17 @@
  *
  */
-sysarg_t async_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+sysarg_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
     sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
 {
+	if (exch == NULL)
+		return ENOENT;
+	
 	ipc_call_t result;
-	aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4,
+	aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,
 	    &result);
 	
 	sysarg_t rc;
-	async_wait_for(eid, &rc);
+	async_wait_for(aid, &rc);
 	
 	if (r1)
@@ -1197,6 +1310,6 @@
  * Send message asynchronously and return only after the reply arrives.
  *
- * @param phoneid Hash of the phone through which to make the call.
- * @param method  Method of the call.
+ * @param exch    Exchange for sending the message.
+ * @param imethod Interface and method of the call.
  * @param arg1    Service-defined payload argument.
  * @param arg2    Service-defined payload argument.
@@ -1213,14 +1326,17 @@
  *
  */
-sysarg_t async_req_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+sysarg_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
     sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
 {
+	if (exch == NULL)
+		return ENOENT;
+	
 	ipc_call_t result;
-	aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5,
+	aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,
 	    &result);
 	
 	sysarg_t rc;
-	async_wait_for(eid, &rc);
+	async_wait_for(aid, &rc);
 	
 	if (r1)
@@ -1242,37 +1358,46 @@
 }
 
-void async_msg_0(int phone, sysarg_t imethod)
-{
-	ipc_call_async_0(phone, imethod, NULL, NULL, true);
-}
-
-void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
-{
-	ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
-}
-
-void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
-{
-	ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
-}
-
-void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3)
-{
-	ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
-}
-
-void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, sysarg_t arg4)
-{
-	ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
-	    true);
-}
-
-void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
-{
-	ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
-	    NULL, true);
+void async_msg_0(async_exch_t *exch, sysarg_t imethod)
+{
+	if (exch != NULL)
+		ipc_call_async_0(exch->phone, imethod, NULL, NULL, true);
+}
+
+void async_msg_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1)
+{
+	if (exch != NULL)
+		ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL, true);
+}
+
+void async_msg_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2)
+{
+	if (exch != NULL)
+		ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL,
+		    true);
+}
+
+void async_msg_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3)
+{
+	if (exch != NULL)
+		ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL,
+		    NULL, true);
+}
+
+void async_msg_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
+{
+	if (exch != NULL)
+		ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4,
+		    NULL, NULL, true);
+}
+
+void async_msg_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
+{
+	if (exch != NULL)
+		ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4,
+		    arg5, NULL, NULL, true);
 }
 
@@ -1311,16 +1436,22 @@
 }
 
-int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
-    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
-{
-	return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
-}
-
-int async_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)
-{
-	return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
-	    arg5, mode);
+int async_forward_fast(ipc_callid_t callid, async_exch_t *exch,
+    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
+{
+	if (exch == NULL)
+		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,
+    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
+    sysarg_t arg4, sysarg_t arg5, unsigned int mode)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return ipc_forward_slow(callid, exch->phone, imethod, arg1, arg2, arg3,
+	    arg4, arg5, mode);
 }
 
@@ -1329,5 +1460,5 @@
  * Ask through phone for a new connection to some service.
  *
- * @param phone           Phone handle used for contacting the other side.
+ * @param exch            Exchange for sending the message.
  * @param arg1            User defined argument.
  * @param arg2            User defined argument.
@@ -1335,47 +1466,194 @@
  * @param client_receiver Connection handing routine.
  *
- * @return New phone handle on success or a negative error code.
- *
- */
-int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, async_client_conn_t client_receiver)
-{
-	sysarg_t task_hash;
+ * @return Zero on success or a negative error code.
+ *
+ */
+int async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, async_client_conn_t client_receiver, void *carg)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
 	sysarg_t phone_hash;
-	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
-	    NULL, NULL, NULL, &task_hash, &phone_hash);
+	sysarg_t rc;
+
+	aid_t req;
+	ipc_call_t answer;
+	req = async_send_3(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
+	    &answer);
+	async_wait_for(req, &rc);
+	if (rc != EOK)
+		return (int) rc;
+
+	phone_hash = IPC_GET_ARG5(answer);
+
+	if (client_receiver != NULL)
+		async_new_connection(answer.in_task_id, phone_hash, 0, NULL,
+		    client_receiver, carg);
+	
+	return EOK;
+}
+
+/** Wrapper for making IPC_M_CONNECT_ME calls using the async framework.
+ *
+ * Ask through for a cloned connection to some service.
+ *
+ * @param mgmt Exchange management style.
+ * @param exch Exchange for sending the message.
+ *
+ * @return New session on success or NULL on error.
+ *
+ */
+async_sess_t *async_connect_me(exch_mgmt_t mgmt, async_exch_t *exch)
+{
+	if (exch == NULL) {
+		errno = ENOENT;
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	ipc_call_t result;
+	
+	amsg_t *msg = malloc(sizeof(amsg_t));
+	if (msg == NULL) {
+		free(sess);
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	msg->done = false;
+	msg->dataptr = &result;
+	
+	msg->wdata.to_event.inlist = false;
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
+	msg->wdata.active = true;
+	
+	ipc_call_async_0(exch->phone, IPC_M_CONNECT_ME, msg,
+	    reply_received, true);
+	
+	sysarg_t rc;
+	async_wait_for((aid_t) msg, &rc);
+	
+	if (rc != EOK) {
+		errno = rc;
+		free(sess);
+		return NULL;
+	}
+	
+	int phone = (int) IPC_GET_ARG5(result);
+	
+	if (phone < 0) {
+		errno = phone;
+		free(sess);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
+}
+
+static int async_connect_me_to_internal(int phone, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, sysarg_t arg4)
+{
+	ipc_call_t result;
+	
+	amsg_t *msg = malloc(sizeof(amsg_t));
+	if (msg == NULL)
+		return ENOENT;
+	
+	msg->done = false;
+	msg->dataptr = &result;
+	
+	msg->wdata.to_event.inlist = false;
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
+	msg->wdata.active = true;
+	
+	ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4,
+	    msg, reply_received, true);
+	
+	sysarg_t rc;
+	async_wait_for((aid_t) msg, &rc);
+	
 	if (rc != EOK)
 		return rc;
 	
-	if (client_receiver != NULL)
-		async_new_connection(task_hash, phone_hash, 0, NULL,
-		    client_receiver);
-	
-	return EOK;
+	return (int) IPC_GET_ARG5(result);
 }
 
 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
  *
- * Ask through phone for a new connection to some service.
- *
- * @param phone Phone handle used for contacting the other side.
- * @param arg1  User defined argument.
- * @param arg2  User defined argument.
- * @param arg3  User defined argument.
- *
- * @return New phone handle on success or a negative error code.
- *
- */
-int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3)
-{
-	sysarg_t newphid;
-	int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
-	    NULL, NULL, NULL, NULL, &newphid);
-	
-	if (rc != EOK)
-		return rc;
-	
-	return newphid;
+ * Ask through for a new connection to some service.
+ *
+ * @param mgmt Exchange management style.
+ * @param exch Exchange for sending the message.
+ * @param arg1 User defined argument.
+ * @param arg2 User defined argument.
+ * @param arg3 User defined argument.
+ *
+ * @return New session on success or NULL on error.
+ *
+ */
+async_sess_t *async_connect_me_to(exch_mgmt_t mgmt, async_exch_t *exch,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
+{
+	if (exch == NULL) {
+		errno = ENOENT;
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
+	    0);
+	
+	if (phone < 0) {
+		errno = phone;
+		free(sess);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = arg1;
+	sess->arg2 = arg2;
+	sess->arg3 = arg3;
+	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
 }
 
@@ -1385,23 +1663,50 @@
  * success.
  *
- * @param phoneid Phone handle used for contacting the other side.
- * @param arg1    User defined argument.
- * @param arg2    User defined argument.
- * @param arg3    User defined argument.
- *
- * @return New phone handle on success or a negative error code.
- *
- */
-int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3)
-{
-	sysarg_t newphid;
-	int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
-	    IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
-	
-	if (rc != EOK)
-		return rc;
-	
-	return newphid;
+ * @param mgmt Exchange management style.
+ * @param exch Exchange for sending the message.
+ * @param arg1 User defined argument.
+ * @param arg2 User defined argument.
+ * @param arg3 User defined argument.
+ *
+ * @return New session on success or NULL on error.
+ *
+ */
+async_sess_t *async_connect_me_to_blocking(exch_mgmt_t mgmt, async_exch_t *exch,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
+{
+	if (exch == NULL) {
+		errno = ENOENT;
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
+	    IPC_FLAG_BLOCKING);
+	
+	if (phone < 0) {
+		errno = phone;
+		free(sess);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = arg1;
+	sess->arg2 = arg2;
+	sess->arg3 = arg3;
+	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
 }
 
@@ -1409,19 +1714,59 @@
  *
  */
-int async_connect_kbox(task_id_t id)
-{
-	return ipc_connect_kbox(id);
+async_sess_t *async_connect_kbox(task_id_t id)
+{
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	int phone = ipc_connect_kbox(id);
+	if (phone < 0) {
+		errno = phone;
+		free(sess);
+		return NULL;
+	}
+	
+	sess->mgmt = EXCHANGE_ATOMIC;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
+}
+
+static int async_hangup_internal(int phone)
+{
+	return ipc_hangup(phone);
 }
 
 /** Wrapper for ipc_hangup.
  *
- * @param phone Phone handle to hung up.
+ * @param sess Session to hung up.
  *
  * @return Zero on success or a negative error code.
  *
  */
-int async_hangup(int phone)
-{
-	return ipc_hangup(phone);
+int async_hangup(async_sess_t *sess)
+{
+	assert(sess);
+	
+	if (atomic_get(&sess->refcnt) > 0)
+		return EBUSY;
+	
+	int rc = async_hangup_internal(sess->phone);
+	if (rc == EOK)
+		free(sess);
+	
+	return rc;
 }
 
@@ -1432,20 +1777,145 @@
 }
 
+/** Start new exchange in a session.
+ *
+ * @param session Session.
+ *
+ * @return New exchange or NULL on error.
+ *
+ */
+async_exch_t *async_exchange_begin(async_sess_t *sess)
+{
+	if (sess == NULL)
+		return NULL;
+	
+	async_exch_t *exch;
+	
+	fibril_mutex_lock(&async_sess_mutex);
+	
+	if (!list_empty(&sess->exch_list)) {
+		/*
+		 * There are inactive exchanges in the session.
+		 */
+		exch = (async_exch_t *)
+		    list_get_instance(list_first(&sess->exch_list),
+		    async_exch_t, sess_link);
+		
+		list_remove(&exch->sess_link);
+		list_remove(&exch->global_link);
+	} else {
+		/*
+		 * There are no available exchanges in the session.
+		 */
+		
+		if ((sess->mgmt == EXCHANGE_ATOMIC) ||
+		    (sess->mgmt == EXCHANGE_SERIALIZE)) {
+			exch = (async_exch_t *) malloc(sizeof(async_exch_t));
+			if (exch != NULL) {
+				link_initialize(&exch->sess_link);
+				link_initialize(&exch->global_link);
+				exch->sess = sess;
+				exch->phone = sess->phone;
+			}
+		} else {  /* EXCHANGE_PARALLEL */
+			/*
+			 * Make a one-time attempt to connect a new data phone.
+			 */
+			
+			int phone;
+			
+retry:
+			phone = async_connect_me_to_internal(sess->phone, sess->arg1,
+			    sess->arg2, sess->arg3, 0);
+			if (phone >= 0) {
+				exch = (async_exch_t *) malloc(sizeof(async_exch_t));
+				if (exch != NULL) {
+					link_initialize(&exch->sess_link);
+					link_initialize(&exch->global_link);
+					exch->sess = sess;
+					exch->phone = phone;
+				} else
+					async_hangup_internal(phone);
+			} else if (!list_empty(&inactive_exch_list)) {
+				/*
+				 * We did not manage to connect a new phone. But we
+				 * can try to close some of the currently inactive
+				 * connections in other sessions and try again.
+				 */
+				exch = (async_exch_t *)
+				    list_get_instance(list_first(&inactive_exch_list),
+				    async_exch_t, global_link);
+				
+				list_remove(&exch->sess_link);
+				list_remove(&exch->global_link);
+				async_hangup_internal(exch->phone);
+				free(exch);
+				goto retry;
+			} else {
+				/*
+				 * Wait for a phone to become available.
+				 */
+				fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
+				goto retry;
+			}
+		}
+	}
+	
+	fibril_mutex_unlock(&async_sess_mutex);
+	
+	if (exch != NULL) {
+		atomic_inc(&sess->refcnt);
+		
+		if (sess->mgmt == EXCHANGE_SERIALIZE)
+			fibril_mutex_lock(&sess->mutex);
+	}
+	
+	return exch;
+}
+
+/** Finish an exchange.
+ *
+ * @param exch Exchange to finish.
+ *
+ */
+void async_exchange_end(async_exch_t *exch)
+{
+	if (exch == NULL)
+		return;
+	
+	async_sess_t *sess = exch->sess;
+	
+	atomic_dec(&sess->refcnt);
+	
+	if (sess->mgmt == EXCHANGE_SERIALIZE)
+		fibril_mutex_unlock(&sess->mutex);
+	
+	fibril_mutex_lock(&async_sess_mutex);
+	
+	list_append(&exch->sess_link, &sess->exch_list);
+	list_append(&exch->global_link, &inactive_exch_list);
+	fibril_condvar_signal(&avail_phone_cv);
+	
+	fibril_mutex_unlock(&async_sess_mutex);
+}
+
 /** Wrapper for IPC_M_SHARE_IN calls using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param dst     Destination address space area base.
- * @param size    Size of the destination address space area.
- * @param arg     User defined argument.
- * @param flags   Storage for the received flags. Can be NULL.
+ * @param exch  Exchange for sending the message.
+ * @param dst   Destination address space area base.
+ * @param size  Size of the destination address space area.
+ * @param arg   User defined argument.
+ * @param flags Storage for the received flags. Can be NULL.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
-    unsigned int *flags)
-{
+int async_share_in_start(async_exch_t *exch, void *dst, size_t size,
+    sysarg_t arg, unsigned int *flags)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
 	sysarg_t tmp_flags;
-	int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
+	int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst,
 	    (sysarg_t) size, arg, NULL, &tmp_flags);
 	
@@ -1505,14 +1975,17 @@
 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param src     Source address space area base address.
- * @param flags   Flags to be used for sharing. Bits can be only cleared.
+ * @param exch  Exchange for sending the message.
+ * @param src   Source address space area base address.
+ * @param flags Flags to be used for sharing. Bits can be only cleared.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_share_out_start(int phoneid, void *src, unsigned int flags)
-{
-	return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
+int async_share_out_start(async_exch_t *exch, void *src, unsigned int flags)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return async_req_3_0(exch, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
 	    (sysarg_t) flags);
 }
@@ -1567,16 +2040,36 @@
 }
 
+/** Start IPC_M_DATA_READ using the async framework.
+ *
+ * @param exch    Exchange for sending the message.
+ * @param dst     Address of the beginning of the destination buffer.
+ * @param size    Size of the destination buffer (in bytes).
+ * @param dataptr Storage of call data (arg 2 holds actual data size).
+ *
+ * @return Hash of the sent message or 0 on error.
+ *
+ */
+aid_t async_data_read(async_exch_t *exch, void *dst, size_t size,
+    ipc_call_t *dataptr)
+{
+	return async_send_2(exch, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size, dataptr);
+}
+
 /** Wrapper for IPC_M_DATA_READ calls using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param dst     Address of the beginning of the destination buffer.
- * @param size    Size of the destination buffer.
+ * @param exch Exchange for sending the message.
+ * @param dst  Address of the beginning of the destination buffer.
+ * @param size Size of the destination buffer.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_data_read_start(int phoneid, void *dst, size_t size)
-{
-	return async_req_2_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
+int async_data_read_start(async_exch_t *exch, void *dst, size_t size)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return async_req_2_0(exch, IPC_M_DATA_READ, (sysarg_t) dst,
 	    (sysarg_t) size);
 }
@@ -1634,7 +2127,11 @@
  *
  */
-int async_data_read_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
-{
+int async_data_read_forward_fast(async_exch_t *exch, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
+    ipc_call_t *dataptr)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
 	ipc_callid_t callid;
 	if (!async_data_read_receive(&callid, NULL)) {
@@ -1643,5 +2140,5 @@
 	}
 	
-	aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
+	aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
 	    dataptr);
 	if (msg == 0) {
@@ -1650,5 +2147,5 @@
 	}
 	
-	int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
+	int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
 	    IPC_FF_ROUTE_FROM_ME);
 	if (retval != EOK) {
@@ -1666,14 +2163,17 @@
 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param src     Address of the beginning of the source buffer.
- * @param size    Size of the source buffer.
+ * @param exch Exchange for sending the message.
+ * @param src  Address of the beginning of the source buffer.
+ * @param size Size of the source buffer.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_data_write_start(int phoneid, const void *src, size_t size)
-{
-	return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
+int async_data_write_start(async_exch_t *exch, const void *src, size_t size)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return async_req_2_0(exch, IPC_M_DATA_WRITE, (sysarg_t) src,
 	    (sysarg_t) size);
 }
@@ -1752,4 +2252,6 @@
     size_t *received)
 {
+	assert(data);
+	
 	ipc_callid_t callid;
 	size_t size;
@@ -1819,7 +2321,11 @@
  *
  */
-int async_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
-{
+int async_data_write_forward_fast(async_exch_t *exch, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
+    ipc_call_t *dataptr)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
 	ipc_callid_t callid;
 	if (!async_data_write_receive(&callid, NULL)) {
@@ -1828,5 +2334,5 @@
 	}
 	
-	aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
+	aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
 	    dataptr);
 	if (msg == 0) {
@@ -1835,5 +2341,5 @@
 	}
 	
-	int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
+	int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
 	    IPC_FF_ROUTE_FROM_ME);
 	if (retval != EOK) {
@@ -1849,4 +2355,257 @@
 }
 
+/** Wrapper for sending an exchange over different exchange for cloning
+ *
+ * @param exch       Exchange to be used for sending.
+ * @param clone_exch Exchange to be cloned.
+ *
+ */
+int async_exchange_clone(async_exch_t *exch, async_exch_t *clone_exch)
+{
+	return async_req_1_0(exch, IPC_M_CONNECTION_CLONE, clone_exch->phone);
+}
+
+/** Wrapper for receiving the IPC_M_CONNECTION_CLONE calls.
+ *
+ * If the current call is IPC_M_CONNECTION_CLONE then a new
+ * async session is created for the accepted phone.
+ *
+ * @param mgmt Exchange management style.
+ *
+ * @return New async session or NULL on failure.
+ *
+ */
+async_sess_t *async_clone_receive(exch_mgmt_t mgmt)
+{
+	/* Accept the phone */
+	ipc_call_t call;
+	ipc_callid_t callid = async_get_call(&call);
+	int phone = (int) IPC_GET_ARG1(call);
+	
+	if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) ||
+	    (phone < 0)) {
+		async_answer_0(callid, EINVAL);
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	/* Acknowledge the cloned phone */
+	async_answer_0(callid, EOK);
+	
+	return sess;
+}
+
+/** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls.
+ *
+ * If the current call is IPC_M_CONNECT_TO_ME then a new
+ * async session is created for the accepted phone.
+ *
+ * @param mgmt Exchange management style.
+ *
+ * @return New async session.
+ * @return NULL on failure.
+ *
+ */
+async_sess_t *async_callback_receive(exch_mgmt_t mgmt)
+{
+	/* 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);
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	/* Acknowledge the connected phone */
+	async_answer_0(callid, EOK);
+	
+	return sess;
+}
+
+/** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls.
+ *
+ * If the call is IPC_M_CONNECT_TO_ME then a new
+ * async session is created. However, the phone is
+ * not accepted automatically.
+ *
+ * @param mgmt   Exchange management style.
+ * @param call   Call data.
+ *
+ * @return New async session.
+ * @return NULL on failure.
+ * @return NULL if the call is not IPC_M_CONNECT_TO_ME.
+ *
+ */
+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))
+		return NULL;
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL)
+		return NULL;
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	fibril_mutex_initialize(&sess->remote_state_mtx);
+	sess->remote_state_data = NULL;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
+}
+
+int async_state_change_start(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, async_exch_t *other_exch)
+{
+	return async_req_5_0(exch, IPC_M_STATE_CHANGE_AUTHORIZE,
+	    arg1, arg2, arg3, 0, other_exch->phone);
+}
+
+bool async_state_change_receive(ipc_callid_t *callid, sysarg_t *arg1,
+    sysarg_t *arg2, sysarg_t *arg3)
+{
+	assert(callid);
+
+	ipc_call_t call;
+	*callid = async_get_call(&call);
+
+	if (IPC_GET_IMETHOD(call) != IPC_M_STATE_CHANGE_AUTHORIZE)
+		return false;
+	
+	if (arg1)
+		*arg1 = IPC_GET_ARG1(call);
+	if (arg2)
+		*arg2 = IPC_GET_ARG2(call);
+	if (arg3)
+		*arg3 = IPC_GET_ARG3(call);
+
+	return true;
+}
+
+int async_state_change_finalize(ipc_callid_t callid, async_exch_t *other_exch)
+{
+	return ipc_answer_1(callid, EOK, other_exch->phone);
+}
+
+/** Lock and get session remote state
+ *
+ * Lock and get the local replica of the remote state
+ * in stateful sessions. The call should be paired
+ * with async_remote_state_release*().
+ *
+ * @param[in] sess Stateful session.
+ *
+ * @return Local replica of the remote state.
+ *
+ */
+void *async_remote_state_acquire(async_sess_t *sess)
+{
+	fibril_mutex_lock(&sess->remote_state_mtx);
+	return sess->remote_state_data;
+}
+
+/** Update the session remote state
+ *
+ * Update the local replica of the remote state
+ * in stateful sessions. The remote state must
+ * be already locked.
+ *
+ * @param[in] sess  Stateful session.
+ * @param[in] state New local replica of the remote state.
+ *
+ */
+void async_remote_state_update(async_sess_t *sess, void *state)
+{
+	assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
+	sess->remote_state_data = state;
+}
+
+/** Release the session remote state
+ *
+ * Unlock the local replica of the remote state
+ * in stateful sessions.
+ *
+ * @param[in] sess Stateful session.
+ *
+ */
+void async_remote_state_release(async_sess_t *sess)
+{
+	assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
+	
+	fibril_mutex_unlock(&sess->remote_state_mtx);
+}
+
+/** Release the session remote state and end an exchange
+ *
+ * Unlock the local replica of the remote state
+ * in stateful sessions. This is convenience function
+ * which gets the session pointer from the exchange
+ * and also ends the exchange.
+ *
+ * @param[in] exch Stateful session's exchange.
+ *
+ */
+void async_remote_state_release_exchange(async_exch_t *exch)
+{
+	if (exch == NULL)
+		return;
+	
+	async_sess_t *sess = exch->sess;
+	assert(fibril_mutex_is_locked(&sess->remote_state_mtx));
+	
+	async_exchange_end(exch);
+	fibril_mutex_unlock(&sess->remote_state_mtx);
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/async_obsolete.c
===================================================================
--- uspace/lib/c/generic/async_obsolete.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/async_obsolete.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#define LIBC_ASYNC_C_
+#define LIBC_ASYNC_OBSOLETE_C_
+#include <ipc/ipc.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include "private/async.h"
+#undef LIBC_ASYNC_C_
+#undef LIBC_ASYNC_OBSOLETE_C_
+
+#include <fibril.h>
+#include <malloc.h>
+#include <errno.h>
+
+/** Send message and return id of the sent message.
+ *
+ * The return value can be used as input for async_wait() to wait for
+ * completion.
+ *
+ * @param phoneid Handle of the phone that will be used for the send.
+ * @param method  Service-defined 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 dataptr If non-NULL, storage where the reply data will be
+ *                stored.
+ *
+ * @return Hash of the sent message or 0 on error.
+ *
+ */
+aid_t async_obsolete_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
+{
+	amsg_t *msg = malloc(sizeof(amsg_t));
+	
+	if (!msg)
+		return 0;
+	
+	msg->done = false;
+	msg->dataptr = dataptr;
+	
+	msg->wdata.to_event.inlist = false;
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
+	msg->wdata.active = true;
+	
+	ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
+	    reply_received, true);
+	
+	return (aid_t) msg;
+}
+
+/** Pseudo-synchronous message sending - fast version.
+ *
+ * Send message asynchronously and return only after the reply arrives.
+ *
+ * This function can only transfer 4 register payload arguments. For
+ * transferring more arguments, see the slower async_req_slow().
+ *
+ * @param phoneid Hash of the phone through which to make the call.
+ * @param method  Method of the call.
+ * @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 r1      If non-NULL, storage for the 1st reply argument.
+ * @param r2      If non-NULL, storage for the 2nd reply argument.
+ * @param r3      If non-NULL, storage for the 3rd reply argument.
+ * @param r4      If non-NULL, storage for the 4th reply argument.
+ * @param r5      If non-NULL, storage for the 5th reply argument.
+ *
+ * @return Return code of the reply or a negative error code.
+ *
+ */
+sysarg_t async_obsolete_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
+    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
+{
+	ipc_call_t result;
+	aid_t eid = async_obsolete_send_4(phoneid, method, arg1, arg2, arg3, arg4,
+	    &result);
+	
+	sysarg_t rc;
+	async_wait_for(eid, &rc);
+	
+	if (r1)
+		*r1 = IPC_GET_ARG1(result);
+	
+	if (r2)
+		*r2 = IPC_GET_ARG2(result);
+	
+	if (r3)
+		*r3 = IPC_GET_ARG3(result);
+	
+	if (r4)
+		*r4 = IPC_GET_ARG4(result);
+	
+	if (r5)
+		*r5 = IPC_GET_ARG5(result);
+	
+	return rc;
+}
+
+/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param src     Source address space area base address.
+ * @param flags   Flags to be used for sharing. Bits can be only cleared.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_obsolete_share_out_start(int phoneid, void *src, unsigned int flags)
+{
+	return async_obsolete_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
+	    (sysarg_t) flags);
+}
+
+/** Wrapper for ipc_hangup.
+ *
+ * @param phone Phone handle to hung up.
+ *
+ * @return Zero on success or a negative error code.
+ *
+ */
+int async_obsolete_hangup(int phone)
+{
+	return ipc_hangup(phone);
+}
+
+/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param src     Address of the beginning of the source buffer.
+ * @param size    Size of the source buffer.
+ * @param flags   Flags to control the data transfer.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_obsolete_data_write_start_generic(int phoneid, const void *src, size_t size,
+    int flags)
+{
+	return async_obsolete_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
+	    (sysarg_t) size, (sysarg_t) flags);
+}
+
+/** Start IPC_M_DATA_READ using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Address of the beginning of the destination buffer.
+ * @param size    Size of the destination buffer (in bytes).
+ * @param dataptr Storage of call data (arg 2 holds actual data size).
+ *
+ * @return Hash of the sent message or 0 on error.
+ *
+ */
+aid_t async_obsolete_data_read(int phone, void *dst, size_t size,
+    ipc_call_t *dataptr)
+{
+	return async_obsolete_send_2(phone, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size, dataptr);
+}
+
+/** Wrapper for IPC_M_DATA_READ calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Address of the beginning of the destination buffer.
+ * @param size    Size of the destination buffer.
+ * @param flags   Flags to control the data transfer.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_obsolete_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
+{
+	return async_obsolete_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size, (sysarg_t) flags);
+}
+
+/** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework.
+ *
+ * Ask through phone for a new connection to some service.
+ *
+ * @param phone           Phone handle used for contacting the other side.
+ * @param arg1            User defined argument.
+ * @param arg2            User defined argument.
+ * @param arg3            User defined argument.
+ * @param client_receiver Connection handing routine.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_obsolete_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, async_client_conn_t client_receiver, void *carg)
+{
+	sysarg_t task_hash;
+	sysarg_t phone_hash;
+	int rc = async_obsolete_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
+	    NULL, NULL, NULL, &task_hash, &phone_hash);
+	if (rc != EOK)
+		return rc;
+	
+	if (client_receiver != NULL)
+		async_new_connection(task_hash, phone_hash, 0, NULL,
+		    client_receiver, carg);
+	
+	return EOK;
+}
+
+/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
+ *
+ * Ask through phone for a new connection to some service.
+ *
+ * @param phone Phone handle used for contacting the other side.
+ * @param arg1  User defined argument.
+ * @param arg2  User defined argument.
+ * @param arg3  User defined argument.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_obsolete_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	sysarg_t newphid;
+	int rc = async_obsolete_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
+	    NULL, NULL, NULL, NULL, &newphid);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return newphid;
+}
+
+/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
+ *
+ * Ask through phone for a new connection to some service and block until
+ * success.
+ *
+ * @param phoneid Phone handle used for contacting the other side.
+ * @param arg1    User defined argument.
+ * @param arg2    User defined argument.
+ * @param arg3    User defined argument.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_obsolete_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	sysarg_t newphid;
+	int rc = async_obsolete_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
+	    IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return newphid;
+}
+
+/** Send message and return id of the sent message
+ *
+ * The return value can be used as input for async_wait() to wait for
+ * completion.
+ *
+ * @param phoneid Handle of the phone that will be used for the send.
+ * @param method  Service-defined 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 dataptr If non-NULL, storage where the reply data will be
+ *                stored.
+ *
+ * @return Hash of the sent message or 0 on error.
+ *
+ */
+aid_t async_obsolete_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
+    ipc_call_t *dataptr)
+{
+	amsg_t *msg = malloc(sizeof(amsg_t));
+	
+	if (!msg)
+		return 0;
+	
+	msg->done = false;
+	msg->dataptr = dataptr;
+	
+	msg->wdata.to_event.inlist = false;
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
+	msg->wdata.active = true;
+	
+	ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
+	    reply_received, true);
+	
+	return (aid_t) msg;
+}
+
+void async_obsolete_msg_0(int phone, sysarg_t imethod)
+{
+	ipc_call_async_0(phone, imethod, NULL, NULL, true);
+}
+
+void async_obsolete_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
+{
+	ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
+}
+
+void async_obsolete_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
+{
+	ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
+}
+
+void async_obsolete_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
+}
+
+void async_obsolete_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, sysarg_t arg4)
+{
+	ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
+	    true);
+}
+
+void async_obsolete_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
+{
+	ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
+	    NULL, true);
+}
+
+/** Wrapper for IPC_M_SHARE_IN calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Destination address space area base.
+ * @param size    Size of the destination address space area.
+ * @param arg     User defined argument.
+ * @param flags   Storage for the received flags. Can be NULL.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_obsolete_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
+    unsigned int *flags)
+{
+	sysarg_t tmp_flags;
+	int res = async_obsolete_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
+	    (sysarg_t) size, arg, NULL, &tmp_flags);
+	
+	if (flags)
+		*flags = (unsigned int) tmp_flags;
+	
+	return res;
+}
+
+int async_obsolete_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
+{
+	return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
+}
+
+int async_obsolete_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)
+{
+	return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
+	    arg5, mode);
+}
+
+/** Wrapper for forwarding any data that is about to be received
+ *
+ */
+int async_obsolete_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
+{
+	ipc_callid_t callid;
+	if (!async_data_write_receive(&callid, NULL)) {
+		ipc_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	aid_t msg = async_obsolete_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
+	    dataptr);
+	if (msg == 0) {
+		ipc_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
+	    IPC_FF_ROUTE_FROM_ME);
+	if (retval != EOK) {
+		async_wait_for(msg, NULL);
+		ipc_answer_0(callid, retval);
+		return retval;
+	}
+	
+	sysarg_t rc;
+	async_wait_for(msg, &rc);
+	
+	return (int) rc;
+}
+
+/** @}
+ */
Index: pace/lib/c/generic/async_sess.c
===================================================================
--- uspace/lib/c/generic/async_sess.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,308 +1,0 @@
-/*
- * Copyright (c) 2010 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-/**
- * This file implements simple session support for the async framework.
- *
- * By the term 'session', we mean a logical data path between a client and a
- * server over which the client can perform multiple concurrent exchanges.
- * Each exchange consists of one or more requests (IPC calls) which can
- * be potentially blocking.
- *
- * Clients and servers are naturally connected using IPC phones, thus an IPC
- * phone represents a session between a client and a server. In one
- * session, there can be many outstanding exchanges. In the current
- * implementation each concurrent exchanges takes place over a different
- * connection (there can be at most one active exchage per connection).
- *
- * Sessions make it useful for a client or client API to support concurrent
- * requests, independent of the actual implementation. Sessions provide
- * an abstract interface to concurrent IPC communication. This is especially
- * useful for client API stubs that aim to be reentrant (i.e. that allow
- * themselves to be called from different fibrils and threads concurrently).
- *
- * There are several possible implementations of sessions. This implementation
- * uses additional phones to represent sessions. Using phones both for the
- * session and also for its exchages/connections has several advantages:
- *
- * - to make a series of exchanges over a session, the client can continue to
- *   use the existing async framework APIs
- * - the server supports sessions by the virtue of spawning a new connection
- *   fibril, just as it does for every new connection even without sessions
- * - the implementation is pretty straightforward; a very naive implementation
- *   would be to make each exchage using a fresh phone (that is what we
- *   have done in the past); a slightly better approach would be to cache
- *   connections so that they can be reused by a later exchange within
- *   the same session (that is what this implementation does)
- *
- * The main disadvantages of using phones to represent sessions are:
- *
- * - if there are too many exchanges (even cached ones), the task may hit its
- *   limit on the maximum number of connected phones, which could prevent the
- *   task from making new IPC connections to other tasks
- * - if there are too many IPC connections already, it may be impossible to
- *   create an exchange by connecting a new phone thanks to the task's limit on
- *   the maximum number of connected phones
- *
- * These problems can be alleviated by increasing the limit on the maximum
- * number of connected phones to some reasonable value and by limiting the number
- * of cached connections to some fraction of this limit.
- *
- * The cache itself has a mechanism to close some number of unused phones if a
- * new phone cannot be connected, but the outer world currently does not have a
- * way to ask the phone cache to shrink.
- *
- * To minimize the confusion stemming from the fact that we use phones for two
- * things (the session itself and also one for each data connection), this file
- * makes the distinction by using the term 'session phone' for the former and
- * 'data phone' for the latter. Under the hood, all phones remain equal,
- * of course.
- *
- * There is a small inefficiency in that the cache repeatedly allocates and
- * deallocates the conn_node_t structures when in fact it could keep the
- * allocated structures around and reuse them later. But such a solution would
- * be effectively implementing a poor man's slab allocator while it would be
- * better to have the slab allocator ported to uspace so that everyone could
- * benefit from it.
- */
-
-#include <async_sess.h>
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <adt/hash_table.h>
-#include <malloc.h>
-#include <errno.h>
-#include <assert.h>
-#include "private/async_sess.h"
-
-/** An inactive open connection. */
-typedef struct {
-	link_t sess_link;	/**< Link for the session list of inactive connections. */
-	link_t global_link;	/**< Link for the global list of inactive connections. */
-	int data_phone;		/**< Connected data phone. */
-} conn_node_t;
-
-/**
- * Mutex protecting the inactive_conn_head list, the session list and the
- * avail_phone condition variable.
- */
-static fibril_mutex_t async_sess_mutex;
-
-/**
- * List of all currently inactive connections.
- */
-static LIST_INITIALIZE(inactive_conn_head);
-
-/**
- * List of all open sessions.
- */
-static LIST_INITIALIZE(session_list_head);
-
-/**
- * Condition variable used to wait for a phone to become available.
- */
-static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
-
-/** Initialize the async_sess subsystem.
- *
- * Needs to be called prior to any other interface in this file.
- *
- */
-void __async_sess_init(void)
-{
-	fibril_mutex_initialize(&async_sess_mutex);
-	list_initialize(&inactive_conn_head);
-	list_initialize(&session_list_head);
-}
-
-/** Create a session.
- *
- * Session is a logical datapath from a client task to a server task.
- * One session can accomodate multiple concurrent exchanges. Here
- * @a phone is a phone connected to the desired server task.
- *
- * This function always succeeds.
- *
- * @param sess	Session structure provided by caller, will be filled in.
- * @param phone	Phone connected to the desired server task.
- * @param arg1	Value to pass as first argument upon creating a new
- *		connection. Typical use is to identify a resource within
- *		the server that the caller wants to access (port ID,
- *		interface ID, device ID, etc.).
- */
-void async_session_create(async_sess_t *sess, int phone, sysarg_t arg1)
-{
-	sess->sess_phone = phone;
-	sess->connect_arg1 = arg1;
-	list_initialize(&sess->conn_head);
-	
-	/* Add to list of sessions. */
-	fibril_mutex_lock(&async_sess_mutex);
-	list_append(&sess->sess_link, &session_list_head);
-	fibril_mutex_unlock(&async_sess_mutex);
-}
-
-/** Destroy a session.
- *
- * Dismantle session structure @a sess and release any resources (connections)
- * held by the session.
- *
- * @param sess	Session to destroy.
- */
-void async_session_destroy(async_sess_t *sess)
-{
-	conn_node_t *conn;
-
-	/* Remove from list of sessions. */
-	fibril_mutex_lock(&async_sess_mutex);
-	list_remove(&sess->sess_link);
-	fibril_mutex_unlock(&async_sess_mutex);
-
-	/* We did not connect the phone so we do not hang it up either. */
-	sess->sess_phone = -1;
-
-	/* Tear down all data connections. */
-	while (!list_empty(&sess->conn_head)) {
-		conn = list_get_instance(sess->conn_head.next, conn_node_t,
-		    sess_link);
-
-		list_remove(&conn->sess_link);
-		list_remove(&conn->global_link);
-		
-		async_hangup(conn->data_phone);
-		free(conn);
-	}
-	
-	fibril_condvar_broadcast(&avail_phone_cv);
-}
-
-static void conn_node_initialize(conn_node_t *conn)
-{
-	link_initialize(&conn->sess_link);
-	link_initialize(&conn->global_link);
-	conn->data_phone = -1;
-}
-
-/** Start new exchange in a session.
- *
- * @param sess_phone	Session.
- * @return		Phone representing the new exchange or a negative error
- *			code.
- */
-int async_exchange_begin(async_sess_t *sess)
-{
-	conn_node_t *conn;
-	int data_phone;
-
-	fibril_mutex_lock(&async_sess_mutex);
-
-	if (!list_empty(&sess->conn_head)) {
-		/*
-		 * There are inactive connections in the session.
-		 */
-		conn = list_get_instance(sess->conn_head.next, conn_node_t,
-		    sess_link);
-		list_remove(&conn->sess_link);
-		list_remove(&conn->global_link);
-		
-		data_phone = conn->data_phone;
-		free(conn);
-	} else {
-		/*
-		 * There are no available connections in the session.
-		 * Make a one-time attempt to connect a new data phone.
-		 */
-retry:
-		data_phone = async_connect_me_to(sess->sess_phone,
-		    sess->connect_arg1, 0, 0);
-		if (data_phone >= 0) {
-			/* success, do nothing */
-		} else if (!list_empty(&inactive_conn_head)) {
-			/*
-			 * We did not manage to connect a new phone. But we can
-			 * try to close some of the currently inactive
-			 * connections in other sessions and try again.
-			 */
-			conn = list_get_instance(inactive_conn_head.next,
-			    conn_node_t, global_link);
-			list_remove(&conn->global_link);
-			list_remove(&conn->sess_link);
-			data_phone = conn->data_phone;
-			free(conn);
-			async_hangup(data_phone);
-			goto retry;
-		} else {
-			/*
-			 * Wait for a phone to become available.
-			 */
-			fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
-			goto retry;
-		}
-	}
-
-	fibril_mutex_unlock(&async_sess_mutex);
-	return data_phone;
-}
-
-/** Finish an exchange.
- *
- * @param sess		Session.
- * @param data_phone	Phone representing the exchange within the session.
- */
-void async_exchange_end(async_sess_t *sess, int data_phone)
-{
-	conn_node_t *conn;
-
-	fibril_mutex_lock(&async_sess_mutex);
-	fibril_condvar_signal(&avail_phone_cv);
-	conn = (conn_node_t *) malloc(sizeof(conn_node_t));
-	if (!conn) {
-		/*
-		 * Being unable to remember the connected data phone here
-		 * means that we simply hang up.
-		 */
-		async_hangup(data_phone);
-		fibril_mutex_unlock(&async_sess_mutex);
-		return;
-	}
-
-	conn_node_initialize(conn);
-	conn->data_phone = data_phone;
-	list_append(&conn->sess_link, &sess->conn_head);
-	list_append(&conn->global_link, &inactive_conn_head);
-	fibril_mutex_unlock(&async_sess_mutex);
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/clipboard.c
===================================================================
--- uspace/lib/c/generic/clipboard.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/clipboard.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,7 +39,8 @@
 
 #include <clipboard.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <ipc/services.h>
 #include <ipc/clipboard.h>
+#include <fibril_synch.h>
 #include <async.h>
 #include <str.h>
@@ -47,13 +48,33 @@
 #include <malloc.h>
 
-static int clip_phone = -1;
-
-/** Connect to clipboard server
- *
- */
-static void clip_connect(void)
-{
-	while (clip_phone < 0)
-		clip_phone = service_connect_blocking(SERVICE_CLIPBOARD, 0, 0);
+static FIBRIL_MUTEX_INITIALIZE(clip_mutex);
+static async_sess_t *clip_sess = NULL;
+
+/** Start an async exchange on the clipboard session.
+ *
+ * @return New exchange.
+ *
+ */
+static async_exch_t *clip_exchange_begin(void)
+{
+	fibril_mutex_lock(&clip_mutex);
+	
+	while (clip_sess == NULL)
+		clip_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+		    SERVICE_CLIPBOARD, 0, 0);
+	
+	fibril_mutex_unlock(&clip_mutex);
+	
+	return async_exchange_begin(clip_sess);
+}
+
+/** Finish an async exchange on the clipboard session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+static void clip_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
 }
 
@@ -73,22 +94,20 @@
 	
 	if (size == 0) {
-		async_serialize_start();
-		clip_connect();
-		
-		sysarg_t rc = async_req_1_0(clip_phone, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_NONE);
-		
-		async_serialize_end();
+		async_exch_t *exch = clip_exchange_begin();
+		sysarg_t rc = async_req_1_0(exch, CLIPBOARD_PUT_DATA,
+		    CLIPBOARD_TAG_NONE);
+		clip_exchange_end(exch);
 		
 		return (int) rc;
 	} else {
-		async_serialize_start();
-		clip_connect();
-		
-		aid_t req = async_send_1(clip_phone, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_DATA, NULL);
-		sysarg_t rc = async_data_write_start(clip_phone, (void *) str, size);
+		async_exch_t *exch = clip_exchange_begin();
+		aid_t req = async_send_1(exch, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_DATA,
+		    NULL);
+		sysarg_t rc = async_data_write_start(exch, (void *) str, size);
+		clip_exchange_end(exch);
+		
 		if (rc != EOK) {
 			sysarg_t rc_orig;
 			async_wait_for(req, &rc_orig);
-			async_serialize_end();
 			if (rc_orig == EOK)
 				return (int) rc;
@@ -98,5 +117,4 @@
 		
 		async_wait_for(req, &rc);
-		async_serialize_end();
 		
 		return (int) rc;
@@ -117,12 +135,11 @@
 	/* Loop until clipboard read succesful */
 	while (true) {
-		async_serialize_start();
-		clip_connect();
+		async_exch_t *exch = clip_exchange_begin();
 		
 		sysarg_t size;
 		sysarg_t tag;
-		sysarg_t rc = async_req_0_2(clip_phone, CLIPBOARD_CONTENT, &size, &tag);
-		
-		async_serialize_end();
+		sysarg_t rc = async_req_0_2(exch, CLIPBOARD_CONTENT, &size, &tag);
+		
+		clip_exchange_end(exch);
 		
 		if (rc != EOK)
@@ -145,8 +162,9 @@
 				return ENOMEM;
 			
-			async_serialize_start();
-			
-			aid_t req = async_send_1(clip_phone, CLIPBOARD_GET_DATA, tag, NULL);
-			rc = async_data_read_start(clip_phone, (void *) sbuf, size);
+			exch = clip_exchange_begin();
+			aid_t req = async_send_1(exch, CLIPBOARD_GET_DATA, tag, NULL);
+			rc = async_data_read_start(exch, (void *) sbuf, size);
+			clip_exchange_end(exch);
+			
 			if ((int) rc == EOVERFLOW) {
 				/*
@@ -154,5 +172,4 @@
 				 * the last call of CLIPBOARD_CONTENT
 				 */
-				async_serialize_end();
 				break;
 			}
@@ -161,5 +178,4 @@
 				sysarg_t rc_orig;
 				async_wait_for(req, &rc_orig);
-				async_serialize_end();
 				if (rc_orig == EOK)
 					return (int) rc;
@@ -169,5 +185,4 @@
 			
 			async_wait_for(req, &rc);
-			async_serialize_end();
 			
 			if (rc == EOK) {
Index: uspace/lib/c/generic/ddi.c
===================================================================
--- uspace/lib/c/generic/ddi.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/ddi.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -31,6 +31,8 @@
  */
 /** @file
- */ 
+ */
 
+#include <sys/types.h>
+#include <abi/ddi/arg.h>
 #include <ddi.h>
 #include <libarch/ddi.h>
@@ -40,5 +42,4 @@
 #include <align.h>
 #include <libarch/config.h>
-#include <kernel/ddi/ddi_arg.h>
 
 /** Return unique device number.
Index: uspace/lib/c/generic/device/char_dev.c
===================================================================
--- uspace/lib/c/generic/device/char_dev.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/device/char_dev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,35 +45,37 @@
  * using its character interface.
  *
- * @param dev_phone	Phone 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.
+ * @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.
+ * @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(int dev_phone, void *buf, size_t size, bool read)
+static ssize_t char_dev_rw(async_sess_t *sess, void *buf, size_t size, bool read)
 {
-	async_serialize_start();
-	
 	ipc_call_t answer;
 	aid_t req;
 	int ret;
 	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
 	if (read) {
-		req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE),
+		req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE),
 		    CHAR_DEV_READ, &answer);
-		ret = async_data_read_start(dev_phone, buf, size);
+		ret = async_data_read_start(exch, buf, size);
 	} else {
-		req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE),
+		req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE),
 		    CHAR_DEV_WRITE, &answer);
-		ret = async_data_write_start(dev_phone, buf, size);
+		ret = async_data_write_start(exch, buf, size);
 	}
+	
+	async_exchange_end(exch);
 	
 	sysarg_t rc;
 	if (ret != EOK) {
 		async_wait_for(req, &rc);
-		async_serialize_end();
 		if (rc == EOK)
 			return (ssize_t) ret;
@@ -83,5 +85,4 @@
 	
 	async_wait_for(req, &rc);
-	async_serialize_end();
 	
 	ret = (int) rc;
@@ -94,29 +95,31 @@
 /** Read from character device.
  *
- * @param dev_phone	Phone 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.
+ * @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.
+ * @return Non-negative number of bytes actually read from the
+ *         device on success, negative error number otherwise.
+ *
  */
-ssize_t char_dev_read(int dev_phone, void *buf, size_t size)
+ssize_t char_dev_read(async_sess_t *sess, void *buf, size_t size)
 {
-	return char_dev_rw(dev_phone, buf, size, true);
+	return char_dev_rw(sess, buf, size, true);
 }
 
 /** Write to character device.
  *
- * @param dev_phone	Phone 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.
+ * @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.
+ * @return Non-negative number of bytes actually written to the
+ *         device on success, negative error number otherwise.
+ *
  */
-ssize_t char_dev_write(int dev_phone, void *buf, size_t size)
+ssize_t char_dev_write(async_sess_t *sess, void *buf, size_t size)
 {
-	return char_dev_rw(dev_phone, buf, size, false);
+	return char_dev_rw(sess, buf, size, false);
 }
 
Index: uspace/lib/c/generic/device/hw_res.c
===================================================================
--- uspace/lib/c/generic/device/hw_res.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/device/hw_res.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,36 +38,48 @@
 #include <malloc.h>
 
-int hw_res_get_resource_list(int dev_phone, hw_resource_list_t *hw_resources)
+int hw_res_get_resource_list(async_sess_t *sess,
+    hw_resource_list_t *hw_resources)
 {
 	sysarg_t count = 0;
-
-	int rc = async_req_1_1(dev_phone, DEV_IFACE_ID(HW_RES_DEV_IFACE),
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
 	    HW_RES_GET_RESOURCE_LIST, &count);
-
-	hw_resources->count = count;
-	if (rc != EOK)
+	
+	if (rc != EOK) {
+		async_exchange_end(exch);
 		return rc;
+	}
 	
 	size_t size = count * sizeof(hw_resource_t);
-	hw_resources->resources = (hw_resource_t *)malloc(size);
-	if (!hw_resources->resources)
+	hw_resource_t *resources = (hw_resource_t *) malloc(size);
+	if (resources == NULL) {
+		// FIXME: This is protocol violation
+		async_exchange_end(exch);
 		return ENOMEM;
+	}
 	
-	rc = async_data_read_start(dev_phone, hw_resources->resources, size);
+	rc = async_data_read_start(exch, resources, size);
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
-		free(hw_resources->resources);
-		hw_resources->resources = NULL;
+		free(resources);
 		return rc;
 	}
+	
+	hw_resources->resources = resources;
+	hw_resources->count = count;
 	
 	return EOK;
 }
 
-bool hw_res_enable_interrupt(int dev_phone)
+bool hw_res_enable_interrupt(async_sess_t *sess)
 {
-	int rc = async_req_1_0(dev_phone, DEV_IFACE_ID(HW_RES_DEV_IFACE),
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
 	    HW_RES_ENABLE_INTERRUPT);
-
-	return rc == EOK;
+	async_exchange_end(exch);
+	
+	return (rc == EOK);
 }
 
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/devman.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2007 Josef Cejka
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
  * All rights reserved.
@@ -35,60 +35,143 @@
  */
 
+#include <adt/list.h>
 #include <str.h>
-#include <stdio.h>
 #include <ipc/services.h>
+#include <ns.h>
 #include <ipc/devman.h>
 #include <devman.h>
+#include <fibril_synch.h>
 #include <async.h>
-#include <fibril_synch.h>
 #include <errno.h>
 #include <malloc.h>
 #include <bool.h>
-#include <adt/list.h>
-
-static int devman_phone_driver = -1;
-static int devman_phone_client = -1;
-
-static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
-
-int devman_get_phone(devman_interface_t iface, unsigned int flags)
+
+static FIBRIL_MUTEX_INITIALIZE(devman_driver_block_mutex);
+static FIBRIL_MUTEX_INITIALIZE(devman_client_block_mutex);
+
+static FIBRIL_MUTEX_INITIALIZE(devman_driver_mutex);
+static FIBRIL_MUTEX_INITIALIZE(devman_client_mutex);
+
+static async_sess_t *devman_driver_block_sess = NULL;
+static async_sess_t *devman_client_block_sess = NULL;
+
+static async_sess_t *devman_driver_sess = NULL;
+static async_sess_t *devman_client_sess = NULL;
+
+static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
+    async_sess_t **dst)
+{
+	fibril_mutex_lock(mtx);
+	
+	if ((*dst == NULL) && (src != NULL))
+		*dst = src;
+	
+	fibril_mutex_unlock(mtx);
+}
+
+/** Start an async exchange on the devman session (blocking).
+ *
+ * @param iface Device manager interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *devman_exchange_begin_blocking(devman_interface_t iface)
 {
 	switch (iface) {
 	case DEVMAN_DRIVER:
-		fibril_mutex_lock(&devman_phone_mutex);
-		if (devman_phone_driver >= 0) {
-			fibril_mutex_unlock(&devman_phone_mutex);
-			return devman_phone_driver;
+		fibril_mutex_lock(&devman_driver_block_mutex);
+		
+		while (devman_driver_block_sess == NULL) {
+			clone_session(&devman_driver_mutex, devman_driver_sess,
+			    &devman_driver_block_sess);
+			
+			if (devman_driver_block_sess == NULL)
+				devman_driver_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
 		}
 		
-		if (flags & IPC_FLAG_BLOCKING)
-			devman_phone_driver = async_connect_me_to_blocking(
-			    PHONE_NS, SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
-		else
-			devman_phone_driver = async_connect_me_to(PHONE_NS,
-			    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
-		
-		fibril_mutex_unlock(&devman_phone_mutex);
-		return devman_phone_driver;
+		fibril_mutex_unlock(&devman_driver_block_mutex);
+		
+		clone_session(&devman_driver_mutex, devman_driver_block_sess,
+		    &devman_driver_sess);
+		
+		return async_exchange_begin(devman_driver_block_sess);
 	case DEVMAN_CLIENT:
-		fibril_mutex_lock(&devman_phone_mutex);
-		if (devman_phone_client >= 0) {
-			fibril_mutex_unlock(&devman_phone_mutex);
-			return devman_phone_client;
+		fibril_mutex_lock(&devman_client_block_mutex);
+		
+		while (devman_client_block_sess == NULL) {
+			clone_session(&devman_client_mutex, devman_client_sess,
+			    &devman_client_block_sess);
+			
+			if (devman_client_block_sess == NULL)
+				devman_client_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
 		}
 		
-		if (flags & IPC_FLAG_BLOCKING) {
-			devman_phone_client = async_connect_me_to_blocking(
-			    PHONE_NS, SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
-		} else {
-			devman_phone_client = async_connect_me_to(PHONE_NS,
-			    SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
-		}
-		
-		fibril_mutex_unlock(&devman_phone_mutex);
-		return devman_phone_client;
+		fibril_mutex_unlock(&devman_client_block_mutex);
+		
+		clone_session(&devman_client_mutex, devman_client_block_sess,
+		    &devman_client_sess);
+		
+		return async_exchange_begin(devman_client_block_sess);
 	default:
-		return -1;
-	}
+		return NULL;
+	}
+}
+
+/** Start an async exchange on the devman session.
+ *
+ * @param iface Device manager interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *devman_exchange_begin(devman_interface_t iface)
+{
+	switch (iface) {
+	case DEVMAN_DRIVER:
+		fibril_mutex_lock(&devman_driver_mutex);
+		
+		if (devman_driver_sess == NULL)
+			devman_driver_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
+			    DEVMAN_DRIVER, 0);
+		
+		fibril_mutex_unlock(&devman_driver_mutex);
+		
+		if (devman_driver_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(devman_driver_sess);
+	case DEVMAN_CLIENT:
+		fibril_mutex_lock(&devman_client_mutex);
+		
+		if (devman_client_sess == NULL)
+			devman_client_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
+			    DEVMAN_CLIENT, 0);
+		
+		fibril_mutex_unlock(&devman_client_mutex);
+		
+		if (devman_client_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(devman_client_sess);
+	default:
+		return NULL;
+	}
+}
+
+/** Finish an async exchange on the devman session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+void devman_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
 }
 
@@ -96,64 +179,25 @@
 int devman_driver_register(const char *name, async_client_conn_t conn)
 {
-	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
 	
 	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
+	aid_t req = async_send_2(exch, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	devman_exchange_end(exch);
+	
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
-		async_serialize_end();
-		return -1;
+		return retval;
 	}
 	
 	async_set_client_connection(conn);
 	
-	async_connect_to_me(phone, 0, 0, 0, NULL);
+	exch = devman_exchange_begin(DEVMAN_DRIVER);
+	async_connect_to_me(exch, 0, 0, 0, conn, NULL);
+	devman_exchange_end(exch);
+	
 	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
 	return retval;
-}
-
-static int devman_send_match_id(int phone, match_id_t *match_id)
-{
-	ipc_call_t answer;
-
-	aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
-	    &answer);
-	int retval = async_data_write_start(phone, match_id->id,
-	    str_size(match_id->id));
-
-	async_wait_for(req, NULL);
-	return retval;
-}
-
-
-static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
-{
-	link_t *link = match_ids->ids.next;
-	match_id_t *match_id = NULL;
-	int ret = EOK;
-
-	while (link != &match_ids->ids) {
-		match_id = list_get_instance(link, match_id_t, link); 
-		ret = devman_send_match_id(phone, match_id);
-		if (ret != EOK) {
-			printf("Driver failed to send match id, error %d\n",
-			    ret);
-			return ret;
-		}
-
-		link = link->next;
-	}
-
-	return ret;
 }
 
@@ -163,158 +207,171 @@
  * this driver task.
  *
- * @param name		Name of the new function
- * @param ftype		Function type, fun_inner or fun_exposed
- * @param match_ids	Match IDs (should be empty for fun_exposed)
- * @param devh		Devman handle of the device
- * @param funh		Place to store handle of the new function
- *
- * @return		EOK on success or negative error code.
+ * @param name      Name of the new function
+ * @param ftype     Function type, fun_inner or fun_exposed
+ * @param match_ids Match IDs (should be empty for fun_exposed)
+ * @param devh      Devman handle of the device
+ * @param funh      Place to store handle of the new function
+ *
+ * @return EOK on success or negative error code.
+ *
  */
 int devman_add_function(const char *name, fun_type_t ftype,
     match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
 {
-	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
-	int fun_handle;
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
 	int match_count = list_count(&match_ids->ids);
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
+	
 	ipc_call_t answer;
-
-	aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
+	aid_t req = async_send_3(exch, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
 	    devh, match_count, &answer);
-
-	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	if (retval != EOK) {
+		devman_exchange_end(exch);
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	match_id_t *match_id = NULL;
+	
+	list_foreach(match_ids->ids, link) {
+		match_id = list_get_instance(link, match_id_t, link);
+		
+		ipc_call_t answer2;
+		aid_t req2 = async_send_1(exch, DEVMAN_ADD_MATCH_ID,
+		    match_id->score, &answer2);
+		retval = async_data_write_start(exch, match_id->id,
+		    str_size(match_id->id));
+		if (retval != EOK) {
+			devman_exchange_end(exch);
+			async_wait_for(req2, NULL);
+			async_wait_for(req, NULL);
+			return retval;
+		}
+		
+		async_wait_for(req2, &retval);
+		if (retval != EOK) {
+			devman_exchange_end(exch);
+			async_wait_for(req, NULL);
+			return retval;
+		}
+	}
+	
+	devman_exchange_end(exch);
+	
+	async_wait_for(req, &retval);
+	if (retval == EOK) {
+		if (funh != NULL)
+			*funh = (int) IPC_GET_ARG1(answer);
+	} else {
+		if (funh != NULL)
+			*funh = -1;
+	}
+	
+	return retval;
+}
+
+int devman_add_device_to_category(devman_handle_t devman_handle,
+    const char *cat_name)
+{
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, DEVMAN_ADD_DEVICE_TO_CATEGORY,
+	    devman_handle, &answer);
+	sysarg_t retval = async_data_write_start(exch, cat_name,
+	    str_size(cat_name));
+	
+	devman_exchange_end(exch);
+	
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-	
-	devman_send_match_ids(phone, match_ids);
+		return retval;
+	}
 	
 	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
-	if (retval == EOK)
-		fun_handle = (int) IPC_GET_ARG1(answer);
+	return retval;
+}
+
+async_sess_t *devman_device_connect(exch_mgmt_t mgmt, devman_handle_t handle,
+    unsigned int flags)
+{
+	async_sess_t *sess;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
+			    DEVMAN_CONNECT_TO_DEVICE, handle);
 	else
-		fun_handle = -1;
-	
-	*funh = fun_handle;
-
-	return retval;
-}
-
-int devman_add_device_to_class(devman_handle_t devman_handle,
-    const char *class_name)
-{
-	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
+		sess = service_connect(mgmt, SERVICE_DEVMAN,
+			    DEVMAN_CONNECT_TO_DEVICE, handle);
+	
+	return sess;
+}
+
+/** Remove function from device.
+ *
+ * Request devman to remove function owned by this driver task.
+ * @param funh      Devman handle of the function
+ *
+ * @return EOK on success or negative error code.
+ */
+int devman_remove_function(devman_handle_t funh)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	
+	exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
+	retval = async_req_1_0(exch, DEVMAN_REMOVE_FUNCTION, (sysarg_t) funh);
+	devman_exchange_end(exch);
+	
+	return (int) retval;
+}
+
+async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt,
+    devman_handle_t handle, unsigned int flags)
+{
+	async_sess_t *sess;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
+			    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
+	else
+		sess = service_connect(mgmt, SERVICE_DEVMAN,
+			    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
+	
+	return sess;
+}
+
+int devman_fun_get_handle(const char *pathname, devman_handle_t *handle,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
+	else {
+		exch = devman_exchange_begin(DEVMAN_CLIENT);
+		if (exch == NULL)
+			return ENOMEM;
+	}
+	
 	ipc_call_t answer;
-	aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
-	    devman_handle, &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, class_name,
-	    str_size(class_name));
+	aid_t req = async_send_2(exch, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, pathname,
+	    str_size(pathname));
+	
+	devman_exchange_end(exch);
+	
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
-		async_serialize_end();
 		return retval;
 	}
 	
 	async_wait_for(req, &retval);
-	async_serialize_end();
-	
-	return retval;
-}
-
-void devman_hangup_phone(devman_interface_t iface)
-{
-	switch (iface) {
-	case DEVMAN_DRIVER:
-		if (devman_phone_driver >= 0) {
-			async_hangup(devman_phone_driver);
-			devman_phone_driver = -1;
-		}
-		break;
-	case DEVMAN_CLIENT:
-		if (devman_phone_client >= 0) {
-			async_hangup(devman_phone_client);
-			devman_phone_client = -1;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-int devman_device_connect(devman_handle_t handle, unsigned int flags)
-{
-	int phone;
-	
-	if (flags & IPC_FLAG_BLOCKING) {
-		phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
-		    DEVMAN_CONNECT_TO_DEVICE, handle);
-	} else {
-		phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
-		    DEVMAN_CONNECT_TO_DEVICE, handle);
-	}
-	
-	return phone;
-}
-
-int devman_parent_device_connect(devman_handle_t handle, unsigned int flags)
-{
-	int phone;
-	
-	if (flags & IPC_FLAG_BLOCKING) {
-		phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
-		    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
-	} else {
-		phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
-		    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
-	}
-	
-	return phone;
-}
-
-int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
-    unsigned int flags)
-{
-	int phone = devman_get_phone(DEVMAN_CLIENT, flags);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
-	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, pathname,
-	    str_size(pathname));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	async_serialize_end();
 	
 	if (retval != EOK) {
 		if (handle != NULL)
 			*handle = (devman_handle_t) -1;
+		
 		return retval;
 	}
@@ -326,4 +383,163 @@
 }
 
+static int devman_get_str_internal(sysarg_t method, sysarg_t arg1, char *buf,
+    size_t buf_size)
+{
+	async_exch_t *exch;
+	ipc_call_t dreply;
+	size_t act_size;
+	sysarg_t dretval;
+	
+	exch = devman_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	aid_t dreq = async_data_read(exch, buf, buf_size - 1, &dreply);
+	async_wait_for(dreq, &dretval);
+	
+	devman_exchange_end(exch);
+	
+	if (dretval != EOK) {
+		async_wait_for(req, NULL);
+		return dretval;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK)
+		return retval;
+	
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= buf_size - 1);
+	buf[act_size] = '\0';
+	
+	return EOK;
+}
+
+int devman_fun_get_path(devman_handle_t handle, char *buf, size_t buf_size)
+{
+	return devman_get_str_internal(DEVMAN_FUN_GET_PATH, handle, buf,
+	    buf_size);
+}
+
+int devman_fun_get_name(devman_handle_t handle, char *buf, size_t buf_size)
+{
+	return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, buf,
+	    buf_size);
+}
+
+static int devman_get_handles_once(sysarg_t method, sysarg_t arg1,
+    devman_handle_t *handle_buf, size_t buf_size, size_t *act_size)
+{
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	int rc = async_data_read_start(exch, handle_buf, buf_size);
+	
+	devman_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		return retval;
+	}
+	
+	*act_size = IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Get list of handles.
+ *
+ * Returns an allocated array of handles.
+ *
+ * @param method	IPC method
+ * @param arg1		IPC argument 1
+ * @param data		Place to store pointer to array of handles
+ * @param count		Place to store number of handles
+ * @return 		EOK on success or negative error code
+ */
+static int devman_get_handles_internal(sysarg_t method, sysarg_t arg1,
+    devman_handle_t **data, size_t *count)
+{
+	devman_handle_t *handles;
+	size_t act_size;
+	size_t alloc_size;
+	int rc;
+
+	*data = NULL;
+	act_size = 0;	/* silence warning */
+
+	rc = devman_get_handles_once(method, arg1, NULL, 0,
+	    &act_size);
+	if (rc != EOK)
+		return rc;
+
+	alloc_size = act_size;
+	handles = malloc(alloc_size);
+	if (handles == NULL)
+		return ENOMEM;
+
+	while (true) {
+		rc = devman_get_handles_once(method, arg1, handles, alloc_size,
+		    &act_size);
+		if (rc != EOK)
+			return rc;
+
+		if (act_size <= alloc_size)
+			break;
+
+		alloc_size *= 2;
+		free(handles);
+
+		handles = malloc(alloc_size);
+		if (handles == NULL)
+			return ENOMEM;
+	}
+
+	*count = act_size / sizeof(devman_handle_t);
+	*data = handles;
+	return EOK;
+}
+
+int devman_fun_get_child(devman_handle_t funh, devman_handle_t *devh)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_GET_CHILD,
+	    funh, devh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
+int devman_dev_get_functions(devman_handle_t devh, devman_handle_t **funcs,
+    size_t *count)
+{
+	return devman_get_handles_internal(DEVMAN_DEV_GET_FUNCTIONS,
+	    devh, funcs, count);
+}
+
+int devman_fun_sid_to_handle(service_id_t sid, devman_handle_t *handle)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_SID_TO_HANDLE,
+	    sid, handle);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
 
 /** @}
Index: pace/lib/c/generic/devmap.c
===================================================================
--- uspace/lib/c/generic/devmap.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,457 +1,0 @@
-/*
- * Copyright (c) 2007 Josef Cejka
- * 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.
- */
-
-#include <str.h>
-#include <ipc/services.h>
-#include <ipc/ns.h>
-#include <ipc/devmap.h>
-#include <devmap.h>
-#include <async.h>
-#include <errno.h>
-#include <malloc.h>
-#include <bool.h>
-
-static int devmap_phone_driver = -1;
-static int devmap_phone_client = -1;
-
-/** Get phone to device mapper task. */
-int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
-{
-	switch (iface) {
-	case DEVMAP_DRIVER:
-		if (devmap_phone_driver >= 0)
-			return devmap_phone_driver;
-		
-		if (flags & IPC_FLAG_BLOCKING)
-			devmap_phone_driver = service_connect_blocking(SERVICE_DEVMAP,
-			    DEVMAP_DRIVER, 0);
-		else
-			devmap_phone_driver = service_connect(SERVICE_DEVMAP,
-			    DEVMAP_DRIVER, 0);
-		
-		return devmap_phone_driver;
-	case DEVMAP_CLIENT:
-		if (devmap_phone_client >= 0)
-			return devmap_phone_client;
-		
-		if (flags & IPC_FLAG_BLOCKING)
-			devmap_phone_client = service_connect_blocking(SERVICE_DEVMAP,
-			    DEVMAP_CLIENT, 0);
-		else
-			devmap_phone_client = service_connect(SERVICE_DEVMAP,
-			    DEVMAP_CLIENT, 0);
-		
-		return devmap_phone_client;
-	default:
-		return -1;
-	}
-}
-
-void devmap_hangup_phone(devmap_interface_t iface)
-{
-	switch (iface) {
-	case DEVMAP_DRIVER:
-		if (devmap_phone_driver >= 0) {
-			async_hangup(devmap_phone_driver);
-			devmap_phone_driver = -1;
-		}
-		break;
-	case DEVMAP_CLIENT:
-		if (devmap_phone_client >= 0) {
-			async_hangup(devmap_phone_client);
-			devmap_phone_client = -1;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-/** Register new driver with devmap. */
-int devmap_driver_register(const char *name, async_client_conn_t conn)
-{
-	int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return -1;
-	}
-	
-	async_set_client_connection(conn);
-	
-	async_connect_to_me(phone, 0, 0, 0, NULL);
-	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
-	return retval;
-}
-
-/** Register new device.
- *
- * The @p interface is used when forwarding connection to the driver.
- * If not 0, the first argument is the interface and the second argument
- * is the devmap handle of the device.
- * When the interface is zero (default), the first argument is directly
- * the handle (to ensure backward compatibility).
- *
- * @param fqdn Fully qualified device name.
- * @param[out] handle Handle to the created instance of device.
- * @param interface Interface when forwarding.
- *
- */
-int devmap_device_register_with_iface(const char *fqdn,
-    devmap_handle_t *handle, sysarg_t interface)
-{
-	int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
-	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
-	if (retval != EOK) {
-		if (handle != NULL)
-			*handle = -1;
-		return retval;
-	}
-	
-	if (handle != NULL)
-		*handle = (devmap_handle_t) IPC_GET_ARG1(answer);
-	
-	return retval;
-}
-
-/** Register new device.
- *
- * @param fqdn      Fully qualified device name.
- * @param handle    Output: Handle to the created instance of device.
- *
- */
-int devmap_device_register(const char *fqdn, devmap_handle_t *handle)
-{
-	return devmap_device_register_with_iface(fqdn, handle, 0);
-}
-
-
-int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
-	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
-	if (retval != EOK) {
-		if (handle != NULL)
-			*handle = (devmap_handle_t) -1;
-		return retval;
-	}
-	
-	if (handle != NULL)
-		*handle = (devmap_handle_t) IPC_GET_ARG1(answer);
-	
-	return retval;
-}
-
-int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle, unsigned int flags)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
-	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
-	if (retval != EOK) {
-		if (handle != NULL)
-			*handle = (devmap_handle_t) -1;
-		return retval;
-	}
-	
-	if (handle != NULL)
-		*handle = (devmap_handle_t) IPC_GET_ARG1(answer);
-	
-	return retval;
-}
-
-devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	sysarg_t type;
-	int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
-	if (retval != EOK)
-		return DEV_HANDLE_NONE;
-	
-	return (devmap_handle_type_t) type;
-}
-
-int devmap_device_connect(devmap_handle_t handle, unsigned int flags)
-{
-	int phone;
-	
-	if (flags & IPC_FLAG_BLOCKING) {
-		phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
-		    DEVMAP_CONNECT_TO_DEVICE, handle);
-	} else {
-		phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
-		    DEVMAP_CONNECT_TO_DEVICE, handle);
-	}
-	
-	return phone;
-}
-
-int devmap_null_create(void)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return -1;
-	
-	sysarg_t null_id;
-	int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
-	if (retval != EOK)
-		return -1;
-	
-	return (int) null_id;
-}
-
-void devmap_null_destroy(int null_id)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return;
-	
-	async_req_1_0(phone, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
-}
-
-static size_t devmap_count_namespaces_internal(int phone)
-{
-	sysarg_t count;
-	int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
-	if (retval != EOK)
-		return 0;
-	
-	return count;
-}
-
-static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
-{
-	sysarg_t count;
-	int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
-	if (retval != EOK)
-		return 0;
-	
-	return count;
-}
-
-size_t devmap_count_namespaces(void)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return 0;
-	
-	return devmap_count_namespaces_internal(phone);
-}
-
-size_t devmap_count_devices(devmap_handle_t ns_handle)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return 0;
-	
-	return devmap_count_devices_internal(phone, ns_handle);
-}
-
-size_t devmap_get_namespaces(dev_desc_t **data)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return 0;
-	
-	/* Loop until namespaces read succesful */
-	while (true) {
-		size_t count = devmap_count_namespaces_internal(phone);
-		if (count == 0)
-			return 0;
-		
-		dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
-		if (devs == NULL)
-			return 0;
-		
-		async_serialize_start();
-		
-		ipc_call_t answer;
-		aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
-		
-		int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
-		if (rc == EOVERFLOW) {
-			/*
-			 * Number of namespaces has changed since
-			 * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
-			 */
-			async_serialize_end();
-			free(devs);
-			continue;
-		}
-		
-		if (rc != EOK) {
-			async_wait_for(req, NULL);
-			async_serialize_end();
-			free(devs);
-			return 0;
-		}
-		
-		sysarg_t retval;
-		async_wait_for(req, &retval);
-		async_serialize_end();
-		
-		if (retval != EOK)
-			return 0;
-		
-		*data = devs;
-		return count;
-	}
-}
-
-size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return 0;
-	
-	/* Loop until namespaces read succesful */
-	while (true) {
-		size_t count = devmap_count_devices_internal(phone, ns_handle);
-		if (count == 0)
-			return 0;
-		
-		dev_desc_t *devs = (dev_desc_t *) calloc(count, sizeof(dev_desc_t));
-		if (devs == NULL)
-			return 0;
-		
-		async_serialize_start();
-		
-		ipc_call_t answer;
-		aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
-		
-		int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
-		if (rc == EOVERFLOW) {
-			/*
-			 * Number of devices has changed since
-			 * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
-			 */
-			async_serialize_end();
-			free(devs);
-			continue;
-		}
-		
-		if (rc != EOK) {
-			async_wait_for(req, NULL);
-			async_serialize_end();
-			free(devs);
-			return 0;
-		}
-		
-		sysarg_t retval;
-		async_wait_for(req, &retval);
-		async_serialize_end();
-		
-		if (retval != EOK)
-			return 0;
-		
-		*data = devs;
-		return count;
-	}
-}
Index: uspace/lib/c/generic/dlfcn.c
===================================================================
--- uspace/lib/c/generic/dlfcn.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/dlfcn.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,90 @@
+/*
+ * 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 rtld rtld
+ * @brief
+ * @{
+ */ 
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#include <rtld/module.h>
+#include <rtld/symbol.h>
+
+void *dlopen(const char *path, int flag)
+{
+	module_t *m;
+
+	if (runtime_env == NULL) {
+		printf("Dynamic linker not set up -- initializing.\n");
+		rtld_init_static();
+	}
+
+	printf("dlopen(\"%s\", %d)\n", path, flag);
+
+	printf("module_find('%s')\n", path);
+	m = module_find(path);
+	if (m == NULL) {
+		printf("NULL. module_load('%s')\n", path);
+		m = module_load(path);
+		printf("module_load_deps(m)\n");
+		module_load_deps(m);
+		/* Now relocate. */
+		printf("module_process_relocs(m)\n");
+		module_process_relocs(m);
+	} else {
+		printf("not NULL\n");
+	}
+
+	return (void *) m;
+}
+
+/*
+ * @note Symbols with NULL values are not accounted for.
+ */
+void *dlsym(void *mod, const char *sym_name)
+{
+	elf_symbol_t *sd;
+	module_t *sm;
+
+	printf("dlsym(0x%lx, \"%s\")\n", (long)mod, sym_name);
+	sd = symbol_bfs_find(sym_name, (module_t *) mod, &sm);
+	if (sd != NULL) {
+		return symbol_get_addr(sd, sm);
+	}
+
+	return NULL;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/elf/elf_load.c
===================================================================
--- uspace/lib/c/generic/elf/elf_load.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/elf/elf_load.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * Copyright (c) 2006 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+
+/**
+ * @file
+ * @brief	Userspace ELF loader.
+ *
+ * This module allows loading ELF binaries (both executables and
+ * shared objects) from VFS. The current implementation allocates
+ * anonymous memory, fills it with segment data and then adjusts
+ * the memory areas' flags to the final value. In the future,
+ * the segments will be mapped directly from the file.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <align.h>
+#include <assert.h>
+#include <as.h>
+#include <elf/elf.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <smc.h>
+#include <loader/pcb.h>
+#include <entry_point.h>
+
+#include <elf/elf_load.h>
+
+#define DPRINTF(...)
+
+static const char *error_codes[] = {
+	"no error",
+	"invalid image",
+	"address space error",
+	"incompatible image",
+	"unsupported image type",
+	"irrecoverable error"
+};
+
+static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
+static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
+static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
+static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
+
+/** Load ELF binary from a file.
+ *
+ * Load an ELF binary from the specified file. If the file is
+ * an executable program, it is loaded unbiased. If it is a shared
+ * object, it is loaded with the bias @a so_bias. Some information
+ * extracted from the binary is stored in a elf_info_t structure
+ * pointed to by @a info.
+ *
+ * @param file_name Path to the ELF file.
+ * @param so_bias   Bias to use if the file is a shared object.
+ * @param info      Pointer to a structure for storing information
+ *                  extracted from the binary.
+ *
+ * @return EOK on success or negative error code.
+ *
+ */
+int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
+    elf_info_t *info)
+{
+	elf_ld_t elf;
+
+	int fd;
+	int rc;
+	
+	fd = open(file_name, O_RDONLY);
+	if (fd < 0) {
+		DPRINTF("failed opening file\n");
+		return -1;
+	}
+
+	elf.fd = fd;
+	elf.info = info;
+	elf.flags = flags;
+
+	rc = elf_load(&elf, so_bias);
+
+	close(fd);
+
+	return rc;
+}
+
+/** Create the program control block (PCB).
+ *
+ * Fills the program control block @a pcb with information from
+ * @a info.
+ *
+ * @param info	Program info structure
+ * @return EOK on success or negative error code
+ */
+void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
+{
+	pcb->entry = info->entry;
+	pcb->dynamic = info->dynamic;
+	pcb->rtld_runtime = NULL;
+}
+
+
+/** Load an ELF binary.
+ *
+ * The @a elf structure contains the loader state, including
+ * an open file, from which the binary will be loaded,
+ * a pointer to the @c info structure etc.
+ *
+ * @param elf		Pointer to loader state buffer.
+ * @param so_bias	Bias to use if the file is a shared object.
+ * @return EE_OK on success or EE_xx error code.
+ */
+static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
+{
+	elf_header_t header_buf;
+	elf_header_t *header = &header_buf;
+	int i, rc;
+
+	rc = read_all(elf->fd, header, sizeof(elf_header_t));
+	if (rc != sizeof(elf_header_t)) {
+		DPRINTF("Read error.\n"); 
+		return EE_INVALID;
+	}
+
+	elf->header = header;
+
+	/* Identify ELF */
+	if (header->e_ident[EI_MAG0] != ELFMAG0 ||
+	    header->e_ident[EI_MAG1] != ELFMAG1 || 
+	    header->e_ident[EI_MAG2] != ELFMAG2 ||
+	    header->e_ident[EI_MAG3] != ELFMAG3) {
+		DPRINTF("Invalid header.\n");
+		return EE_INVALID;
+	}
+	
+	/* Identify ELF compatibility */
+	if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
+	    header->e_machine != ELF_MACHINE || 
+	    header->e_ident[EI_VERSION] != EV_CURRENT ||
+	    header->e_version != EV_CURRENT ||
+	    header->e_ident[EI_CLASS] != ELF_CLASS) {
+		DPRINTF("Incompatible data/version/class.\n");
+		return EE_INCOMPATIBLE;
+	}
+
+	if (header->e_phentsize != sizeof(elf_segment_header_t)) {
+		DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
+		    sizeof(elf_segment_header_t));
+		return EE_INCOMPATIBLE;
+	}
+
+	if (header->e_shentsize != sizeof(elf_section_header_t)) {
+		DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
+		    sizeof(elf_section_header_t));
+		return EE_INCOMPATIBLE;
+	}
+
+	/* Check if the object type is supported. */
+	if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
+		DPRINTF("Object type %d is not supported\n", header->e_type);
+		return EE_UNSUPPORTED;
+	}
+
+	/* Shared objects can be loaded with a bias */
+	if (header->e_type == ET_DYN)
+		elf->bias = so_bias;
+	else
+		elf->bias = 0;
+
+	elf->info->interp = NULL;
+	elf->info->dynamic = NULL;
+
+	/* Walk through all segment headers and process them. */
+	for (i = 0; i < header->e_phnum; i++) {
+		elf_segment_header_t segment_hdr;
+
+		/* Seek to start of segment header */
+		lseek(elf->fd, header->e_phoff
+		        + i * sizeof(elf_segment_header_t), SEEK_SET);
+
+		rc = read_all(elf->fd, &segment_hdr,
+		    sizeof(elf_segment_header_t));
+		if (rc != sizeof(elf_segment_header_t)) {
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		rc = segment_header(elf, &segment_hdr);
+		if (rc != EE_OK)
+			return rc;
+	}
+
+	DPRINTF("Parse sections.\n");
+
+	/* Inspect all section headers and proccess them. */
+	for (i = 0; i < header->e_shnum; i++) {
+		elf_section_header_t section_hdr;
+
+		/* Seek to start of section header */
+		lseek(elf->fd, header->e_shoff
+		    + i * sizeof(elf_section_header_t), SEEK_SET);
+
+		rc = read_all(elf->fd, &section_hdr,
+		    sizeof(elf_section_header_t));
+		if (rc != sizeof(elf_section_header_t)) {
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		rc = section_header(elf, &section_hdr);
+		if (rc != EE_OK)
+			return rc;
+	}
+
+	elf->info->entry =
+	    (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
+
+	DPRINTF("Done.\n");
+
+	return EE_OK;
+}
+
+/** Print error message according to error code.
+ *
+ * @param rc Return code returned by elf_load().
+ *
+ * @return NULL terminated description of error.
+ */
+const char *elf_error(unsigned int rc)
+{
+	assert(rc < sizeof(error_codes) / sizeof(char *));
+
+	return error_codes[rc];
+}
+
+/** Process segment header.
+ *
+ * @param entry	Segment header.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
+{
+	switch (entry->p_type) {
+	case PT_NULL:
+	case PT_PHDR:
+	case PT_NOTE:
+		break;
+	case PT_LOAD:
+		return load_segment(elf, entry);
+		break;
+	case PT_INTERP:
+		/* Assume silently interp == "/app/dload" */
+		elf->info->interp = "/app/dload";
+		break;
+	case PT_DYNAMIC:
+		/* Record pointer to dynamic section into info structure */
+		elf->info->dynamic =
+		    (void *)((uint8_t *)entry->p_vaddr + elf->bias);
+		DPRINTF("dynamic section found at 0x%x\n",
+			(uintptr_t)elf->info->dynamic);
+		break;
+	case 0x70000000:
+		/* FIXME: MIPS reginfo */
+		break;
+	case PT_SHLIB:
+//	case PT_LOPROC:
+//	case PT_HIPROC:
+	default:
+		DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
+		return EE_UNSUPPORTED;
+		break;
+	}
+	return EE_OK;
+}
+
+/** Load segment described by program header entry.
+ *
+ * @param elf	Loader state.
+ * @param entry Program header entry describing segment to be loaded.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
+{
+	void *a;
+	int flags = 0;
+	uintptr_t bias;
+	uintptr_t base;
+	void *seg_ptr;
+	uintptr_t seg_addr;
+	size_t mem_sz;
+	ssize_t rc;
+
+	bias = elf->bias;
+
+	seg_addr = entry->p_vaddr + bias;
+	seg_ptr = (void *) seg_addr;
+
+	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
+		entry->p_memsz);
+
+	if (entry->p_align > 1) {
+		if ((entry->p_offset % entry->p_align) !=
+		    (seg_addr % entry->p_align)) {
+			DPRINTF("Align check 1 failed offset%%align=%d, "
+			    "vaddr%%align=%d\n",
+			    entry->p_offset % entry->p_align,
+			    seg_addr % entry->p_align
+			);
+			return EE_INVALID;
+		}
+	}
+
+	/* Final flags that will be set for the memory area */
+
+	if (entry->p_flags & PF_X)
+		flags |= AS_AREA_EXEC;
+	if (entry->p_flags & PF_W)
+		flags |= AS_AREA_WRITE;
+	if (entry->p_flags & PF_R)
+		flags |= AS_AREA_READ;
+	flags |= AS_AREA_CACHEABLE;
+	
+	base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
+	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
+
+	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
+	    (void *) (entry->p_vaddr + bias +
+	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
+
+	/*
+	 * For the course of loading, the area needs to be readable
+	 * and writeable.
+	 */
+	a = as_area_create((uint8_t *)base + bias, mem_sz,
+	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
+	if (a == (void *)(-1)) {
+		DPRINTF("memory mapping failed (0x%x, %d)\n",
+			base+bias, mem_sz);
+		return EE_MEMORY;
+	}
+
+	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
+	    (void *) (base + bias), mem_sz, flags, (void *) a);
+
+	/*
+	 * Load segment data
+	 */
+	rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
+	if (rc < 0) {
+		printf("seek error\n");
+		return EE_INVALID;
+	}
+
+/*	rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
+	if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
+
+	/* Long reads are not possible yet. Load segment piecewise. */
+
+	unsigned left, now;
+	uint8_t *dp;
+
+	left = entry->p_filesz;
+	dp = seg_ptr;
+
+	while (left > 0) {
+		now = 16384;
+		if (now > left) now = left;
+
+		rc = read_all(elf->fd, dp, now);
+
+		if (rc != (ssize_t) now) { 
+			DPRINTF("Read error.\n");
+			return EE_INVALID;
+		}
+
+		left -= now;
+		dp += now;
+	}
+
+	/*
+	 * The caller wants to modify the segments first. He will then
+	 * need to set the right access mode and ensure SMC coherence.
+	 */
+	if ((elf->flags & ELDF_RW) != 0) return EE_OK;
+
+//	printf("set area flags to %d\n", flags);
+	rc = as_area_change_flags(seg_ptr, flags);
+	if (rc != 0) {
+		DPRINTF("Failed to set memory area flags.\n");
+		return EE_MEMORY;
+	}
+
+	if (flags & AS_AREA_EXEC) {
+		/* Enforce SMC coherence for the segment */
+		if (smc_coherence(seg_ptr, entry->p_filesz))
+			return EE_MEMORY;
+	}
+
+	return EE_OK;
+}
+
+/** Process section header.
+ *
+ * @param elf	Loader state.
+ * @param entry Segment header.
+ *
+ * @return EE_OK on success, error code otherwise.
+ */
+static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
+{
+	switch (entry->sh_type) {
+	case SHT_PROGBITS:
+		if (entry->sh_flags & SHF_TLS) {
+			/* .tdata */
+		}
+		break;
+	case SHT_NOBITS:
+		if (entry->sh_flags & SHF_TLS) {
+			/* .tbss */
+		}
+		break;
+	case SHT_DYNAMIC:
+		/* Record pointer to dynamic section into info structure */
+		elf->info->dynamic =
+		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
+		DPRINTF("Dynamic section found at %p.\n",
+		    (void *) elf->info->dynamic);
+		break;
+	default:
+		break;
+	}
+	
+	return EE_OK;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/errno.c
===================================================================
--- uspace/lib/c/generic/errno.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/errno.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,5 +36,10 @@
 #include <fibril.h>
 
-int _errno;
+static fibril_local int fibril_errno;
+
+int *__errno(void)
+{
+	return &fibril_errno;
+}
 
 /** @}
Index: uspace/lib/c/generic/event.c
===================================================================
--- uspace/lib/c/generic/event.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/event.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,16 +39,40 @@
 #include <libc.h>
 #include <event.h>
-#include <kernel/ipc/event_types.h>
 
-/** Subscribe for event notifications.
+/** Subscribe event notifications.
  *
- * @param evno   Event number.
- * @param method Use this method for notifying me.
+ * @param evno    Event type to subscribe.
+ * @param imethod Use this interface and method for notifying me.
  *
  * @return Value returned by the kernel.
+ *
  */
-int event_subscribe(event_type_t e, sysarg_t method)
+int event_subscribe(event_type_t evno, sysarg_t imethod)
 {
-	return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) e, (sysarg_t) method);
+	return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
+	    (sysarg_t) imethod);
+}
+
+int event_task_subscribe(event_task_type_t evno, sysarg_t imethod)
+{
+	return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
+	    (sysarg_t) imethod);
+}
+
+/** Unmask event notifications.
+ *
+ * @param evno Event type to unmask.
+ *
+ * @return Value returned by the kernel.
+ *
+ */
+int event_unmask(event_type_t evno)
+{
+	return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
+}
+
+int event_task_unmask(event_task_type_t evno)
+{
+	return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
 }
 
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/fibril.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,5 +41,5 @@
 #include <unistd.h>
 #include <stdio.h>
-#include <arch/barrier.h>
+#include <libarch/barrier.h>
 #include <libarch/faddr.h>
 #include <futex.h>
@@ -222,5 +222,6 @@
 	fibril_t *dstf;
 	if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) {
-		dstf = list_get_instance(manager_list.next, fibril_t, link);
+		dstf = list_get_instance(list_first(&manager_list), fibril_t,
+		    link);
 		if (serialization_count && stype == FIBRIL_TO_MANAGER) {
 			serialized_threads++;
@@ -233,10 +234,10 @@
 	} else {
 		if (!list_empty(&serialized_list)) {
-			dstf = list_get_instance(serialized_list.next, fibril_t,
-			    link);
+			dstf = list_get_instance(list_first(&serialized_list),
+			    fibril_t, link);
 			serialized_threads--;
 		} else {
-			dstf = list_get_instance(ready_list.next, fibril_t,
-			    link);
+			dstf = list_get_instance(list_first(&ready_list),
+			    fibril_t, link);
 		}
 	}
@@ -326,5 +327,5 @@
 	
 	if (!list_empty(&manager_list))
-		list_remove(manager_list.next);
+		list_remove(list_first(&manager_list));
 	
 	futex_up(&fibril_futex);
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/fibril_synch.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,4 +43,5 @@
 #include <stacktrace.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include "private/async.h"
 
@@ -147,6 +148,6 @@
 		fibril_t *f;
 	
-		assert(!list_empty(&fm->waiters));
-		tmp = fm->waiters.next;
+		tmp = list_first(&fm->waiters);
+		assert(tmp != NULL);
 		wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
 		wdp->active = true;
@@ -278,5 +279,5 @@
 	
 	while (!list_empty(&frw->waiters)) {
-		link_t *tmp = frw->waiters.next;
+		link_t *tmp = list_first(&frw->waiters);
 		awaiter_t *wdp;
 		fibril_t *f;
@@ -421,5 +422,5 @@
 	futex_down(&async_futex);
 	while (!list_empty(&fcv->waiters)) {
-		tmp = fcv->waiters.next;
+		tmp = list_first(&fcv->waiters);
 		wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
 		list_remove(&wdp->wu_event.link);
Index: uspace/lib/c/generic/io/console.c
===================================================================
--- uspace/lib/c/generic/io/console.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/io/console.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,73 +37,200 @@
 #include <libc.h>
 #include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <vfs/vfs_sess.h>
 #include <io/console.h>
 #include <ipc/console.h>
 
-void console_clear(int phone)
-{
-	async_msg_0(phone, CONSOLE_CLEAR);
-}
-
-int console_get_size(int phone, sysarg_t *cols, sysarg_t *rows)
-{
-	return async_req_0_2(phone, CONSOLE_GET_SIZE, cols, rows);
-}
-
-void console_set_style(int phone, uint8_t style)
-{
-	async_msg_1(phone, CONSOLE_SET_STYLE, style);
-}
-
-void console_set_color(int phone, uint8_t fg_color, uint8_t bg_color,
+console_ctrl_t *console_init(FILE *ifile, FILE *ofile)
+{
+	console_ctrl_t *ctrl = malloc(sizeof(console_ctrl_t));
+	if (!ctrl)
+		return NULL;
+	
+	ctrl->input_sess = fsession(EXCHANGE_SERIALIZE, ifile);
+	if (!ctrl->input_sess) {
+		free(ctrl);
+		return NULL;
+	}
+	
+	ctrl->output_sess = fsession(EXCHANGE_SERIALIZE, ofile);
+	if (!ctrl->output_sess) {
+		free(ctrl);
+		return NULL;
+	}
+	
+	ctrl->input = ifile;
+	ctrl->output = ofile;
+	ctrl->input_aid = 0;
+	
+	return ctrl;
+}
+
+void console_done(console_ctrl_t *ctrl)
+{
+	free(ctrl);
+}
+
+bool console_kcon(void)
+{
+	return __SYSCALL0(SYS_DEBUG_ACTIVATE_CONSOLE);
+}
+
+void console_flush(console_ctrl_t *ctrl)
+{
+	fflush(ctrl->output);
+}
+
+void console_clear(console_ctrl_t *ctrl)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_0(exch, CONSOLE_CLEAR);
+	async_exchange_end(exch);
+}
+
+int console_get_size(console_ctrl_t *ctrl, sysarg_t *cols, sysarg_t *rows)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	int rc = async_req_0_2(exch, CONSOLE_GET_SIZE, cols, rows);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+void console_set_style(console_ctrl_t *ctrl, uint8_t style)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_1(exch, CONSOLE_SET_STYLE, style);
+	async_exchange_end(exch);
+}
+
+void console_set_color(console_ctrl_t *ctrl, uint8_t fg_color, uint8_t bg_color,
     uint8_t flags)
 {
-	async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
-}
-
-void console_set_rgb_color(int phone, uint32_t fg_color, uint32_t bg_color)
-{
-	async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
-}
-
-void console_cursor_visibility(int phone, bool show)
-{
-	async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, (show != false));
-}
-
-int console_get_color_cap(int phone, sysarg_t *ccap)
-{
-	return async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, ccap);
-}
-
-void console_kcon_enable(int phone)
-{
-	async_msg_0(phone, CONSOLE_KCON_ENABLE);
-}
-
-int console_get_pos(int phone, sysarg_t *col, sysarg_t *row)
-{
-	return async_req_0_2(phone, CONSOLE_GET_POS, col, row);
-}
-
-void console_set_pos(int phone, sysarg_t col, sysarg_t row)
-{
-	async_msg_2(phone, CONSOLE_GOTO, col, row);
-}
-
-bool console_get_event(int phone, console_event_t *event)
-{
-	sysarg_t type;
-	sysarg_t key;
-	sysarg_t mods;
-	sysarg_t c;
-	
-	int rc = async_req_0_4(phone, CONSOLE_GET_EVENT, &type, &key, &mods, &c);
-	if (rc < 0)
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_3(exch, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
+	async_exchange_end(exch);
+}
+
+void console_set_rgb_color(console_ctrl_t *ctrl, uint32_t fg_color,
+    uint32_t bg_color)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_2(exch, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
+	async_exchange_end(exch);
+}
+
+void console_cursor_visibility(console_ctrl_t *ctrl, bool show)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_1(exch, CONSOLE_CURSOR_VISIBILITY, (show != false));
+	async_exchange_end(exch);
+}
+
+int console_get_color_cap(console_ctrl_t *ctrl, sysarg_t *ccap)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	int rc = async_req_0_1(exch, CONSOLE_GET_COLOR_CAP, ccap);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+int console_get_pos(console_ctrl_t *ctrl, sysarg_t *col, sysarg_t *row)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	int rc = async_req_0_2(exch, CONSOLE_GET_POS, col, row);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+void console_set_pos(console_ctrl_t *ctrl, sysarg_t col, sysarg_t row)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_2(exch, CONSOLE_GOTO, col, row);
+	async_exchange_end(exch);
+}
+
+bool console_get_kbd_event(console_ctrl_t *ctrl, kbd_event_t *event)
+{
+	if (ctrl->input_aid == 0) {
+		sysarg_t type;
+		sysarg_t key;
+		sysarg_t mods;
+		sysarg_t c;
+		
+		async_exch_t *exch = async_exchange_begin(ctrl->input_sess);
+		int rc = async_req_0_4(exch, CONSOLE_GET_EVENT, &type, &key, &mods, &c);
+		async_exchange_end(exch);
+		
+		if (rc != EOK) {
+			errno = rc;
+			return false;
+		}
+		
+		event->type = type;
+		event->key = key;
+		event->mods = mods;
+		event->c = c;
+	} else {
+		sysarg_t retval;
+		async_wait_for(ctrl->input_aid, &retval);
+		
+		ctrl->input_aid = 0;
+		
+		if (retval != EOK) {
+			errno = (int) retval;
+			return false;
+		}
+		
+		event->type = IPC_GET_ARG1(ctrl->input_call);
+		event->key = IPC_GET_ARG2(ctrl->input_call);
+		event->mods = IPC_GET_ARG3(ctrl->input_call);
+		event->c = IPC_GET_ARG4(ctrl->input_call);
+	}
+	
+	return true;
+}
+
+bool console_get_kbd_event_timeout(console_ctrl_t *ctrl, kbd_event_t *event,
+    suseconds_t *timeout)
+{
+	struct timeval t0;
+	gettimeofday(&t0, NULL);
+	
+	if (ctrl->input_aid == 0) {
+		async_exch_t *exch = async_exchange_begin(ctrl->input_sess);
+		ctrl->input_aid = async_send_0(exch, CONSOLE_GET_EVENT,
+		    &ctrl->input_call);
+		async_exchange_end(exch);
+	}
+	
+	sysarg_t retval;
+	int rc = async_wait_timeout(ctrl->input_aid, &retval, *timeout);
+	if (rc != EOK) {
+		*timeout = 0;
+		errno = rc;
 		return false;
-	
-	event->type = type;
-	event->key = key;
-	event->mods = mods;
-	event->c = c;
+	}
+	
+	ctrl->input_aid = 0;
+	
+	if (retval != EOK) {
+		errno = (int) retval;
+		return false;
+	}
+	
+	event->type = IPC_GET_ARG1(ctrl->input_call);
+	event->key = IPC_GET_ARG2(ctrl->input_call);
+	event->mods = IPC_GET_ARG3(ctrl->input_call);
+	event->c = IPC_GET_ARG4(ctrl->input_call);
+	
+	/* Update timeout */
+	struct timeval t1;
+	gettimeofday(&t1, NULL);
+	*timeout -= tv_sub(&t1, &t0);
 	
 	return true;
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/io/io.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,7 +44,9 @@
 #include <io/klog.h>
 #include <vfs/vfs.h>
-#include <ipc/devmap.h>
+#include <vfs/vfs_sess.h>
+#include <ipc/loc.h>
 #include <adt/list.h>
 #include "../private/io.h"
+#include "../private/stdio.h"
 
 static void _ffillbuf(FILE *stream);
@@ -56,5 +58,5 @@
 	.eof = true,
 	.klog = false,
-	.phone = -1,
+	.sess = NULL,
 	.btype = _IONBF,
 	.buf = NULL,
@@ -70,5 +72,5 @@
 	.eof = false,
 	.klog = true,
-	.phone = -1,
+	.sess = NULL,
 	.btype = _IOLBF,
 	.buf = NULL,
@@ -84,5 +86,5 @@
 	.eof = false,
 	.klog = true,
-	.phone = -1,
+	.sess = NULL,
 	.btype = _IONBF,
 	.buf = NULL,
@@ -99,8 +101,8 @@
 static LIST_INITIALIZE(files);
 
-void __stdio_init(int filc, fdi_node_t *filv[])
+void __stdio_init(int filc)
 {
 	if (filc > 0) {
-		stdin = fopen_node(filv[0], "r");
+		stdin = fdopen(0, "r");
 	} else {
 		stdin = &stdin_null;
@@ -109,5 +111,5 @@
 	
 	if (filc > 1) {
-		stdout = fopen_node(filv[1], "w");
+		stdout = fdopen(1, "w");
 	} else {
 		stdout = &stdout_klog;
@@ -116,5 +118,5 @@
 	
 	if (filc > 2) {
-		stderr = fopen_node(filv[2], "w");
+		stderr = fdopen(2, "w");
 	} else {
 		stderr = &stderr_klog;
@@ -125,10 +127,7 @@
 void __stdio_done(void)
 {
-	link_t *link = files.next;
-	
-	while (link != &files) {
-		FILE *file = list_get_instance(link, FILE, link);
+	while (!list_empty(&files)) {
+		FILE *file = list_get_instance(list_first(&files), FILE, link);
 		fclose(file);
-		link = files.next;
 	}
 }
@@ -173,4 +172,5 @@
 		}
 		*flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
+		break;
 	default:
 		errno = EINVAL;
@@ -254,5 +254,5 @@
 	stream->eof = false;
 	stream->klog = false;
-	stream->phone = -1;
+	stream->sess = NULL;
 	stream->need_sync = false;
 	_setvbuf(stream);
@@ -276,5 +276,5 @@
 	stream->eof = false;
 	stream->klog = false;
-	stream->phone = -1;
+	stream->sess = NULL;
 	stream->need_sync = false;
 	_setvbuf(stream);
@@ -285,36 +285,4 @@
 }
 
-FILE *fopen_node(fdi_node_t *node, const char *mode)
-{
-	int flags;
-	if (!parse_mode(mode, &flags))
-		return NULL;
-	
-	/* Open file. */
-	FILE *stream = malloc(sizeof(FILE));
-	if (stream == NULL) {
-		errno = ENOMEM;
-		return NULL;
-	}
-	
-	stream->fd = open_node(node, flags);
-	if (stream->fd < 0) {
-		/* errno was set by open_node() */
-		free(stream);
-		return NULL;
-	}
-	
-	stream->error = false;
-	stream->eof = false;
-	stream->klog = false;
-	stream->phone = -1;
-	stream->need_sync = false;
-	_setvbuf(stream);
-	
-	list_append(&stream->link, &files);
-	
-	return stream;
-}
-
 int fclose(FILE *stream)
 {
@@ -323,6 +291,6 @@
 	fflush(stream);
 	
-	if (stream->phone >= 0)
-		async_hangup(stream->phone);
+	if (stream->sess != NULL)
+		async_hangup(stream->sess);
 	
 	if (stream->fd >= 0)
@@ -594,9 +562,10 @@
 		}
 		
-		buf += now;
+		data += now;
 		stream->buf_head += now;
 		buf_free -= now;
 		bytes_left -= now;
 		total_written += now;
+		stream->buf_state = _bs_write;
 		
 		if (buf_free == 0) {
@@ -606,7 +575,4 @@
 		}
 	}
-	
-	if (total_written > 0)
-		stream->buf_state = _bs_write;
 
 	if (need_flush)
@@ -714,4 +680,5 @@
 off64_t ftell(FILE *stream)
 {
+	_fflushbuf(stream);
 	return lseek(stream->fd, 0, SEEK_CUR);
 }
@@ -731,5 +698,5 @@
 	}
 	
-	if (stream->fd >= 0 && stream->need_sync) {
+	if ((stream->fd >= 0) && (stream->need_sync)) {
 		/**
 		 * Better than syncing always, but probably still not the
@@ -769,20 +736,22 @@
 }
 
-int fphone(FILE *stream)
+async_sess_t *fsession(exch_mgmt_t mgmt, FILE *stream)
 {
 	if (stream->fd >= 0) {
-		if (stream->phone < 0)
-			stream->phone = fd_phone(stream->fd);
-		
-		return stream->phone;
-	}
-	
-	return -1;
-}
-
-int fnode(FILE *stream, fdi_node_t *node)
-{
-	if (stream->fd >= 0)
-		return fd_node(stream->fd, node);
+		if (stream->sess == NULL)
+			stream->sess = fd_session(mgmt, stream->fd);
+		
+		return stream->sess;
+	}
+	
+	return NULL;
+}
+
+int fhandle(FILE *stream, int *handle)
+{
+	if (stream->fd >= 0) {
+		*handle = stream->fd;
+		return EOK;
+	}
 	
 	return ENOENT;
Index: uspace/lib/c/generic/io/klog.c
===================================================================
--- uspace/lib/c/generic/io/klog.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/io/klog.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,7 @@
 #include <sys/types.h>
 #include <unistd.h>
+#include <errno.h>
 #include <io/klog.h>
+#include <io/printf_core.h>
 
 size_t klog_write(const void *buf, size_t size)
@@ -55,4 +57,67 @@
 }
 
+/** Print formatted text to klog.
+ *
+ * @param fmt Format string
+ *
+ * \see For more details about format string see printf_core.
+ *
+ */
+int klog_printf(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	
+	int ret = klog_vprintf(fmt, args);
+	
+	va_end(args);
+	
+	return ret;
+}
+
+static int klog_vprintf_str_write(const char *str, size_t size, void *data)
+{
+	size_t wr = klog_write(str, size);
+	return str_nlength(str, wr);
+}
+
+static int klog_vprintf_wstr_write(const wchar_t *str, size_t size, void *data)
+{
+	size_t offset = 0;
+	size_t chars = 0;
+	
+	while (offset < size) {
+		char buf[STR_BOUNDS(1)];
+		size_t sz = 0;
+		
+		if (chr_encode(str[chars], buf, &sz, STR_BOUNDS(1)) == EOK)
+			klog_write(buf, sz);
+		
+		chars++;
+		offset += sizeof(wchar_t);
+	}
+	
+	return chars;
+}
+
+/** Print formatted text to klog.
+ *
+ * @param fmt Format string
+ * @param ap  Format parameters
+ *
+ * \see For more details about format string see printf_core.
+ *
+ */
+int klog_vprintf(const char *fmt, va_list ap)
+{
+	printf_spec_t ps = {
+		klog_vprintf_str_write,
+		klog_vprintf_wstr_write,
+		NULL
+	};
+	
+	return printf_core(fmt, &ps, ap);
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/io/log.c
===================================================================
--- uspace/lib/c/generic/io/log.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/io/log.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <io/log.h>
+
+/** Serialization mutex for logging functions. */
+static FIBRIL_MUTEX_INITIALIZE(log_serializer);
+
+/** Current log level. */
+static log_level_t log_level;
+
+static FILE *log_stream;
+
+static const char *log_prog_name;
+
+/** Prefixes for individual logging levels. */
+static const char *log_level_names[] = {
+	[LVL_FATAL] = "Fatal error",
+	[LVL_ERROR] = "Error",
+	[LVL_WARN] = "Warning",
+	[LVL_NOTE] = "Note",
+	[LVL_DEBUG] = "Debug",
+	[LVL_DEBUG2] = "Debug2"
+};
+
+/** Initialize the logging system.
+ *
+ * @param prog_name	Program name, will be printed as part of message
+ * @param level		Minimum message level to print
+ */
+int log_init(const char *prog_name, log_level_t level)
+{
+	assert(level < LVL_LIMIT);
+	log_level = level;
+
+	log_stream = stdout;
+	log_prog_name = str_dup(prog_name);
+	if (log_prog_name == NULL)
+		return ENOMEM;
+
+	return EOK;
+}
+
+/** Write an entry to the log.
+ *
+ * @param level		Message verbosity level. Message is only printed
+ *			if verbosity is less than or equal to current
+ *			reporting level.
+ * @param fmt		Format string (no traling newline).
+ */
+void log_msg(log_level_t level, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	log_msgv(level, fmt, args);
+	va_end(args);
+}
+
+/** Write an entry to the log (va_list variant).
+ *
+ * @param level		Message verbosity level. Message is only printed
+ *			if verbosity is less than or equal to current
+ *			reporting level.
+ * @param fmt		Format string (no trailing newline)
+ */
+void log_msgv(log_level_t level, const char *fmt, va_list args)
+{
+	assert(level < LVL_LIMIT);
+
+	/* Higher number means higher verbosity. */
+	if (level <= log_level) {
+		fibril_mutex_lock(&log_serializer);
+
+		fprintf(log_stream, "%s: %s: ", log_prog_name,
+		    log_level_names[level]);
+		vfprintf(log_stream, fmt, args);
+		fputc('\n', log_stream);
+		fflush(log_stream);
+
+		fibril_mutex_unlock(&log_serializer);
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/printf_core.c
===================================================================
--- uspace/lib/c/generic/io/printf_core.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/io/printf_core.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -206,5 +206,5 @@
 	}
 	
-	return (int) (counter + 1);
+	return (int) (counter);
 }
 
@@ -244,5 +244,5 @@
 	}
 	
-	return (int) (counter + 1);
+	return (int) (counter);
 }
 
Index: uspace/lib/c/generic/io/vprintf.c
===================================================================
--- uspace/lib/c/generic/io/vprintf.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/io/vprintf.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -96,7 +96,6 @@
 /** Print formatted text to stdout.
  *
- * @param file Output stream
- * @param fmt  Format string
- * @param ap   Format parameters
+ * @param fmt Format string
+ * @param ap  Format parameters
  *
  * \see For more details about format string see printf_core.
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/ipc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -47,4 +47,5 @@
 #include <futex.h>
 #include <fibril.h>
+#include <macros.h>
 
 /**
@@ -458,5 +459,5 @@
 	while (!list_empty(&queued_calls)) {
 		async_call_t *call =
-		    list_get_instance(queued_calls.next, async_call_t, list);
+		    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);
@@ -511,5 +512,5 @@
 	
 	link_t *item;
-	for (item = dispatched_calls.next; item != &dispatched_calls;
+	for (item = dispatched_calls.head.next; item != &dispatched_calls.head;
 	    item = item->next) {
 		async_call_t *call =
@@ -611,5 +612,5 @@
 /** Request callback connection.
  *
- * The @a taskhash and @a phonehash identifiers returned
+ * The @a task_id and @a phonehash identifiers returned
  * by the kernel can be used for connection tracking.
  *
@@ -618,5 +619,5 @@
  * @param arg2      User defined argument.
  * @param arg3      User defined argument.
- * @param taskhash  Opaque identifier of the client task.
+ * @param task_id   Identifier of the client task.
  * @param phonehash Opaque identifier of the phone that will
  *                  be used for incoming calls.
@@ -626,8 +627,32 @@
  */
 int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
-    sysarg_t *taskhash, sysarg_t *phonehash)
-{
-	return ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2,
-	    arg3, NULL, NULL, NULL, taskhash, phonehash);
+    task_id_t *task_id, sysarg_t *phonehash)
+{
+	ipc_call_t data;
+	int rc = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid,
+	    IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, (sysarg_t) &data);
+	if (rc == EOK) {
+		*task_id = data.in_task_id;
+		*phonehash = IPC_GET_ARG5(data);
+	}	
+	return rc;
+}
+
+/** Request cloned connection.
+ *
+ * @param phoneid Phone handle used for contacting the other side.
+ *
+ * @return Cloned phone handle on success or a negative error code.
+ *
+ */
+int ipc_connect_me(int phoneid)
+{
+	sysarg_t newphid;
+	int res = ipc_call_sync_0_5(phoneid, IPC_M_CONNECT_ME, NULL, NULL,
+	    NULL, NULL, &newphid);
+	if (res)
+		return res;
+	
+	return newphid;
 }
 
Index: pace/lib/c/generic/ipc/ns.c
===================================================================
--- uspace/lib/c/generic/ipc/ns.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2011 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.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#include <async.h>
-#include <ipc/ns.h>
-
-int service_register(sysarg_t service)
-{
-	return async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
-}
-
-int service_connect(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
-{
-	return async_connect_me_to(PHONE_NS, service, arg2, arg3);
-}
-
-int service_connect_blocking(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
-{
-	return async_connect_me_to_blocking(PHONE_NS, service, arg2, arg3);
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/l18n/langs.c
===================================================================
--- uspace/lib/c/generic/l18n/langs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/l18n/langs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011 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 libc
+ * @{
+ */
+/** @file
+ * Language and locale ids.
+ */
+
+#include <l18n/langs.h>
+#include <stdio.h>
+#include <fibril.h>
+
+#define UNKNOWN_LOCALE_LEN 64
+
+static fibril_local char unknown_locale[UNKNOWN_LOCALE_LEN];
+
+/** Get string representation of a given locale.
+ *
+ * @param locale The locale.
+ * @return Name of the locale.
+ */
+const char *str_l18_win_locale(l18_win_locales_t locale)
+{
+	/*
+	 * Static array with names might be better but it would be
+	 * way too big.
+	 */
+	switch (locale) {
+		case L18N_WIN_LOCALE_AFRIKAANS:
+			return "Afrikaans";
+		case L18N_WIN_LOCALE_CZECH:
+			return "Czech";
+		case L18N_WIN_LOCALE_ENGLISH_UNITED_STATES:
+			return "English (US)";
+		case L18N_WIN_LOCALE_SLOVAK:
+			return "Slovak";
+		case L18N_WIN_LOCALE_SPANISH_TRADITIONAL:
+			return "Spanish (traditional)";
+		case L18N_WIN_LOCALE_ZULU:
+			return "Zulu";
+	}
+
+	snprintf(unknown_locale, UNKNOWN_LOCALE_LEN, "Unknown locale 0x%04d",
+	    (int) locale);
+	return unknown_locale;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/libc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -49,7 +49,10 @@
 #include "private/libc.h"
 #include "private/async.h"
-#include "private/async_sess.h"
 #include "private/malloc.h"
 #include "private/io.h"
+
+#ifdef CONFIG_RTLD
+#include <rtld/rtld.h>
+#endif
 
 static bool env_setup = false;
@@ -60,5 +63,4 @@
 	__malloc_init();
 	__async_init();
-	__async_sess_init();
 	
 	fibril_t *fibril = fibril_setup();
@@ -77,4 +79,9 @@
 	char **argv;
 	
+#ifdef __IN_SHARED_LIBC__
+	if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
+		runtime_env = (runtime_env_t *) __pcb->rtld_runtime;
+	}
+#endif
 	/*
 	 * Get command line arguments and initialize
@@ -84,9 +91,9 @@
 		argc = 0;
 		argv = NULL;
-		__stdio_init(0, NULL);
+		__stdio_init(0);
 	} else {
 		argc = __pcb->argc;
 		argv = __pcb->argv;
-		__stdio_init(__pcb->filc, __pcb->filv);
+		__stdio_init(__pcb->filc);
 		(void) chdir(__pcb->cwd);
 	}
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/loader.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,5 @@
 #include <ipc/loader.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <libc.h>
 #include <task.h>
@@ -44,4 +44,5 @@
 #include <vfs/vfs.h>
 #include <loader/loader.h>
+#include "private/loader.h"
 
 /** Connect to a new program loader.
@@ -63,13 +64,16 @@
 loader_t *loader_connect(void)
 {
-	int phone_id = service_connect_blocking(SERVICE_LOAD, 0, 0);
-	if (phone_id < 0)
-		return NULL;
-	
 	loader_t *ldr = malloc(sizeof(loader_t));
 	if (ldr == NULL)
 		return NULL;
 	
-	ldr->phone_id = phone_id;
+	async_sess_t *sess =
+	    service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOAD, 0, 0);
+	if (sess == NULL) {
+		free(ldr);
+		return NULL;
+	}
+	
+	ldr->sess = sess;
 	return ldr;
 }
@@ -88,15 +92,19 @@
 {
 	/* Get task ID. */
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
-	int rc = async_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	return (int) retval;
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_GET_TASKID, &answer);
+	sysarg_t rc = async_data_read_start(exch, task_id, sizeof(task_id_t));
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -112,26 +120,29 @@
 int loader_set_cwd(loader_t *ldr)
 {
-	char *cwd;
-	size_t len;
-
-	cwd = (char *) malloc(MAX_PATH_LEN + 1);
+	char *cwd = (char *) malloc(MAX_PATH_LEN + 1);
 	if (!cwd)
 		return ENOMEM;
+	
 	if (!getcwd(cwd, MAX_PATH_LEN + 1))
-		str_cpy(cwd, MAX_PATH_LEN + 1, "/"); 
-	len = str_length(cwd);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_SET_CWD, &answer);
-	int rc = async_data_write_start(ldr->phone_id, cwd, len);
+		str_cpy(cwd, MAX_PATH_LEN + 1, "/");
+	
+	size_t len = str_length(cwd);
+	
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_SET_CWD, &answer);
+	sysarg_t rc = async_data_write_start(exch, cwd, len);
+	
+	async_exchange_end(exch);
 	free(cwd);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	return (int) retval;
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -153,21 +164,23 @@
 	char *pa = absolutize(path, &pa_len);
 	if (!pa)
-		return 0;
+		return ENOMEM;
 	
 	/* Send program pathname */
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
-	int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
-	if (rc != EOK) {
-		free(pa);
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_SET_PATHNAME, &answer);
+	sysarg_t rc = async_data_write_start(exch, (void *) pa, pa_len);
+	
+	async_exchange_end(exch);
 	free(pa);
 	
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	return (int) retval;
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -212,20 +225,21 @@
 	
 	/* Send serialized arguments to the loader */
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
-	sysarg_t rc = async_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
-	async_wait_for(req, &rc);
-	if (rc != EOK)
-		return rc;
-	
-	/* Free temporary buffer */
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_SET_ARGS, &answer);
+	sysarg_t rc = async_data_write_start(exch, (void *) arg_buf,
+	    buffer_size);
+	
+	async_exchange_end(exch);
 	free(arg_buf);
 	
-	return EOK;
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -242,45 +256,35 @@
  *
  */
-int loader_set_files(loader_t *ldr, fdi_node_t *const files[])
-{
-	/*
-	 * Serialize the arguments into a single array. First
-	 * compute size of the buffer needed.
-	 */
-	fdi_node_t *const *ap = files;
-	size_t count = 0;
-	while (*ap != NULL) {
-		count++;
-		ap++;
-	}
-	
-	fdi_node_t *files_buf;
-	files_buf = (fdi_node_t *) malloc(count * sizeof(fdi_node_t));
-	if (files_buf == NULL)
-		return ENOMEM;
-	
-	/* Fill the buffer */
-	size_t i;
-	for (i = 0; i < count; i++)
-		files_buf[i] = *files[i];
-	
+int loader_set_files(loader_t *ldr, int * const files[])
+{
 	/* Send serialized files to the loader */
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
-	sysarg_t rc = async_data_write_start(ldr->phone_id, (void *) files_buf,
-	    count * sizeof(fdi_node_t));
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
-	async_wait_for(req, &rc);
-	if (rc != EOK)
-		return rc;
-	
-	/* Free temporary buffer */
-	free(files_buf);
-	
-	return EOK;
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	async_exch_t *vfs_exch = vfs_exchange_begin();
+	
+	int i;
+	for (i = 0; files[i]; i++);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, LOADER_SET_FILES, i, &answer);
+
+	sysarg_t rc = EOK;
+	
+	for (i = 0; files[i]; i++) {
+		rc = async_state_change_start(exch, VFS_PASS_HANDLE, *files[i],
+		    0, vfs_exch); 
+		if (rc != EOK)
+			break;
+	}
+	
+	vfs_exchange_end(vfs_exch);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -297,5 +301,9 @@
 int loader_load_program(loader_t *ldr)
 {
-	return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD);
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	int rc = async_req_0_0(exch, LOADER_LOAD);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
@@ -306,6 +314,6 @@
  * the task and its thread is stopped.
  *
- * After using this function, no further operations must be performed
- * on the loader structure. It should be de-allocated using free().
+ * After using this function, no further operations can be performed
+ * on the loader structure and it is deallocated.
  *
  * @param ldr Loader connection structure.
@@ -316,10 +324,14 @@
 int loader_run(loader_t *ldr)
 {
-	int rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	int rc = async_req_0_0(exch, LOADER_RUN);
+	async_exchange_end(exch);
+	
 	if (rc != EOK)
 		return rc;
 	
-	async_hangup(ldr->phone_id);
-	ldr->phone_id = 0;
+	async_hangup(ldr->sess);
+	free(ldr);
+	
 	return EOK;
 }
@@ -327,7 +339,7 @@
 /** Cancel the loader session.
  *
- * Tells the loader not to load any program and terminate.
- * After using this function, no further operations must be performed
- * on the loader structure. It should be de-allocated using free().
+ * Tell the loader not to load any program and terminate.
+ * After using this function, no further operations can be performed
+ * on the loader structure and it is deallocated.
  *
  * @param ldr Loader connection structure.
@@ -338,6 +350,6 @@
 void loader_abort(loader_t *ldr)
 {
-	async_hangup(ldr->phone_id);
-	ldr->phone_id = 0;
+	async_hangup(ldr->sess);
+	free(ldr);
 }
 
Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/loc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,876 @@
+/*
+ * Copyright (c) 2007 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <str.h>
+#include <ipc/services.h>
+#include <ns.h>
+#include <ipc/loc.h>
+#include <loc.h>
+#include <fibril_synch.h>
+#include <async.h>
+#include <errno.h>
+#include <malloc.h>
+#include <bool.h>
+
+static FIBRIL_MUTEX_INITIALIZE(loc_supp_block_mutex);
+static FIBRIL_MUTEX_INITIALIZE(loc_cons_block_mutex);
+
+static FIBRIL_MUTEX_INITIALIZE(loc_supplier_mutex);
+static FIBRIL_MUTEX_INITIALIZE(loc_consumer_mutex);
+
+static FIBRIL_MUTEX_INITIALIZE(loc_callback_mutex);
+static bool loc_callback_created = false;
+
+static async_sess_t *loc_supp_block_sess = NULL;
+static async_sess_t *loc_cons_block_sess = NULL;
+
+static async_sess_t *loc_supplier_sess = NULL;
+static async_sess_t *loc_consumer_sess = NULL;
+
+static loc_cat_change_cb_t cat_change_cb = NULL;
+
+static void loc_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	loc_cat_change_cb_t cb_fun;
+	
+	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;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case LOC_EVENT_CAT_CHANGE:
+			fibril_mutex_lock(&loc_callback_mutex);
+			cb_fun = cat_change_cb;
+			if (cb_fun != NULL) {
+				(*cb_fun)();
+			}
+			fibril_mutex_unlock(&loc_callback_mutex);
+			retval = 0;
+			break;
+		default:
+			retval = ENOTSUP;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+
+static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
+    async_sess_t **dst)
+{
+	fibril_mutex_lock(mtx);
+	
+	if ((*dst == NULL) && (src != NULL))
+		*dst = src;
+	
+	fibril_mutex_unlock(mtx);
+}
+
+static int loc_callback_create(void)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	int rc = EOK;
+
+	fibril_mutex_lock(&loc_callback_mutex);
+	
+	if (!loc_callback_created) {
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		
+		ipc_call_t answer;
+		aid_t req = async_send_0(exch, LOC_CALLBACK_CREATE, &answer);
+		async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
+		loc_exchange_end(exch);
+		
+		async_wait_for(req, &retval);
+		if (rc != EOK)
+			goto done;
+		
+		if (retval != EOK) {
+			rc = retval;
+			goto done;
+		}
+		
+		loc_callback_created = true;
+	}
+	
+	rc = EOK;
+done:
+	fibril_mutex_unlock(&loc_callback_mutex);
+	return rc;
+}
+
+/** Start an async exchange on the loc session (blocking).
+ *
+ * @param iface Location service interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *loc_exchange_begin_blocking(loc_interface_t iface)
+{
+	switch (iface) {
+	case LOC_PORT_SUPPLIER:
+		fibril_mutex_lock(&loc_supp_block_mutex);
+		
+		while (loc_supp_block_sess == NULL) {
+			clone_session(&loc_supplier_mutex, loc_supplier_sess,
+			    &loc_supp_block_sess);
+			
+			if (loc_supp_block_sess == NULL)
+				loc_supp_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_LOC, LOC_PORT_SUPPLIER, 0);
+		}
+		
+		fibril_mutex_unlock(&loc_supp_block_mutex);
+		
+		clone_session(&loc_supplier_mutex, loc_supp_block_sess,
+		    &loc_supplier_sess);
+		
+		return async_exchange_begin(loc_supp_block_sess);
+	case LOC_PORT_CONSUMER:
+		fibril_mutex_lock(&loc_cons_block_mutex);
+		
+		while (loc_cons_block_sess == NULL) {
+			clone_session(&loc_consumer_mutex, loc_consumer_sess,
+			    &loc_cons_block_sess);
+			
+			if (loc_cons_block_sess == NULL)
+				loc_cons_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_LOC, LOC_PORT_CONSUMER, 0);
+		}
+		
+		fibril_mutex_unlock(&loc_cons_block_mutex);
+		
+		clone_session(&loc_consumer_mutex, loc_cons_block_sess,
+		    &loc_consumer_sess);
+		
+		return async_exchange_begin(loc_cons_block_sess);
+	default:
+		return NULL;
+	}
+}
+
+/** Start an async exchange on the loc session.
+ *
+ * @param iface Location service interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *loc_exchange_begin(loc_interface_t iface)
+{
+	switch (iface) {
+	case LOC_PORT_SUPPLIER:
+		fibril_mutex_lock(&loc_supplier_mutex);
+		
+		if (loc_supplier_sess == NULL)
+			loc_supplier_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_LOC,
+			    LOC_PORT_SUPPLIER, 0);
+		
+		fibril_mutex_unlock(&loc_supplier_mutex);
+		
+		if (loc_supplier_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(loc_supplier_sess);
+	case LOC_PORT_CONSUMER:
+		fibril_mutex_lock(&loc_consumer_mutex);
+		
+		if (loc_consumer_sess == NULL)
+			loc_consumer_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_LOC,
+			    LOC_PORT_CONSUMER, 0);
+		
+		fibril_mutex_unlock(&loc_consumer_mutex);
+		
+		if (loc_consumer_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(loc_consumer_sess);
+	default:
+		return NULL;
+	}
+}
+
+/** Finish an async exchange on the loc session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+void loc_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
+}
+
+/** Register new driver with loc. */
+int loc_server_register(const char *name, async_client_conn_t conn)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, LOC_SERVER_REGISTER, 0, 0, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_set_client_connection(conn);
+	
+	exch = loc_exchange_begin(LOC_PORT_SUPPLIER);
+	async_connect_to_me(exch, 0, 0, 0, NULL, NULL);
+	loc_exchange_end(exch);
+	
+	async_wait_for(req, &retval);
+	return retval;
+}
+
+/** Register new service.
+ *
+ * The @p interface is used when forwarding connection to the server.
+ * If not 0, the first argument is the interface and the second argument
+ * is the service ID.
+ *
+ * When the interface is zero (default), the first argument is directly
+ * the handle (to ensure backward compatibility).
+ *
+ * @param      fqsn      Fully qualified service name
+ * @param[out] sid       Service ID of new service
+ * @param      interface Interface when forwarding
+ *
+ */
+int loc_service_register_with_iface(const char *fqsn,
+    service_id_t *sid, sysarg_t interface)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, LOC_SERVICE_REGISTER, interface, 0,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, fqsn, str_size(fqsn));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (sid != NULL)
+			*sid = -1;
+		
+		return retval;
+	}
+	
+	if (sid != NULL)
+		*sid = (service_id_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+/** Register new service.
+ *
+ * @param fqsn Fully qualified service name
+ * @param sid  Output: ID of new service
+ *
+ */
+int loc_service_register(const char *fqdn, service_id_t *sid)
+{
+	return loc_service_register_with_iface(fqdn, sid, 0);
+}
+
+/** Unregister service.
+ *
+ * @param sid	Service ID
+ */
+int loc_service_unregister(service_id_t sid)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	
+	exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
+	retval = async_req_1_0(exch, LOC_SERVICE_UNREGISTER, sid);
+	loc_exchange_end(exch);
+	
+	return (int)retval;
+}
+
+int loc_service_get_id(const char *fqdn, service_id_t *handle,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	else {
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		if (exch == NULL)
+			return errno;
+	}
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, LOC_SERVICE_GET_ID, flags, 0,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (handle != NULL)
+			*handle = (service_id_t) -1;
+		
+		return retval;
+	}
+	
+	if (handle != NULL)
+		*handle = (service_id_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+/** Get object name.
+ *
+ * Provided ID of an object, return its name.
+ *
+ * @param method	IPC method
+ * @param id		Object ID
+ * @param name		Place to store pointer to new string. Caller should
+ *			free it using free().
+ * @return		EOK on success or negative error code
+ */
+static int loc_get_name_internal(sysarg_t method, sysarg_t id, char **name)
+{
+	async_exch_t *exch;
+	char name_buf[LOC_NAME_MAXLEN + 1];
+	ipc_call_t dreply;
+	size_t act_size;
+	sysarg_t dretval;
+	
+	*name = NULL;
+	exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, id, &answer);
+	aid_t dreq = async_data_read(exch, name_buf, LOC_NAME_MAXLEN,
+	    &dreply);
+	async_wait_for(dreq, &dretval);
+	
+	loc_exchange_end(exch);
+	
+	if (dretval != EOK) {
+		async_wait_for(req, NULL);
+		return dretval;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK)
+		return retval;
+	
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= LOC_NAME_MAXLEN);
+	name_buf[act_size] = '\0';
+
+	*name = str_dup(name_buf);
+	if (*name == NULL)
+		return ENOMEM;
+	
+	return EOK;
+}
+
+/** Get category name.
+ *
+ * Provided ID of a service, return its name.
+ *
+ * @param cat_id	Category ID
+ * @param name		Place to store pointer to new string. Caller should
+ *			free it using free().
+ * @return		EOK on success or negative error code
+ */
+int loc_category_get_name(category_id_t cat_id, char **name)
+{
+	return loc_get_name_internal(LOC_CATEGORY_GET_NAME, cat_id, name);
+}
+
+/** Get service name.
+ *
+ * Provided ID of a service, return its name.
+ *
+ * @param svc_id	Service ID
+ * @param name		Place to store pointer to new string. Caller should
+ *			free it using free().
+ * @return		EOK on success or negative error code
+ */
+int loc_service_get_name(service_id_t svc_id, char **name)
+{
+	return loc_get_name_internal(LOC_SERVICE_GET_NAME, svc_id, name);
+}
+
+int loc_namespace_get_id(const char *name, service_id_t *handle,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	else {
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		if (exch == NULL)
+			return errno;
+	}
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, LOC_NAMESPACE_GET_ID, flags, 0,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (handle != NULL)
+			*handle = (service_id_t) -1;
+		
+		return retval;
+	}
+	
+	if (handle != NULL)
+		*handle = (service_id_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+/** Get category ID.
+ *
+ * Provided name of a category, return its ID.
+ *
+ * @param name		Category name
+ * @param cat_id	Place to store ID
+ * @param flags		IPC_FLAG_BLOCKING to wait for location service to start
+ * @return		EOK on success or negative error code
+ */
+int loc_category_get_id(const char *name, category_id_t *cat_id,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	else {
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		if (exch == NULL)
+			return errno;
+	}
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOC_CATEGORY_GET_ID,
+	    &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		if (cat_id != NULL)
+			*cat_id = (category_id_t) -1;
+		
+		return retval;
+	}
+	
+	if (cat_id != NULL)
+		*cat_id = (category_id_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+
+loc_object_type_t loc_id_probe(service_id_t handle)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	sysarg_t type;
+	int retval = async_req_1_1(exch, LOC_ID_PROBE, handle, &type);
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK)
+		return LOC_OBJECT_NONE;
+	
+	return (loc_object_type_t) type;
+}
+
+async_sess_t *loc_service_connect(exch_mgmt_t mgmt, service_id_t handle,
+    unsigned int flags)
+{
+	async_sess_t *sess;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		sess = service_connect_blocking(mgmt, SERVICE_LOC,
+		    LOC_CONNECT_TO_SERVICE, handle);
+	else
+		sess = service_connect(mgmt, SERVICE_LOC,
+		    LOC_CONNECT_TO_SERVICE, handle);
+	
+	return sess;
+}
+
+int loc_null_create(void)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	sysarg_t null_id;
+	int retval = async_req_0_1(exch, LOC_NULL_CREATE, &null_id);
+	
+	loc_exchange_end(exch);
+	
+	if (retval != EOK)
+		return -1;
+	
+	return (int) null_id;
+}
+
+void loc_null_destroy(int null_id)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	async_req_1_0(exch, LOC_NULL_DESTROY, (sysarg_t) null_id);
+	loc_exchange_end(exch);
+}
+
+static size_t loc_count_namespaces_internal(async_exch_t *exch)
+{
+	sysarg_t count;
+	int retval = async_req_0_1(exch, LOC_GET_NAMESPACE_COUNT, &count);
+	if (retval != EOK)
+		return 0;
+	
+	return count;
+}
+
+/** Add service to category.
+ *
+ * @param svc_id	Service ID
+ * @param cat_id	Category ID
+ * @return		EOK on success or negative error code
+ */
+int loc_service_add_to_cat(service_id_t svc_id, service_id_t cat_id)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	
+	exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER);
+	retval = async_req_2_0(exch, LOC_SERVICE_ADD_TO_CAT, svc_id, cat_id);
+	loc_exchange_end(exch);
+	
+	return retval;
+}
+
+static size_t loc_count_services_internal(async_exch_t *exch,
+    service_id_t ns_handle)
+{
+	sysarg_t count;
+	int retval = async_req_1_1(exch, LOC_GET_SERVICE_COUNT, ns_handle,
+	    &count);
+	if (retval != EOK)
+		return 0;
+	
+	return count;
+}
+
+size_t loc_count_namespaces(void)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	size_t size = loc_count_namespaces_internal(exch);
+	loc_exchange_end(exch);
+	
+	return size;
+}
+
+size_t loc_count_services(service_id_t ns_handle)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	size_t size = loc_count_services_internal(exch, ns_handle);
+	loc_exchange_end(exch);
+	
+	return size;
+}
+
+size_t loc_get_namespaces(loc_sdesc_t **data)
+{
+	/* Loop until read is succesful */
+	while (true) {
+		async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		size_t count = loc_count_namespaces_internal(exch);
+		loc_exchange_end(exch);
+		
+		if (count == 0)
+			return 0;
+		
+		loc_sdesc_t *devs = (loc_sdesc_t *) calloc(count, sizeof(loc_sdesc_t));
+		if (devs == NULL)
+			return 0;
+		
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		
+		ipc_call_t answer;
+		aid_t req = async_send_0(exch, LOC_GET_NAMESPACES, &answer);
+		int rc = async_data_read_start(exch, devs, count * sizeof(loc_sdesc_t));
+		
+		loc_exchange_end(exch);
+		
+		if (rc == EOVERFLOW) {
+			/*
+			 * Number of namespaces has changed since
+			 * the last call of LOC_GET_NAMESPACE_COUNT
+			 */
+			free(devs);
+			continue;
+		}
+		
+		if (rc != EOK) {
+			async_wait_for(req, NULL);
+			free(devs);
+			return 0;
+		}
+		
+		sysarg_t retval;
+		async_wait_for(req, &retval);
+		
+		if (retval != EOK)
+			return 0;
+		
+		*data = devs;
+		return count;
+	}
+}
+
+size_t loc_get_services(service_id_t ns_handle, loc_sdesc_t **data)
+{
+	/* Loop until read is succesful */
+	while (true) {
+		async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		size_t count = loc_count_services_internal(exch, ns_handle);
+		loc_exchange_end(exch);
+		
+		if (count == 0)
+			return 0;
+		
+		loc_sdesc_t *devs = (loc_sdesc_t *) calloc(count, sizeof(loc_sdesc_t));
+		if (devs == NULL)
+			return 0;
+		
+		exch = loc_exchange_begin(LOC_PORT_CONSUMER);
+		
+		ipc_call_t answer;
+		aid_t req = async_send_1(exch, LOC_GET_SERVICES, ns_handle, &answer);
+		int rc = async_data_read_start(exch, devs, count * sizeof(loc_sdesc_t));
+		
+		loc_exchange_end(exch);
+		
+		if (rc == EOVERFLOW) {
+			/*
+			 * Number of services has changed since
+			 * the last call of LOC_GET_SERVICE_COUNT
+			 */
+			free(devs);
+			continue;
+		}
+		
+		if (rc != EOK) {
+			async_wait_for(req, NULL);
+			free(devs);
+			return 0;
+		}
+		
+		sysarg_t retval;
+		async_wait_for(req, &retval);
+		
+		if (retval != EOK)
+			return 0;
+		
+		*data = devs;
+		return count;
+	}
+}
+
+static int loc_category_get_ids_once(sysarg_t method, sysarg_t arg1,
+    sysarg_t *id_buf, size_t buf_size, size_t *act_size)
+{
+	async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	int rc = async_data_read_start(exch, id_buf, buf_size);
+	
+	loc_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		return retval;
+	}
+	
+	*act_size = IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Get list of IDs.
+ *
+ * Returns an allocated array of service IDs.
+ *
+ * @param method	IPC method
+ * @param arg1		IPC argument 1
+ * @param data		Place to store pointer to array of IDs
+ * @param count		Place to store number of IDs
+ * @return 		EOK on success or negative error code
+ */
+static int loc_get_ids_internal(sysarg_t method, sysarg_t arg1,
+    sysarg_t **data, size_t *count)
+{
+	service_id_t *ids;
+	size_t act_size;
+	size_t alloc_size;
+	int rc;
+
+	*data = NULL;
+	act_size = 0;	/* silence warning */
+
+	rc = loc_category_get_ids_once(method, arg1, NULL, 0,
+	    &act_size);
+	if (rc != EOK)
+		return rc;
+
+	alloc_size = act_size;
+	ids = malloc(alloc_size);
+	if (ids == NULL)
+		return ENOMEM;
+
+	while (true) {
+		rc = loc_category_get_ids_once(method, arg1, ids, alloc_size,
+		    &act_size);
+		if (rc != EOK)
+			return rc;
+
+		if (act_size <= alloc_size)
+			break;
+
+		alloc_size *= 2;
+		free(ids);
+
+		ids = malloc(alloc_size);
+		if (ids == NULL)
+			return ENOMEM;
+	}
+
+	*count = act_size / sizeof(category_id_t);
+	*data = ids;
+	return EOK;
+}
+
+/** Get list of services in category.
+ *
+ * Returns an allocated array of service IDs.
+ *
+ * @param cat_id	Category ID
+ * @param data		Place to store pointer to array of IDs
+ * @param count		Place to store number of IDs
+ * @return 		EOK on success or negative error code
+ */
+int loc_category_get_svcs(category_id_t cat_id, service_id_t **data,
+    size_t *count)
+{
+	return loc_get_ids_internal(LOC_CATEGORY_GET_SVCS, cat_id,
+	    data, count);
+}
+
+/** Get list of categories.
+ *
+ * Returns an allocated array of category IDs.
+ *
+ * @param data		Place to store pointer to array of IDs
+ * @param count		Place to store number of IDs
+ * @return 		EOK on success or negative error code
+ */
+int loc_get_categories(category_id_t **data, size_t *count)
+{
+	return loc_get_ids_internal(LOC_GET_CATEGORIES, 0,
+	    data, count);
+}
+
+int loc_register_cat_change_cb(loc_cat_change_cb_t cb_fun)
+{
+	if (loc_callback_create() != EOK)
+		return EIO;
+
+	cat_change_cb = cb_fun;
+	return EOK;
+}
Index: uspace/lib/c/generic/malloc.c
===================================================================
--- uspace/lib/c/generic/malloc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/malloc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,4 +44,5 @@
 #include <mem.h>
 #include <futex.h>
+#include <stdlib.h>
 #include <adt/gcdlcm.h>
 #include "private/malloc.h"
@@ -63,4 +64,14 @@
  */
 #define BASE_ALIGN  16
+
+/** Heap shrink granularity
+ *
+ * Try not to pump and stress the heap to much
+ * by shrinking and enlarging it too often.
+ * A heap area won't shrunk if it the released
+ * free block is smaller than this constant.
+ *
+ */
+#define SHRINK_GRANULARITY  (64 * PAGE_SIZE)
 
 /** Overhead of each heap block. */
@@ -68,4 +79,8 @@
 	(sizeof(heap_block_head_t) + sizeof(heap_block_foot_t))
 
+/** Overhead of each area. */
+#define AREA_OVERHEAD(size) \
+	(ALIGN_UP(size + sizeof(heap_area_t), BASE_ALIGN))
+
 /** Calculate real size of a heap block.
  *
@@ -85,6 +100,19 @@
  *
  */
-#define AREA_FIRST_BLOCK(area) \
+#define AREA_FIRST_BLOCK_HEAD(area) \
 	(ALIGN_UP(((uintptr_t) (area)) + sizeof(heap_area_t), BASE_ALIGN))
+
+/** Get last block in heap area.
+ *
+ */
+#define AREA_LAST_BLOCK_FOOT(area) \
+	(((uintptr_t) (area)->end) - sizeof(heap_block_foot_t))
+
+/** Get header in heap block.
+ *
+ */
+#define BLOCK_HEAD(foot) \
+	((heap_block_head_t *) \
+	    (((uintptr_t) (foot)) + sizeof(heap_block_foot_t) - (foot)->size))
 
 /** Get footer in heap block.
@@ -93,5 +121,5 @@
 #define BLOCK_FOOT(head) \
 	((heap_block_foot_t *) \
-	    (((uintptr_t) head) + head->size - sizeof(heap_block_foot_t)))
+	    (((uintptr_t) (head)) + (head)->size - sizeof(heap_block_foot_t)))
 
 /** Heap area.
@@ -114,4 +142,7 @@
 	void *end;
 	
+	/** Previous heap area */
+	struct heap_area *prev;
+	
 	/** Next heap area */
 	struct heap_area *next;
@@ -156,8 +187,24 @@
 
 /** Next heap block to examine (next fit algorithm) */
-static heap_block_head_t *next = NULL;
+static heap_block_head_t *next_fit = NULL;
 
 /** Futex for thread-safe heap manipulation */
 static futex_t malloc_futex = FUTEX_INITIALIZER;
+
+#ifndef NDEBUG
+
+#define malloc_assert(expr) \
+	do { \
+		if (!(expr)) {\
+			futex_up(&malloc_futex); \
+			assert_abort(#expr, __FILE__, __LINE__); \
+		} \
+	} while (0)
+
+#else /* NDEBUG */
+
+#define malloc_assert(expr)
+
+#endif /* NDEBUG */
 
 /** Initialize a heap block
@@ -201,14 +248,16 @@
 	heap_block_head_t *head = (heap_block_head_t *) addr;
 	
-	assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
+	malloc_assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
 	
 	heap_block_foot_t *foot = BLOCK_FOOT(head);
 	
-	assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
-	assert(head->size == foot->size);
+	malloc_assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
+	malloc_assert(head->size == foot->size);
 }
 
 /** Check a heap area structure
  *
+ * Should be called only inside the critical section.
+ *
  * @param addr Address of the heap area.
  *
@@ -218,14 +267,16 @@
 	heap_area_t *area = (heap_area_t *) addr;
 	
-	assert(area->magic == HEAP_AREA_MAGIC);
-	assert(area->start < area->end);
-	assert(((uintptr_t) area->start % PAGE_SIZE) == 0);
-	assert(((uintptr_t) area->end % PAGE_SIZE) == 0);
+	malloc_assert(area->magic == HEAP_AREA_MAGIC);
+	malloc_assert(addr == area->start);
+	malloc_assert(area->start < area->end);
+	malloc_assert(((uintptr_t) area->start % PAGE_SIZE) == 0);
+	malloc_assert(((uintptr_t) area->end % PAGE_SIZE) == 0);
 }
 
 /** Create new heap area
  *
- * @param start Preffered starting address of the new area.
- * @param size  Size of the area.
+ * Should be called only inside the critical section.
+ *
+ * @param size Size of the area.
  *
  */
@@ -247,10 +298,10 @@
 	
 	area->start = astart;
-	area->end = (void *)
-	    ALIGN_DOWN((uintptr_t) astart + asize, BASE_ALIGN);
+	area->end = (void *) ((uintptr_t) astart + asize);
+	area->prev = NULL;
 	area->next = NULL;
 	area->magic = HEAP_AREA_MAGIC;
 	
-	void *block = (void *) AREA_FIRST_BLOCK(area);
+	void *block = (void *) AREA_FIRST_BLOCK_HEAD(area);
 	size_t bsize = (size_t) (area->end - block);
 	
@@ -261,4 +312,5 @@
 		last_heap_area = area;
 	} else {
+		area->prev = last_heap_area;
 		last_heap_area->next = area;
 		last_heap_area = area;
@@ -270,6 +322,10 @@
 /** Try to enlarge a heap area
  *
+ * Should be called only inside the critical section.
+ *
  * @param area Heap area to grow.
- * @param size Gross size of item to allocate (bytes).
+ * @param size Gross size to grow (bytes).
+ *
+ * @return True if successful.
  *
  */
@@ -281,10 +337,8 @@
 	area_check(area);
 	
-	size_t asize = ALIGN_UP((size_t) (area->end - area->start) + size,
-	    PAGE_SIZE);
-	
 	/* New heap area size */
-	void *end = (void *)
-	    ALIGN_DOWN((uintptr_t) area->start + asize, BASE_ALIGN);
+	size_t gross_size = (size_t) (area->end - area->start) + size;
+	size_t asize = ALIGN_UP(gross_size, PAGE_SIZE);
+	void *end = (void *) ((uintptr_t) area->start + asize);
 	
 	/* Check for overflow */
@@ -298,5 +352,7 @@
 	
 	/* Add new free block */
-	block_init(area->end, (size_t) (end - area->end), true, area);
+	size_t net_size = (size_t) (end - area->end);
+	if (net_size > 0)
+		block_init(area->end, net_size, true, area);
 	
 	/* Update heap area parameters */
@@ -308,4 +364,6 @@
 /** Try to enlarge any of the heap areas
  *
+ * Should be called only inside the critical section.
+ *
  * @param size Gross size of item to allocate (bytes).
  *
@@ -317,6 +375,6 @@
 	
 	/* First try to enlarge some existing area */
-	heap_area_t *area;
-	for (area = first_heap_area; area != NULL; area = area->next) {
+	for (heap_area_t *area = first_heap_area; area != NULL;
+	    area = area->next) {
 		if (area_grow(area, size))
 			return true;
@@ -324,15 +382,110 @@
 	
 	/* Eventually try to create a new area */
-	return area_create(AREA_FIRST_BLOCK(size));
-}
-
-/** Try to shrink heap space
- *
+	return area_create(AREA_OVERHEAD(size));
+}
+
+/** Try to shrink heap
+ *
+ * Should be called only inside the critical section.
  * In all cases the next pointer is reset.
  *
- */
-static void heap_shrink(void)
-{
-	next = NULL;
+ * @param area Last modified heap area.
+ *
+ */
+static void heap_shrink(heap_area_t *area)
+{
+	area_check(area);
+	
+	heap_block_foot_t *last_foot =
+	    (heap_block_foot_t *) AREA_LAST_BLOCK_FOOT(area);
+	heap_block_head_t *last_head = BLOCK_HEAD(last_foot);
+	
+	block_check((void *) last_head);
+	malloc_assert(last_head->area == area);
+	
+	if (last_head->free) {
+		/*
+		 * The last block of the heap area is
+		 * unused. The area might be potentially
+		 * shrunk.
+		 */
+		
+		heap_block_head_t *first_head =
+		    (heap_block_head_t *) AREA_FIRST_BLOCK_HEAD(area);
+		
+		block_check((void *) first_head);
+		malloc_assert(first_head->area == area);
+		
+		size_t shrink_size = ALIGN_DOWN(last_head->size, PAGE_SIZE);
+		
+		if (first_head == last_head) {
+			/*
+			 * The entire heap area consists of a single
+			 * free heap block. This means we can get rid
+			 * of it entirely.
+			 */
+			
+			heap_area_t *prev = area->prev;
+			heap_area_t *next = area->next;
+			
+			if (prev != NULL) {
+				area_check(prev);
+				prev->next = next;
+			} else
+				first_heap_area = next;
+			
+			if (next != NULL) {
+				area_check(next);
+				next->prev = prev;
+			} else
+				last_heap_area = prev;
+			
+			as_area_destroy(area->start);
+		} else if (shrink_size >= SHRINK_GRANULARITY) {
+			/*
+			 * Make sure that we always shrink the area
+			 * by a multiple of page size and update
+			 * the block layout accordingly.
+			 */
+			
+			size_t asize = (size_t) (area->end - area->start) - shrink_size;
+			void *end = (void *) ((uintptr_t) area->start + asize);
+			
+			/* Resize the address space area */
+			int ret = as_area_resize(area->start, asize, 0);
+			if (ret != EOK)
+				abort();
+			
+			/* Update heap area parameters */
+			area->end = end;
+			size_t excess = ((size_t) area->end) - ((size_t) last_head);
+			
+			if (excess > 0) {
+				if (excess >= STRUCT_OVERHEAD) {
+					/*
+					 * The previous block cannot be free and there
+					 * is enough free space left in the area to
+					 * create a new free block.
+					 */
+					block_init((void *) last_head, excess, true, area);
+				} else {
+					/*
+					 * The excess is small. Therefore just enlarge
+					 * the previous block.
+					 */
+					heap_block_foot_t *prev_foot = (heap_block_foot_t *)
+					    (((uintptr_t) last_head) - sizeof(heap_block_foot_t));
+					heap_block_head_t *prev_head = BLOCK_HEAD(prev_foot);
+					
+					block_check((void *) prev_head);
+					
+					block_init(prev_head, prev_head->size + excess,
+					    prev_head->free, area);
+				}
+			}
+		}
+	}
+	
+	next_fit = NULL;
 }
 
@@ -361,5 +514,5 @@
 static void split_mark(heap_block_head_t *cur, const size_t size)
 {
-	assert(cur->size >= size);
+	malloc_assert(cur->size >= size);
 	
 	/* See if we should split the block. */
@@ -397,9 +550,8 @@
 {
 	area_check((void *) area);
-	assert((void *) first_block >= (void *) AREA_FIRST_BLOCK(area));
-	assert((void *) first_block < area->end);
-	
-	heap_block_head_t *cur;
-	for (cur = first_block; (void *) cur < area->end;
+	malloc_assert((void *) first_block >= (void *) AREA_FIRST_BLOCK_HEAD(area));
+	malloc_assert((void *) first_block < area->end);
+	
+	for (heap_block_head_t *cur = first_block; (void *) cur < area->end;
 	    cur = (heap_block_head_t *) (((void *) cur) + cur->size)) {
 		block_check(cur);
@@ -424,5 +576,5 @@
 				split_mark(cur, real_size);
 				
-				next = cur;
+				next_fit = cur;
 				return addr;
 			} else {
@@ -435,5 +587,5 @@
 					 * data in (including alignment).
 					 */
-					if ((void *) cur > (void *) AREA_FIRST_BLOCK(area)) {
+					if ((void *) cur > (void *) AREA_FIRST_BLOCK_HEAD(area)) {
 						/*
 						 * There is a block before the current block.
@@ -476,5 +628,5 @@
 						split_mark(next_head, real_size);
 						
-						next = next_head;
+						next_fit = next_head;
 						return aligned;
 					} else {
@@ -495,12 +647,12 @@
 							size_t reduced_size = cur->size - excess;
 							cur = (heap_block_head_t *)
-							    (AREA_FIRST_BLOCK(area) + excess);
+							    (AREA_FIRST_BLOCK_HEAD(area) + excess);
 							
-							block_init((void *) AREA_FIRST_BLOCK(area), excess,
-							    true, area);
+							block_init((void *) AREA_FIRST_BLOCK_HEAD(area),
+							    excess, true, area);
 							block_init(cur, reduced_size, true, area);
 							split_mark(cur, real_size);
 							
-							next = cur;
+							next_fit = cur;
 							return aligned;
 						}
@@ -526,5 +678,5 @@
 static void *malloc_internal(const size_t size, const size_t align)
 {
-	assert(first_heap_area != NULL);
+	malloc_assert(first_heap_area != NULL);
 	
 	if (align == 0)
@@ -540,5 +692,5 @@
 	
 	/* Try the next fit approach */
-	split = next;
+	split = next_fit;
 	
 	if (split != NULL) {
@@ -551,8 +703,8 @@
 	
 	/* Search the entire heap */
-	heap_area_t *area;
-	for (area = first_heap_area; area != NULL; area = area->next) {
+	for (heap_area_t *area = first_heap_area; area != NULL;
+	    area = area->next) {
 		heap_block_head_t *first = (heap_block_head_t *)
-		    AREA_FIRST_BLOCK(area);
+		    AREA_FIRST_BLOCK_HEAD(area);
 		
 		void *addr = malloc_area(area, first, split, real_size,
@@ -651,11 +803,11 @@
 	
 	block_check(head);
-	assert(!head->free);
+	malloc_assert(!head->free);
 	
 	heap_area_t *area = head->area;
 	
 	area_check(area);
-	assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
-	assert((void *) head < area->end);
+	malloc_assert((void *) head >= (void *) AREA_FIRST_BLOCK_HEAD(area));
+	malloc_assert((void *) head < area->end);
 	
 	void *ptr = NULL;
@@ -674,5 +826,5 @@
 			block_init((void *) head + real_size,
 			    orig_size - real_size, true, area);
-			heap_shrink();
+			heap_shrink(area);
 		}
 		
@@ -696,5 +848,5 @@
 			
 			ptr = ((void *) head) + sizeof(heap_block_head_t);
-			next = NULL;
+			next_fit = NULL;
 		} else
 			reloc = true;
@@ -728,11 +880,11 @@
 	
 	block_check(head);
-	assert(!head->free);
+	malloc_assert(!head->free);
 	
 	heap_area_t *area = head->area;
 	
 	area_check(area);
-	assert((void *) head >= (void *) AREA_FIRST_BLOCK(area));
-	assert((void *) head < area->end);
+	malloc_assert((void *) head >= (void *) AREA_FIRST_BLOCK_HEAD(area));
+	malloc_assert((void *) head < area->end);
 	
 	/* Mark the block itself as free. */
@@ -750,5 +902,5 @@
 	
 	/* Look at the previous block. If it is free, merge the two. */
-	if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) {
+	if ((void *) head > (void *) AREA_FIRST_BLOCK_HEAD(area)) {
 		heap_block_foot_t *prev_foot =
 		    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
@@ -764,9 +916,58 @@
 	}
 	
-	heap_shrink();
+	heap_shrink(area);
 	
 	futex_up(&malloc_futex);
 }
 
+void *heap_check(void)
+{
+	futex_down(&malloc_futex);
+	
+	if (first_heap_area == NULL) {
+		futex_up(&malloc_futex);
+		return (void *) -1;
+	}
+	
+	/* Walk all heap areas */
+	for (heap_area_t *area = first_heap_area; area != NULL;
+	    area = area->next) {
+		
+		/* Check heap area consistency */
+		if ((area->magic != HEAP_AREA_MAGIC) ||
+		    ((void *) area != area->start) ||
+		    (area->start >= area->end) ||
+		    (((uintptr_t) area->start % PAGE_SIZE) != 0) ||
+		    (((uintptr_t) area->end % PAGE_SIZE) != 0)) {
+			futex_up(&malloc_futex);
+			return (void *) area;
+		}
+		
+		/* Walk all heap blocks */
+		for (heap_block_head_t *head = (heap_block_head_t *)
+		    AREA_FIRST_BLOCK_HEAD(area); (void *) head < area->end;
+		    head = (heap_block_head_t *) (((void *) head) + head->size)) {
+			
+			/* Check heap block consistency */
+			if (head->magic != HEAP_BLOCK_HEAD_MAGIC) {
+				futex_up(&malloc_futex);
+				return (void *) head;
+			}
+			
+			heap_block_foot_t *foot = BLOCK_FOOT(head);
+			
+			if ((foot->magic != HEAP_BLOCK_FOOT_MAGIC) ||
+			    (head->size != foot->size)) {
+				futex_up(&malloc_futex);
+				return (void *) foot;
+			}
+		}
+	}
+	
+	futex_up(&malloc_futex);
+	
+	return NULL;
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/net/icmp_api.c
===================================================================
--- uspace/lib/c/generic/net/icmp_api.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/net/icmp_api.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -54,5 +54,5 @@
  * timeout occurs.
  *
- * @param[in] icmp_phone The ICMP module phone used for (semi)remote calls.
+ * @param[in] sess The ICMP session.
  * @param[in] size	The message data length in bytes.
  * @param[in] timeout	The timeout in milliseconds.
@@ -73,5 +73,5 @@
  */
 int
-icmp_echo_msg(int icmp_phone, size_t size, mseconds_t timeout, ip_ttl_t ttl,
+icmp_echo_msg(async_sess_t *sess, size_t size, mseconds_t timeout, ip_ttl_t ttl,
     ip_tos_t tos, int dont_fragment, const struct sockaddr *addr,
     socklen_t addrlen)
@@ -82,10 +82,14 @@
 	if (addrlen <= 0)
 		return EINVAL;
-
-	message_id = async_send_5(icmp_phone, NET_ICMP_ECHO, size, timeout, ttl,
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	message_id = async_send_5(exch, NET_ICMP_ECHO, size, timeout, ttl,
 	    tos, (sysarg_t) dont_fragment, NULL);
-
+	
 	/* Send the address */
-	async_data_write_start(icmp_phone, addr, (size_t) addrlen);
+	async_data_write_start(exch, addr, (size_t) addrlen);
+	
+	async_exchange_end(exch);
 
 	async_wait_for(message_id, &result);
Index: uspace/lib/c/generic/net/icmp_common.c
===================================================================
--- uspace/lib/c/generic/net/icmp_common.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/net/icmp_common.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,14 +45,10 @@
 /** Connect to the ICMP module.
  *
- * @param[in] timeout Connection timeout in microseconds, zero
- *                    for no timeout.
- *
- * @return ICMP module phone on success.
- * @return ETIMEOUT if the connection timeouted.
+ * @return ICMP module session.
  *
  */
-int icmp_connect_module(suseconds_t timeout)
+async_sess_t *icmp_connect_module(void)
 {
-	return connect_to_service_timeout(SERVICE_ICMP, timeout);
+	return connect_to_service(SERVICE_ICMP);
 }
 
Index: uspace/lib/c/generic/net/modules.c
===================================================================
--- uspace/lib/c/generic/net/modules.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/net/modules.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,7 +45,5 @@
 #include <ipc/services.h>
 #include <net/modules.h>
-
-/** The time between connect requests in microseconds. */
-#define MODULE_WAIT_TIME	(10 * 1000)
+#include <ns.h>
 
 /** Answer a call.
@@ -95,109 +93,65 @@
 }
 
-/** Create bidirectional connection with the needed module service and registers
+/** Create bidirectional connection with the needed module service and register
  * the message receiver.
  *
- * @param[in] need	The needed module service.
- * @param[in] arg1	The first parameter.
- * @param[in] arg2	The second parameter.
- * @param[in] arg3	The third parameter.
- * @param[in] client_receiver The message receiver.
- *
- * @return		The phone of the needed service.
- * @return		Other error codes as defined for the ipc_connect_to_me()
- *			function.
- */
-int bind_service(services_t need, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
-    async_client_conn_t client_receiver)
-{
-	return bind_service_timeout(need, arg1, arg2, arg3, client_receiver, 0);
-}
-
-/** Create bidirectional connection with the needed module service and registers
- * the message receiver.
- *
- * @param[in] need	The needed module service.
- * @param[in] arg1	The first parameter.
- * @param[in] arg2	The second parameter.
- * @param[in] arg3	The third parameter.
- * @param[in] client_receiver The message receiver.
- * @param[in] timeout	The connection timeout in microseconds. No timeout if
- * 			set to zero (0).
- *
- * @return		The phone of the needed service.
- * @return		ETIMEOUT if the connection timeouted.
- * @return		Other error codes as defined for the ipc_connect_to_me()
- *			function.
- *
- */
-int bind_service_timeout(services_t need, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, async_client_conn_t client_receiver, suseconds_t timeout)
+ * @param[in] need            Needed module service.
+ * @param[in] arg1            First parameter.
+ * @param[in] arg2            Second parameter.
+ * @param[in] arg3            Third parameter.
+ * @param[in] client_receiver Message receiver.
+ *
+ * @return Session to the needed service.
+ * @return Other error codes as defined for the async_connect_to_me()
+ *         function.
+ *
+ */
+async_sess_t *bind_service(services_t need, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, async_client_conn_t client_receiver)
 {
 	/* Connect to the needed service */
-	int phone = connect_to_service_timeout(need, timeout);
-	if (phone >= 0) {
+	async_sess_t *sess = connect_to_service(need);
+	if (sess != NULL) {
 		/* Request the bidirectional connection */
-		int rc = async_connect_to_me(phone, arg1, arg2, arg3, client_receiver);
+		async_exch_t *exch = async_exchange_begin(sess);
+		int rc = async_connect_to_me(exch, arg1, arg2, arg3,
+		    client_receiver, NULL);
+		async_exchange_end(exch);
+		
 		if (rc != EOK) {
-			async_hangup(phone);
-			return rc;
+			async_hangup(sess);
+			errno = rc;
+			return NULL;
 		}
 	}
 	
-	return phone;
-}
-
-/** Connects to the needed module.
- *
- * @param[in] need	The needed module service.
- * @return		The phone of the needed service.
- */
-int connect_to_service(services_t need)
-{
-	return connect_to_service_timeout(need, 0);
-}
-
-/** Connects to the needed module.
- *
- *  @param[in] need	The needed module service.
- *  @param[in] timeout	The connection timeout in microseconds. No timeout if
- *			set to zero (0).
- *  @return		The phone of the needed service.
- *  @return		ETIMEOUT if the connection timeouted.
- */
-int connect_to_service_timeout(services_t need, suseconds_t timeout)
-{
-	int phone;
-
-	/* If no timeout is set */
-	if (timeout <= 0)
-		return async_connect_me_to_blocking(PHONE_NS, need, 0, 0);
-
-	while (true) {
-		phone = async_connect_me_to(PHONE_NS, need, 0, 0);
-		if ((phone >= 0) || (phone != ENOENT))
-			return phone;
-
-		/* Abort if no time is left */
-		if (timeout <= 0)
-			return ETIMEOUT;
-
-		/* Wait the minimum of the module wait time and the timeout */
-		usleep((timeout <= MODULE_WAIT_TIME) ?
-		    timeout : MODULE_WAIT_TIME);
-		timeout -= MODULE_WAIT_TIME;
-	}
-}
-
-/** Replies the data to the other party.
- *
- * @param[in] data	The data buffer to be sent.
+	return sess;
+}
+
+/** Connect to the needed module.
+ *
+ * @param[in] need Needed module service.
+ *
+ * @return Session to the needed service.
+ * @return NULL if the connection timeouted.
+ *
+ */
+async_sess_t *connect_to_service(services_t need)
+{
+	return service_connect_blocking(EXCHANGE_SERIALIZE, need, 0, 0);
+}
+
+/** Reply the data to the other party.
+ *
+ * @param[in] data        The data buffer to be sent.
  * @param[in] data_length The buffer length.
- * @return		EOK on success.
- * @return		EINVAL if the client does not expect the data.
- * @return		EOVERFLOW if the client does not expect all the data.
- *			Only partial data are transfered.
- * @return		Other error codes as defined for the
- *			async_data_read_finalize() function.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the client does not expect the data.
+ * @return EOVERFLOW if the client does not expect all the data.
+ *         Only partial data are transfered.
+ * @return Other error codes as defined for the
+ *         async_data_read_finalize() function.
+ *
  */
 int data_reply(void *data, size_t data_length)
@@ -205,9 +159,9 @@
 	size_t length;
 	ipc_callid_t callid;
-
+	
 	/* Fetch the request */
 	if (!async_data_read_receive(&callid, &length))
 		return EINVAL;
-
+	
 	/* Check the requested data size */
 	if (length < data_length) {
@@ -215,5 +169,5 @@
 		return EOVERFLOW;
 	}
-
+	
 	/* Send the data */
 	return async_data_read_finalize(callid, data, data_length);
Index: uspace/lib/c/generic/net/packet.c
===================================================================
--- uspace/lib/c/generic/net/packet.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/net/packet.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -190,5 +190,5 @@
 		}
 	}
-	gpm_destroy(&pm_globals.packet_map);
+	gpm_destroy(&pm_globals.packet_map, free);
 	/* leave locked */
 }
Index: uspace/lib/c/generic/net/socket_client.c
===================================================================
--- uspace/lib/c/generic/net/socket_client.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/net/socket_client.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -64,7 +64,4 @@
 #define SOCKET_MAX_ACCEPTED_SIZE	0
 
-/** Default timeout for connections in microseconds. */
-#define SOCKET_CONNECT_TIMEOUT	(1 * 1000 * 1000)
-
 /**
  * Maximum number of random attempts to find a new socket identifier before
@@ -86,6 +83,6 @@
 	/** Socket identifier. */
 	int socket_id;
-	/** Parent module phone. */
-	int phone;
+	/** Parent module session. */
+	async_sess_t *sess;
 	/** Parent module service. */
 	services_t service;
@@ -146,12 +143,8 @@
 /** Socket client library global data. */
 static struct socket_client_globals {
-	/** TCP module phone. */
-	int tcp_phone;
-	/** UDP module phone. */
-	int udp_phone;
-
-//	/** The last socket identifier.
-//	 */
-//	int last_id;
+	/** TCP module session. */
+	async_sess_t *tcp_sess;
+	/** UDP module session. */
+	async_sess_t *udp_sess;
 
 	/** Active sockets. */
@@ -166,7 +159,6 @@
 	fibril_rwlock_t lock;
 } socket_globals = {
-	.tcp_phone = -1,
-	.udp_phone = -1,
-//	.last_id = 0,
+	.tcp_sess = NULL,
+	.udp_sess = NULL,
 	.sockets = NULL,
 	.lock = FIBRIL_RWLOCK_INITIALIZER(socket_globals.lock)
@@ -202,6 +194,7 @@
  * @param[in] iid	The initial message identifier.
  * @param[in] icall	The initial message call structure.
- */
-static void socket_connection(ipc_callid_t iid, ipc_call_t * icall)
+ * @param[in] arg	Local argument.
+ */
+static void socket_connection(ipc_callid_t iid, ipc_call_t * icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -281,40 +274,36 @@
 }
 
-/** Returns the TCP module phone.
- *
- * Connects to the TCP module if necessary.
- *
- * @return		The TCP module phone.
- * @return		Other error codes as defined for the
- *			bind_service_timeout() function.
- */
-static int socket_get_tcp_phone(void)
-{
-	if (socket_globals.tcp_phone < 0) {
-		socket_globals.tcp_phone = bind_service_timeout(SERVICE_TCP,
-		    0, 0, SERVICE_TCP, socket_connection,
-		    SOCKET_CONNECT_TIMEOUT);
-	}
-
-	return socket_globals.tcp_phone;
-}
-
-/** Returns the UDP module phone.
- *
- * Connects to the UDP module if necessary.
- *
- * @return		The UDP module phone.
- * @return		Other error codes as defined for the
- *			bind_service_timeout() function.
- */
-static int socket_get_udp_phone(void)
-{
-	if (socket_globals.udp_phone < 0) {
-		socket_globals.udp_phone = bind_service_timeout(SERVICE_UDP,
-		    0, 0, SERVICE_UDP, socket_connection,
-		    SOCKET_CONNECT_TIMEOUT);
-	}
-
-	return socket_globals.udp_phone;
+/** Return the TCP module session.
+ *
+ * Connect to the TCP module if necessary.
+ *
+ * @return The TCP module session.
+ *
+ */
+static async_sess_t *socket_get_tcp_sess(void)
+{
+	if (socket_globals.tcp_sess == NULL) {
+		socket_globals.tcp_sess = bind_service(SERVICE_TCP,
+		    0, 0, SERVICE_TCP, socket_connection);
+	}
+
+	return socket_globals.tcp_sess;
+}
+
+/** Return the UDP module session.
+ *
+ * Connect to the UDP module if necessary.
+ *
+ * @return The UDP module session.
+ *
+ */
+static async_sess_t *socket_get_udp_sess(void)
+{
+	if (socket_globals.udp_sess == NULL) {
+		socket_globals.udp_sess = bind_service(SERVICE_UDP,
+		    0, 0, SERVICE_UDP, socket_connection);
+	}
+
+	return socket_globals.udp_sess;
 }
 
@@ -332,5 +321,4 @@
 	sockets = socket_get_sockets();
 	count = 0;
-//	socket_id = socket_globals.last_id;
 
 	do {
@@ -345,14 +333,10 @@
 			if (socket_id < INT_MAX) {
 				++socket_id;
-/*			} else if(socket_globals.last_id) {
- *				socket_globals.last_id = 0;
- *				socket_id = 1;
- */			} else {
+			} else {
 				return ELIMIT;
 			}
 		}
 	} while (sockets_find(sockets, socket_id));
-
-//	last_id = socket_id
+	
 	return socket_id;
 }
@@ -361,14 +345,13 @@
  *
  * @param[in,out] socket The socket to be initialized.
- * @param[in] socket_id	The new socket identifier.
- * @param[in] phone	The parent module phone.
- * @param[in] service	The parent module service.
- */
-static void
-socket_initialize(socket_t *socket, int socket_id, int phone,
-    services_t service)
+ * @param[in] socket_id  The new socket identifier.
+ * @param[in] sess       The parent module session.
+ * @param[in] service    The parent module service.
+ */
+static void socket_initialize(socket_t *socket, int socket_id,
+    async_sess_t *sess, services_t service)
 {
 	socket->socket_id = socket_id;
-	socket->phone = phone;
+	socket->sess = sess;
 	socket->service = service;
 	dyn_fifo_initialize(&socket->received, SOCKET_INITIAL_RECEIVED_SIZE);
@@ -395,10 +378,10 @@
  * @return		Other error codes as defined for the NET_SOCKET message.
  * @return		Other error codes as defined for the
- *			bind_service_timeout() function.
+ *			bind_service() function.
  */
 int socket(int domain, int type, int protocol)
 {
 	socket_t *socket;
-	int phone;
+	async_sess_t *sess;
 	int socket_id;
 	services_t service;
@@ -417,5 +400,5 @@
 			switch (protocol) {
 			case IPPROTO_TCP:
-				phone = socket_get_tcp_phone();
+				sess = socket_get_tcp_sess();
 				service = SERVICE_TCP;
 				break;
@@ -432,5 +415,5 @@
 			switch (protocol) {
 			case IPPROTO_UDP:
-				phone = socket_get_udp_phone();
+				sess = socket_get_udp_sess();
 				service = SERVICE_UDP;
 				break;
@@ -453,6 +436,6 @@
 	}
 
-	if (phone < 0)
-		return phone;
+	if (sess == NULL)
+		return ENOENT;
 
 	/* Create a new socket structure */
@@ -471,7 +454,10 @@
 		return socket_id;
 	}
-
-	rc = (int) async_req_3_3(phone, NET_SOCKET, socket_id, 0, service, NULL,
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	rc = (int) async_req_3_3(exch, NET_SOCKET, socket_id, 0, service, NULL,
 	    &fragment_size, &header_size);
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&socket_globals.lock);
@@ -484,5 +470,5 @@
 
 	/* Finish the new socket initialization */
-	socket_initialize(socket, socket_id, phone, service);
+	socket_initialize(socket, socket_id, sess, service);
 	/* Store the new socket */
 	rc = sockets_add(socket_get_sockets(), socket_id, socket);
@@ -493,6 +479,10 @@
 		dyn_fifo_destroy(&socket->accepted);
 		free(socket);
-		async_msg_3(phone, NET_SOCKET_CLOSE, (sysarg_t) socket_id, 0,
+		
+		exch = async_exchange_begin(sess);
+		async_msg_3(exch, NET_SOCKET_CLOSE, (sysarg_t) socket_id, 0,
 		    service);
+		async_exchange_end(exch);
+		
 		return rc;
 	}
@@ -538,8 +528,10 @@
 
 	/* Request the message */
-	message_id = async_send_3(socket->phone, message,
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	message_id = async_send_3(exch, message,
 	    (sysarg_t) socket->socket_id, arg2, socket->service, NULL);
 	/* Send the address */
-	async_data_write_start(socket->phone, data, datalength);
+	async_data_write_start(exch, data, datalength);
+	async_exchange_end(exch);
 
 	fibril_rwlock_read_unlock(&socket_globals.lock);
@@ -598,6 +590,8 @@
 
 	/* Request listen backlog change */
-	result = (int) async_req_3_0(socket->phone, NET_SOCKET_LISTEN,
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	result = (int) async_req_3_0(exch, NET_SOCKET_LISTEN,
 	    (sysarg_t) socket->socket_id, (sysarg_t) backlog, socket->service);
+	async_exchange_end(exch);
 
 	fibril_rwlock_read_unlock(&socket_globals.lock);
@@ -669,5 +663,5 @@
 		return socket_id;
 	}
-	socket_initialize(new_socket, socket_id, socket->phone,
+	socket_initialize(new_socket, socket_id, socket->sess,
 	    socket->service);
 	result = sockets_add(socket_get_sockets(), new_socket->socket_id,
@@ -681,10 +675,13 @@
 
 	/* Request accept */
-	message_id = async_send_5(socket->phone, NET_SOCKET_ACCEPT,
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	message_id = async_send_5(exch, NET_SOCKET_ACCEPT,
 	    (sysarg_t) socket->socket_id, 0, socket->service, 0,
 	    new_socket->socket_id, &answer);
 
 	/* Read address */
-	async_data_read_start(socket->phone, cliaddr, *addrlen);
+	async_data_read_start(exch, cliaddr, *addrlen);
+	async_exchange_end(exch);
+	
 	fibril_rwlock_write_unlock(&socket_globals.lock);
 	async_wait_for(message_id, &ipc_result);
@@ -749,5 +746,5 @@
 	dyn_fifo_destroy(&socket->received);
 	dyn_fifo_destroy(&socket->accepted);
-	sockets_exclude(socket_get_sockets(), socket->socket_id);
+	sockets_exclude(socket_get_sockets(), socket->socket_id, free);
 }
 
@@ -780,6 +777,9 @@
 
 	/* Request close */
-	rc = (int) async_req_3_0(socket->phone, NET_SOCKET_CLOSE,
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	rc = (int) async_req_3_0(exch, NET_SOCKET_CLOSE,
 	    (sysarg_t) socket->socket_id, 0, socket->service);
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&socket_globals.lock);
@@ -853,5 +853,7 @@
 
 	/* Request send */
-	message_id = async_send_5(socket->phone, message,
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	
+	message_id = async_send_5(exch, message,
 	    (sysarg_t) socket->socket_id,
 	    (fragments == 1 ? datalength : socket->data_fragment_size),
@@ -860,11 +862,11 @@
 	/* Send the address if given */
 	if (!toaddr ||
-	    (async_data_write_start(socket->phone, toaddr, addrlen) == EOK)) {
+	    (async_data_write_start(exch, toaddr, addrlen) == EOK)) {
 		if (fragments == 1) {
 			/* Send all if only one fragment */
-			async_data_write_start(socket->phone, data, datalength);
+			async_data_write_start(exch, data, datalength);
 		} else {
 			/* Send the first fragment */
-			async_data_write_start(socket->phone, data,
+			async_data_write_start(exch, data,
 			    socket->data_fragment_size - socket->header_size);
 			data = ((const uint8_t *) data) +
@@ -873,5 +875,5 @@
 			/* Send the middle fragments */
 			while (--fragments > 1) {
-				async_data_write_start(socket->phone, data,
+				async_data_write_start(exch, data,
 				    socket->data_fragment_size);
 				data = ((const uint8_t *) data) +
@@ -880,9 +882,11 @@
 
 			/* Send the last fragment */
-			async_data_write_start(socket->phone, data,
+			async_data_write_start(exch, data,
 			    (datalength + socket->header_size) %
 			    socket->data_fragment_size);
 		}
 	}
+	
+	async_exchange_end(exch);
 
 	async_wait_for(message_id, &result);
@@ -1026,4 +1030,6 @@
 		return 0;
 	}
+	
+	async_exch_t *exch = async_exchange_begin(socket->sess);
 
 	/* Prepare lengths if more fragments */
@@ -1038,5 +1044,5 @@
 
 		/* Request packet data */
-		message_id = async_send_4(socket->phone, message,
+		message_id = async_send_4(exch, message,
 		    (sysarg_t) socket->socket_id, 0, socket->service,
 		    (sysarg_t) flags, &answer);
@@ -1044,8 +1050,8 @@
 		/* Read the address if desired */
 		if(!fromaddr ||
-		    (async_data_read_start(socket->phone, fromaddr,
+		    (async_data_read_start(exch, fromaddr,
 		    *addrlen) == EOK)) {
 			/* Read the fragment lengths */
-			if (async_data_read_start(socket->phone, lengths,
+			if (async_data_read_start(exch, lengths,
 			    sizeof(int) * (fragments + 1)) == EOK) {
 				if (lengths[fragments] <= datalength) {
@@ -1054,6 +1060,5 @@
 					for (index = 0; index < fragments;
 					    ++index) {
-						async_data_read_start(
-						    socket->phone, data,
+						async_data_read_start(exch, data,
 						    lengths[index]);
 						data = ((uint8_t *) data) +
@@ -1067,5 +1072,5 @@
 	} else { /* fragments == 1 */
 		/* Request packet data */
-		message_id = async_send_4(socket->phone, message,
+		message_id = async_send_4(exch, message,
 		    (sysarg_t) socket->socket_id, 0, socket->service,
 		    (sysarg_t) flags, &answer);
@@ -1073,10 +1078,11 @@
 		/* Read the address if desired */
 		if (!fromaddr ||
-		    (async_data_read_start(socket->phone, fromaddr,
-		        *addrlen) == EOK)) {
+		    (async_data_read_start(exch, fromaddr, *addrlen) == EOK)) {
 			/* Read all if only one fragment */
-			async_data_read_start(socket->phone, data, datalength);
+			async_data_read_start(exch, data, datalength);
 		}
 	}
+	
+	async_exchange_end(exch);
 
 	async_wait_for(message_id, &ipc_result);
@@ -1190,14 +1196,18 @@
 
 	/* Request option value */
-	message_id = async_send_3(socket->phone, NET_SOCKET_GETSOCKOPT,
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	
+	message_id = async_send_3(exch, NET_SOCKET_GETSOCKOPT,
 	    (sysarg_t) socket->socket_id, (sysarg_t) optname, socket->service,
 	    NULL);
 
 	/* Read the length */
-	if (async_data_read_start(socket->phone, optlen,
+	if (async_data_read_start(exch, optlen,
 	    sizeof(*optlen)) == EOK) {
 		/* Read the value */
-		async_data_read_start(socket->phone, value, *optlen);
-	}
+		async_data_read_start(exch, value, *optlen);
+	}
+	
+	async_exchange_end(exch);
 
 	fibril_rwlock_read_unlock(&socket_globals.lock);
Index: uspace/lib/c/generic/ns.c
===================================================================
--- uspace/lib/c/generic/ns.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/ns.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <ns.h>
+#include <ipc/ns.h>
+#include <async.h>
+#include <macros.h>
+#include "private/ns.h"
+
+int service_register(sysarg_t service)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	int rc = async_connect_to_me(exch, service, 0, 0, NULL, NULL);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+async_sess_t *service_connect(exch_mgmt_t mgmt, sysarg_t service, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	async_sess_t *sess =
+	    async_connect_me_to(mgmt, exch, service, arg2, arg3);
+	async_exchange_end(exch);
+	
+	return sess;
+}
+
+async_sess_t *service_connect_blocking(exch_mgmt_t mgmt, sysarg_t service,
+    sysarg_t arg2, sysarg_t arg3)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	async_sess_t *sess =
+	    async_connect_me_to_blocking(mgmt, exch, service, arg2, arg3);
+	async_exchange_end(exch);
+	
+	return sess;
+}
+
+int ns_ping(void)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	int rc = async_req_0_0(exch, NS_PING);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+int ns_intro(task_id_t id)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	int rc = async_req_2_0(exch, NS_ID_INTRO, LOWER32(id), UPPER32(id));
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/ns_obsolete.c
===================================================================
--- uspace/lib/c/generic/ns_obsolete.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/ns_obsolete.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <async_obsolete.h>
+#include <ns_obsolete.h>
+#include <abi/ipc/methods.h>
+
+int service_obsolete_connect(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
+{
+	return async_obsolete_connect_me_to(PHONE_NS, service, arg2, arg3);
+}
+
+int service_obsolete_connect_blocking(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
+{
+	return async_obsolete_connect_me_to_blocking(PHONE_NS, service, arg2, arg3);
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/async.h
===================================================================
--- uspace/lib/c/generic/private/async.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/private/async.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,8 +36,58 @@
 #define LIBC_PRIVATE_ASYNC_H_
 
+#include <async.h>
 #include <adt/list.h>
 #include <fibril.h>
+#include <fibril_synch.h>
 #include <sys/time.h>
 #include <bool.h>
+
+/** Session data */
+struct _async_sess {
+	/** List of inactive exchanges */
+	list_t exch_list;
+	
+	/** Exchange management style */
+	exch_mgmt_t mgmt;
+	
+	/** Session identification */
+	int phone;
+	
+	/** First clone connection argument */
+	sysarg_t arg1;
+	
+	/** Second clone connection argument */
+	sysarg_t arg2;
+	
+	/** Third clone connection argument */
+	sysarg_t arg3;
+	
+	/** Exchange mutex */
+	fibril_mutex_t mutex;
+	
+	/** Number of opened exchanges */
+	atomic_t refcnt;
+	
+	/** Mutex for stateful connections */
+	fibril_mutex_t remote_state_mtx;
+	
+	/** Data for stateful connections */
+	void *remote_state_data;
+};
+
+/** Exchange data */
+struct _async_exch {
+	/** Link into list of inactive exchanges */
+	link_t sess_link;
+	
+	/** Link into global list of inactive exchanges */
+	link_t global_link;
+	
+	/** Session pointer */
+	async_sess_t *sess;
+	
+	/** Exchange identification */
+	int phone;
+};
 
 /** Structures of this type are used to track the timeout events. */
@@ -79,6 +129,20 @@
 } awaiter_t;
 
+/** Message data */
+typedef struct {
+	awaiter_t wdata;
+	
+	/** If reply was received. */
+	bool done;
+	
+	/** Pointer to where the answer data is stored. */
+	ipc_call_t *dataptr;
+	
+	sysarg_t retval;
+} amsg_t;
+
 extern void __async_init(void);
 extern void async_insert_timeout(awaiter_t *);
+extern void reply_received(void *, int, ipc_call_t *);
 
 #endif
Index: pace/lib/c/generic/private/async_sess.h
===================================================================
--- uspace/lib/c/generic/private/async_sess.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,43 +1,0 @@
-/*
- * Copyright (c) 2011 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.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_PRIVATE_ASYNC_SESS_H_
-#define LIBC_PRIVATE_ASYNC_SESS_H_
-
-extern void __async_sess_init(void);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/generic/private/io.h
===================================================================
--- uspace/lib/c/generic/private/io.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/private/io.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,7 +36,5 @@
 #define LIBC_PRIVATE_IO_H_
 
-#include <vfs/vfs.h>
-
-extern void __stdio_init(int filc, fdi_node_t *filv[]);
+extern void __stdio_init(int);
 extern void __stdio_done(void);
 
Index: uspace/lib/c/generic/private/loader.h
===================================================================
--- uspace/lib/c/generic/private/loader.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/private/loader.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_LOADER_H_
+#define LIBC_PRIVATE_LOADER_H_
+
+#include <loader/loader.h>
+
+/** Abstraction of a loader connection */
+struct loader {
+	/** Session to the loader. */
+	async_sess_t *sess;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/ns.h
===================================================================
--- uspace/lib/c/generic/private/ns.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/private/ns.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_NS_H_
+#define LIBC_PRIVATE_NS_H_
+
+#include <async.h>
+
+extern async_sess_t *session_ns;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/stdio.h
===================================================================
--- uspace/lib/c/generic/private/stdio.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/private/stdio.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_STDIO_H_
+#define LIBC_PRIVATE_STDIO_H_
+
+#include <adt/list.h>
+#include <stdio.h>
+#include <async.h>
+
+struct _IO_FILE {
+	/** Linked list pointer. */
+	link_t link;
+	
+	/** Underlying file descriptor. */
+	int fd;
+	
+	/** Error indicator. */
+	int error;
+	
+	/** End-of-file indicator. */
+	int eof;
+	
+	/** Klog indicator */
+	int klog;
+	
+	/** Session to the file provider */
+	async_sess_t *sess;
+	
+	/**
+	 * Non-zero if the stream needs sync on fflush(). XXX change
+	 * console semantics so that sync is not needed.
+	 */
+	int need_sync;
+	
+	/** Buffering type */
+	enum _buffer_type btype;
+	
+	/** Buffer */
+	uint8_t *buf;
+	
+	/** Buffer size */
+	size_t buf_size;
+	
+	/** Buffer state */
+	enum _buffer_state buf_state;
+	
+	/** Buffer I/O pointer */
+	uint8_t *buf_head;
+	
+	/** Points to end of occupied space when in read mode. */
+	uint8_t *buf_tail;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/thread.h
===================================================================
--- uspace/lib/c/generic/private/thread.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/private/thread.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,5 +36,5 @@
 #define LIBC_PRIVATE_THREAD_H_
 
-#include <kernel/proc/uarg.h>
+#include <abi/proc/uarg.h>
 
 extern void __thread_entry(void);
Index: uspace/lib/c/generic/rtld/dynamic.c
===================================================================
--- uspace/lib/c/generic/rtld/dynamic.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/rtld/dynamic.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,142 @@
+/*
+ * 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 rtld rtld
+ * @brief
+ * @{
+ */ 
+/**
+ * @file
+ */
+
+#include <stdio.h>
+
+#include <rtld/elf_dyn.h>
+#include <rtld/dynamic.h>
+#include <rtld/rtld.h>
+#include <rtld/rtld_debug.h>
+
+void dynamic_parse(elf_dyn_t *dyn_ptr, size_t bias, dyn_info_t *info)
+{
+	elf_dyn_t *dp = dyn_ptr;
+
+	void *d_ptr;
+	elf_word d_val;
+
+	elf_word soname_idx;
+	elf_word rpath_idx;
+
+	DPRINTF("memset\n");
+	memset(info, 0, sizeof(dyn_info_t));
+
+	soname_idx = 0;
+	rpath_idx = 0;
+
+	DPRINTF("pass 1\n");
+	while (dp->d_tag != DT_NULL) {
+		d_ptr = (void *)((uint8_t *)dp->d_un.d_ptr + bias);
+		d_val = dp->d_un.d_val;
+		DPRINTF("tag=%u ptr=0x%x val=%u\n", (unsigned)dp->d_tag,
+			(unsigned)d_ptr, (unsigned)d_val);
+
+		switch (dp->d_tag) {
+
+		case DT_PLTRELSZ:	info->plt_rel_sz = d_val; break;
+		case DT_PLTGOT:		info->plt_got = d_ptr; break;
+		case DT_HASH:		info->hash = d_ptr; break;
+		case DT_STRTAB:		info->str_tab = d_ptr; break;
+		case DT_SYMTAB:		info->sym_tab = d_ptr; break;
+		case DT_RELA:		info->rela = d_ptr; break;
+		case DT_RELASZ:		info->rela_sz = d_val; break;
+		case DT_RELAENT:	info->rela_ent = d_val; break;
+		case DT_STRSZ:		info->str_sz = d_val; break;
+		case DT_SYMENT:		info->sym_ent = d_val; break;
+		case DT_INIT:		info->init = d_ptr; break;
+		case DT_FINI:		info->fini = d_ptr; break;
+		case DT_SONAME:		soname_idx = d_val; break;
+		case DT_RPATH:		rpath_idx = d_val; break;
+		case DT_SYMBOLIC:	info->symbolic = true; break;
+		case DT_REL:		info->rel = d_ptr; break;
+		case DT_RELSZ:		info->rel_sz = d_val; break;
+		case DT_RELENT:		info->rel_ent = d_val; break;
+		case DT_PLTREL:		info->plt_rel = d_val; break;
+		case DT_TEXTREL:	info->text_rel = true; break;
+		case DT_JMPREL:		info->jmp_rel = d_ptr; break;
+		case DT_BIND_NOW:	info->bind_now = true; break;
+
+		default:
+			if (dp->d_tag >= DT_LOPROC && dp->d_tag <= DT_HIPROC)
+				dyn_parse_arch(dp, bias, info);
+			break;
+		}
+
+		++dp;
+	}
+
+	info->soname = info->str_tab + soname_idx;
+	info->rpath = info->str_tab + rpath_idx;
+
+	/* This will be useful for parsing dependencies later */
+	info->dynamic = dyn_ptr;
+
+	DPRINTF("str_tab=0x%x, soname_idx=0x%x, soname=0x%x\n",
+		(uintptr_t)info->soname, soname_idx, (uintptr_t)info->soname);
+	DPRINTF("soname='%s'\n", info->soname);
+	DPRINTF("rpath='%s'\n", info->rpath);
+	DPRINTF("hash=0x%x\n", (uintptr_t)info->hash);
+	DPRINTF("dt_rela=0x%x\n", (uintptr_t)info->rela);
+	DPRINTF("dt_rela_sz=0x%x\n", (uintptr_t)info->rela_sz);
+	DPRINTF("dt_rel=0x%x\n", (uintptr_t)info->rel);
+	DPRINTF("dt_rel_sz=0x%x\n", (uintptr_t)info->rel_sz);
+
+	/*
+	 * Now that we have a pointer to the string table,
+	 * we can parse DT_NEEDED fields (which contain offsets into it).
+	 */
+
+	DPRINTF("pass 2\n");
+	dp = dyn_ptr;
+	while (dp->d_tag != DT_NULL) {
+		d_val = dp->d_un.d_val;
+
+		switch (dp->d_tag) {
+		case DT_NEEDED:
+			/* Assume just for now there's only one dependency */
+			info->needed = info->str_tab + d_val;
+			DPRINTF("needed:'%s'\n", info->needed);
+			break;
+
+		default: break;
+		}
+
+		++dp;
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/rtld/module.c
===================================================================
--- uspace/lib/c/generic/rtld/module.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/rtld/module.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,272 @@
+/*
+ * 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 rtld rtld
+ * @brief
+ * @{
+ */ 
+/**
+ * @file
+ */
+
+#include <adt/list.h>
+#include <elf/elf_load.h>
+#include <fcntl.h>
+#include <loader/pcb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rtld/rtld.h>
+#include <rtld/rtld_debug.h>
+#include <rtld/dynamic.h>
+#include <rtld/rtld_arch.h>
+#include <rtld/module.h>
+
+/** (Eagerly) process all relocation tables in a module.
+ *
+ * Currently works as if LD_BIND_NOW was specified.
+ */
+void module_process_relocs(module_t *m)
+{
+	DPRINTF("module_process_relocs('%s')\n", m->dyn.soname);
+
+	/* Do not relocate twice. */
+	if (m->relocated) return;
+
+	module_process_pre_arch(m);
+
+	if (m->dyn.plt_rel == DT_REL) {
+		DPRINTF("table type DT_REL\n");
+		if (m->dyn.rel != NULL) {
+			DPRINTF("non-empty\n");
+			rel_table_process(m, m->dyn.rel, m->dyn.rel_sz);
+		}
+		/* FIXME: this seems wrong */
+		if (m->dyn.jmp_rel != NULL) {
+		DPRINTF("table type jmp-rel\n");
+			DPRINTF("non-empty\n");
+			rel_table_process(m, m->dyn.jmp_rel, m->dyn.plt_rel_sz);
+		}
+	} else { /* (m->dyn.plt_rel == DT_RELA) */
+		DPRINTF("table type DT_RELA\n");
+		if (m->dyn.rela != NULL) {
+			DPRINTF("non-empty\n");
+			rela_table_process(m, m->dyn.rela, m->dyn.rela_sz);
+		}
+	}
+
+	m->relocated = true;
+}
+
+/** Find module structure by soname/pathname.
+ *
+ * Used primarily to see if a module has already been loaded.
+ * Modules are compared according to their soname, i.e. possible
+ * path components are ignored.
+ */
+module_t *module_find(const char *name)
+{
+	module_t *m;
+	const char *p, *soname;
+
+	DPRINTF("module_find('%s')\n", name);
+
+	/*
+	 * If name contains slashes, treat it as a pathname and
+	 * construct soname by chopping off the path. Otherwise
+	 * treat it as soname.
+	 */
+	p = str_rchr(name, '/');
+	soname = p ? (p + 1) : name;
+
+	/* Traverse list of all modules. Not extremely fast, but simple */
+	list_foreach(runtime_env->modules, cur) {
+		DPRINTF("cur = %p\n", cur);
+		m = list_get_instance(cur, module_t, modules_link);
+		if (str_cmp(m->dyn.soname, soname) == 0) {
+			return m; /* Found */
+		}
+	}
+	
+	return NULL; /* Not found */
+}
+
+#define NAME_BUF_SIZE 64
+
+/** Load a module.
+ *
+ * Currently this trivially tries to load '/<name>'.
+ */
+module_t *module_load(const char *name)
+{
+	elf_info_t info;
+	char name_buf[NAME_BUF_SIZE];
+	module_t *m;
+	int rc;
+	
+	m = malloc(sizeof(module_t));
+	if (!m) {
+		printf("malloc failed\n");
+		exit(1);
+	}
+
+	if (str_size(name) > NAME_BUF_SIZE - 2) {
+		printf("soname too long. increase NAME_BUF_SIZE\n");
+		exit(1);
+	}
+
+	/* Prepend soname with '/lib/' */
+	str_cpy(name_buf, NAME_BUF_SIZE, "/lib/");
+	str_cpy(name_buf + 5, NAME_BUF_SIZE - 5, name);
+
+	/* FIXME: need to real allocation of address space */
+	m->bias = runtime_env->next_bias;
+	runtime_env->next_bias += 0x100000;
+
+	DPRINTF("filename:'%s'\n", name_buf);
+	DPRINTF("load '%s' at 0x%x\n", name_buf, m->bias);
+
+	rc = elf_load_file(name_buf, m->bias, ELDF_RW, &info);
+	if (rc != EE_OK) {
+		printf("Failed to load '%s'\n", name_buf);
+		exit(1);
+	}
+
+	if (info.dynamic == NULL) {
+		printf("Error: '%s' is not a dynamically-linked object.\n",
+		    name_buf);
+		exit(1);
+	}
+
+	/* Pending relocation. */
+	m->relocated = false;
+
+	DPRINTF("parse dynamic section\n");
+	/* Parse ELF .dynamic section. Store info to m->dyn. */
+	dynamic_parse(info.dynamic, m->bias, &m->dyn);
+
+	/* Insert into the list of loaded modules */
+	list_append(&m->modules_link, &runtime_env->modules);
+
+	return m;
+}
+
+/** Load all modules on which m (transitively) depends.
+ */
+void module_load_deps(module_t *m)
+{
+	elf_dyn_t *dp;
+	char *dep_name;
+	module_t *dm;
+	size_t n, i;
+
+	DPRINTF("module_load_deps('%s')\n", m->dyn.soname);
+
+	/* Count direct dependencies */
+	
+	dp = m->dyn.dynamic;
+	n = 0;
+
+	while (dp->d_tag != DT_NULL) {
+		if (dp->d_tag == DT_NEEDED) ++n;
+		++dp;
+	}
+
+	/* Create an array of pointers to direct dependencies */
+
+	m->n_deps = n;
+
+	if (n == 0) {
+		/* There are no dependencies, so we are done. */
+		m->deps = NULL;
+		return;
+	}
+
+	m->deps = malloc(n * sizeof(module_t *));
+	if (!m->deps) {
+		printf("malloc failed\n");
+		exit(1);
+	}
+
+	i = 0; /* Current dependency index */
+	dp = m->dyn.dynamic;
+
+	while (dp->d_tag != DT_NULL) {
+		if (dp->d_tag == DT_NEEDED) {
+			dep_name = m->dyn.str_tab + dp->d_un.d_val;
+
+			DPRINTF("%s needs %s\n", m->dyn.soname, dep_name);
+			dm = module_find(dep_name);
+			if (!dm) {
+				dm = module_load(dep_name);
+				module_load_deps(dm);
+			}
+
+			/* Save into deps table */
+			m->deps[i++] = dm;
+		}
+		++dp;
+	}
+}
+
+/** Process relocations in modules.
+ *
+ * Processes relocations in @a start and all its dependencies.
+ * Modules that have already been relocated are unaffected.
+ *
+ * @param	start	The module where to start from.
+ */
+void modules_process_relocs(module_t *start)
+{
+	module_t *m;
+
+	list_foreach(runtime_env->modules, cur) {
+		m = list_get_instance(cur, module_t, modules_link);
+
+		/* Skip rtld, since it has already been processed */
+		if (m != &runtime_env->rtld) {
+			module_process_relocs(m);
+		}
+	}
+}
+
+/** Clear BFS tags of all modules.
+ */
+void modules_untag(void)
+{
+	module_t *m;
+
+	list_foreach(runtime_env->modules, cur) {
+		m = list_get_instance(cur, module_t, modules_link);
+		m->bfs_tag = false;
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/rtld/rtld.c
===================================================================
--- uspace/lib/c/generic/rtld/rtld.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/rtld/rtld.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,52 @@
+/*
+ * 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 rtld rtld
+ * @brief
+ * @{
+ */ 
+/**
+ * @file
+ */
+
+#include <rtld/rtld.h>
+
+runtime_env_t *runtime_env;
+static runtime_env_t rt_env_static;
+
+/** Initialize the loder for use in a statically-linked binary. */
+void rtld_init_static(void)
+{
+	runtime_env = &rt_env_static;
+	list_initialize(&runtime_env->modules);
+	runtime_env->next_bias = 0x2000000;
+	runtime_env->program = NULL;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/rtld/symbol.c
===================================================================
--- uspace/lib/c/generic/rtld/symbol.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/generic/rtld/symbol.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,232 @@
+/*
+ * 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 rtld rtld
+ * @brief
+ * @{
+ */ 
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <elf/elf.h>
+#include <rtld/rtld.h>
+#include <rtld/rtld_debug.h>
+#include <rtld/symbol.h>
+
+/*
+ * Hash tables are 32-bit (elf_word) even for 64-bit ELF files.
+ */
+static elf_word elf_hash(const unsigned char *name)
+{
+	elf_word h = 0, g;
+
+	while (*name) {
+		h = (h << 4) + *name++;
+		g = h & 0xf0000000;
+		if (g != 0) h ^= g >> 24;
+		h &= ~g;
+	}
+
+	return h;
+}
+
+static elf_symbol_t *def_find_in_module(const char *name, module_t *m)
+{
+	elf_symbol_t *sym_table;
+	elf_symbol_t *s, *sym;
+	elf_word nbucket;
+	/*elf_word nchain;*/
+	elf_word i;
+	char *s_name;
+	elf_word bucket;
+
+	DPRINTF("def_find_in_module('%s', %s)\n", name, m->dyn.soname);
+
+	sym_table = m->dyn.sym_tab;
+	nbucket = m->dyn.hash[0];
+	/*nchain = m->dyn.hash[1]; XXX Use to check HT range*/
+
+	bucket = elf_hash((unsigned char *)name) % nbucket;
+	i = m->dyn.hash[2 + bucket];
+
+	sym = NULL;
+	while (i != STN_UNDEF) {
+		s = &sym_table[i];
+		s_name = m->dyn.str_tab + s->st_name;
+
+		if (str_cmp(name, s_name) == 0) {
+			sym = s;
+			break;
+		}
+
+		i = m->dyn.hash[2 + nbucket + i];
+	}
+
+	if (!sym)
+		return NULL;	/* Not found */
+
+	if (sym->st_shndx == SHN_UNDEF) {
+		/* Not a definition */
+		return NULL;
+	}
+
+	return sym; /* Found */
+}
+
+/** Find the definition of a symbol in a module and its deps.
+ *
+ * Search the module dependency graph is breadth-first, beginning
+ * from the module @a start. Thus, @start and all its dependencies
+ * get searched.
+ *
+ * @param name		Name of the symbol to search for.
+ * @param start		Module in which to start the search..
+ * @param mod		(output) Will be filled with a pointer to the module 
+ *			that contains the symbol.
+ */
+elf_symbol_t *symbol_bfs_find(const char *name, module_t *start, module_t **mod)
+{
+	module_t *m, *dm;
+	elf_symbol_t *sym, *s;
+	list_t queue;
+	size_t i;
+
+	/*
+	 * Do a BFS using the queue_link and bfs_tag fields.
+	 * Vertices (modules) are tagged the moment they are inserted
+	 * into the queue. This prevents from visiting the same vertex
+	 * more times in case of circular dependencies.
+	 */
+
+	/* Mark all vertices (modules) as unvisited */	
+	modules_untag();
+
+	/* Insert root (the program) into the queue and tag it */
+	list_initialize(&queue);
+	start->bfs_tag = true;
+	list_append(&start->queue_link, &queue);
+
+	/* If the symbol is found, it will be stored in 'sym' */
+	sym = NULL;
+
+	/* While queue is not empty */
+	while (!list_empty(&queue)) {
+		/* Pop first element from the queue */
+		m = list_get_instance(list_first(&queue), module_t, queue_link);
+		list_remove(&m->queue_link);
+
+		s = def_find_in_module(name, m);
+		if (s != NULL) {
+			/* Symbol found */
+			sym = s;
+			*mod = m;
+			break;
+		}
+
+		/*
+		 * Insert m's untagged dependencies into the queue
+		 * and tag them.
+		 */
+		for (i = 0; i < m->n_deps; ++i) {
+			dm = m->deps[i];
+
+			if (dm->bfs_tag == false) {
+				dm->bfs_tag = true;
+				list_append(&dm->queue_link, &queue);
+			}
+		}
+	}
+
+	/* Empty the queue so that we leave it in a clean state */
+	while (!list_empty(&queue))
+		list_remove(list_first(&queue));
+
+	if (!sym) {
+		return NULL; /* Not found */
+	}
+
+	return sym; /* Symbol found */
+}
+
+
+/** Find the definition of a symbol..
+ *
+ * By definition in System V ABI, if module origin has the flag DT_SYMBOLIC,
+ * origin is searched first. Otherwise, or if the symbol hasn't been found,
+ * the module dependency graph is searched breadth-first, beginning
+ * from the executable program.
+ *
+ * @param name		Name of the symbol to search for.
+ * @param origin	Module in which the dependency originates.
+ * @param mod		(output) Will be filled with a pointer to the module 
+ *			that contains the symbol.
+ */
+elf_symbol_t *symbol_def_find(const char *name, module_t *origin, module_t **mod)
+{
+	elf_symbol_t *s;
+
+	if (origin->dyn.symbolic) {
+		/* 
+		 * Origin module has a DT_SYMBOLIC flag.
+		 * Try this module first
+		 */
+		 s = def_find_in_module(name, origin);
+		 if (s != NULL) {
+			/* Found */
+			*mod = origin;
+			return s;
+		 }
+	}
+
+	/* Not DT_SYMBOLIC or no match. Now try other locations. */
+
+	if (runtime_env->program) {
+		/* Program is dynamic -- start with program as root. */
+		return symbol_bfs_find(name, runtime_env->program, mod);
+	} else {
+		/* Program is static -- start with @a origin as root. */
+		return symbol_bfs_find(name, origin, mod);
+	}
+}
+
+void *symbol_get_addr(elf_symbol_t *sym, module_t *m)
+{
+	if (sym->st_shndx == SHN_ABS) {
+		/* Do not add bias to absolute symbols */
+		return (void *) sym->st_value;
+	} else {
+		return (void *) (sym->st_value + m->bias);
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/stacktrace.c
===================================================================
--- uspace/lib/c/generic/stacktrace.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/stacktrace.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -61,9 +61,11 @@
 	stacktrace_prepare();
 	stacktrace_print_fp_pc(stacktrace_fp_get(), stacktrace_pc_get());
+	
 	/*
 	 * Prevent the tail call optimization of the previous call by
 	 * making it a non-tail call.
 	 */
-	(void) stacktrace_fp_get();
+	
+	printf("-- end of stack trace --\n");
 }
 
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/str.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -540,5 +540,71 @@
 
 	dstr_size = str_size(dest);
+	if (dstr_size >= size)
+		return;
+	
 	str_cpy(dest + dstr_size, size - dstr_size, src);
+}
+
+/** Convert space-padded ASCII to string.
+ *
+ * Common legacy text encoding in hardware is 7-bit ASCII fitted into
+ * a fixed-with byte buffer (bit 7 always zero), right-padded with spaces
+ * (ASCII 0x20). Convert space-padded ascii to string representation.
+ *
+ * If the text does not fit into the destination buffer, the function converts
+ * as many characters as possible and returns EOVERFLOW.
+ *
+ * If the text contains non-ASCII bytes (with bit 7 set), the whole string is
+ * converted anyway and invalid characters are replaced with question marks
+ * (U_SPECIAL) and the function returns EIO.
+ *
+ * Regardless of return value upon return @a dest will always be well-formed.
+ *
+ * @param dest		Destination buffer
+ * @param size		Size of destination buffer
+ * @param src		Space-padded ASCII.
+ * @param n		Size of the source buffer in bytes.
+ *
+ * @return		EOK on success, EOVERFLOW if the text does not fit
+ *			destination buffer, EIO if the text contains
+ *			non-ASCII bytes.
+ */
+int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n)
+{
+	size_t sidx;
+	size_t didx;
+	size_t dlast;
+	uint8_t byte;
+	int rc;
+	int result;
+
+	/* There must be space for a null terminator in the buffer. */
+	assert(size > 0);
+	result = EOK;
+
+	didx = 0;
+	dlast = 0;
+	for (sidx = 0; sidx < n; ++sidx) {
+		byte = src[sidx];
+		if (!ascii_check(byte)) {
+			byte = U_SPECIAL;
+			result = EIO;
+		}
+
+		rc = chr_encode(byte, dest, &didx, size - 1);
+		if (rc != EOK) {
+			assert(rc == EOVERFLOW);
+			dest[didx] = '\0';
+			return rc;
+		}
+
+		/* Remember dest index after last non-empty character */
+		if (byte != 0x20)
+			dlast = didx;
+	}
+
+	/* Terminate string after last non-empty character */
+	dest[dlast] = '\0';
+	return result;
 }
 
@@ -1215,21 +1281,21 @@
 void order_suffix(const uint64_t val, uint64_t *rv, char *suffix)
 {
-	if (val > 10000000000000000000ULL) {
-		*rv = val / 1000000000000000000ULL;
+	if (val > UINT64_C(10000000000000000000)) {
+		*rv = val / UINT64_C(1000000000000000000);
 		*suffix = 'Z';
-	} else if (val > 1000000000000000000ULL) {
-		*rv = val / 1000000000000000ULL;
+	} else if (val > UINT64_C(1000000000000000000)) {
+		*rv = val / UINT64_C(1000000000000000);
 		*suffix = 'E';
-	} else if (val > 1000000000000000ULL) {
-		*rv = val / 1000000000000ULL;
+	} else if (val > UINT64_C(1000000000000000)) {
+		*rv = val / UINT64_C(1000000000000);
 		*suffix = 'T';
-	} else if (val > 1000000000000ULL) {
-		*rv = val / 1000000000ULL;
+	} else if (val > UINT64_C(1000000000000)) {
+		*rv = val / UINT64_C(1000000000);
 		*suffix = 'G';
-	} else if (val > 1000000000ULL) {
-		*rv = val / 1000000ULL;
+	} else if (val > UINT64_C(1000000000)) {
+		*rv = val / UINT64_C(1000000);
 		*suffix = 'M';
-	} else if (val > 1000000ULL) {
-		*rv = val / 1000ULL;
+	} else if (val > UINT64_C(1000000)) {
+		*rv = val / UINT64_C(1000);
 		*suffix = 'k';
 	} else {
@@ -1239,4 +1305,31 @@
 }
 
+void bin_order_suffix(const uint64_t val, uint64_t *rv, const char **suffix,
+    bool fixed)
+{
+	if (val > UINT64_C(1152921504606846976)) {
+		*rv = val / UINT64_C(1125899906842624);
+		*suffix = "EiB";
+	} else if (val > UINT64_C(1125899906842624)) {
+		*rv = val / UINT64_C(1099511627776);
+		*suffix = "TiB";
+	} else if (val > UINT64_C(1099511627776)) {
+		*rv = val / UINT64_C(1073741824);
+		*suffix = "GiB";
+	} else if (val > UINT64_C(1073741824)) {
+		*rv = val / UINT64_C(1048576);
+		*suffix = "MiB";
+	} else if (val > UINT64_C(1048576)) {
+		*rv = val / UINT64_C(1024);
+		*suffix = "KiB";
+	} else {
+		*rv = val;
+		if (fixed)
+			*suffix = "B  ";
+		else
+			*suffix = "B";
+	}
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/str_error.c
===================================================================
--- uspace/lib/c/generic/str_error.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/str_error.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,4 +33,5 @@
  */
 
+#include <errno.h>
 #include <str_error.h>
 #include <stdio.h>
@@ -63,10 +64,25 @@
 static fibril_local char noerr[NOERR_LEN];
 
-const char *str_error(const int errno)
+const char *str_error(const int e)
 {
-	if ((errno <= 0) && (errno >= MIN_ERRNO))
-		return err_desc[-errno];
+	if ((e <= 0) && (e >= MIN_ERRNO))
+		return err_desc[-e];
 	
-	snprintf(noerr, NOERR_LEN, "Unkown error code %d", errno);
+	/* Ad hoc descriptions of error codes interesting for USB. */
+	// FIXME: integrate these as first-class error values
+	switch (e) {
+		case EBADCHECKSUM:
+			return "Bad checksum";
+		case ESTALL:
+			return "Operation stalled";
+		case EAGAIN:
+			return "Resource temporarily unavailable";
+		case EEMPTY:
+			return "Resource is empty";
+		default:
+			break;
+	}
+
+	snprintf(noerr, NOERR_LEN, "Unkown error code %d", e);
 	return noerr;
 }
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/task.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,7 +35,4 @@
 
 #include <task.h>
-#include <libc.h>
-#include <stdlib.h>
-#include <errno.h>
 #include <loader/loader.h>
 #include <stdarg.h>
@@ -43,5 +40,11 @@
 #include <ipc/ns.h>
 #include <macros.h>
+#include <assert.h>
 #include <async.h>
+#include <errno.h>
+#include <malloc.h>
+#include <libc.h>
+#include "private/ns.h"
+#include <vfs/vfs.h>
 
 task_id_t task_get_id(void)
@@ -68,4 +71,6 @@
 int task_set_name(const char *name)
 {
+	assert(name);
+	
 	return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, str_size(name));
 }
@@ -88,23 +93,64 @@
  * loader API. Arguments are passed as a null-terminated array of strings.
  *
- * @param id 	If not NULL, the ID of the task is stored here on success.
- * @param path	Pathname of the binary to execute.
- * @param argv	Command-line arguments.
- *
- * @return	Zero on success or negative error code.
+ * @param id   If not NULL, the ID of the task is stored here on success.
+ * @param path Pathname of the binary to execute.
+ * @param argv Command-line arguments.
+ *
+ * @return Zero on success or negative error code.
+ *
  */
 int task_spawnv(task_id_t *id, const char *path, const char *const args[])
 {
-	loader_t *ldr;
-	task_id_t task_id;
-	int rc;
-
+	/* Send default files */
+	int *files[4];
+	int fd_stdin;
+	int fd_stdout;
+	int fd_stderr;
+	
+	if ((stdin != NULL) && (fhandle(stdin, &fd_stdin) == EOK))
+		files[0] = &fd_stdin;
+	else
+		files[0] = NULL;
+	
+	if ((stdout != NULL) && (fhandle(stdout, &fd_stdout) == EOK))
+		files[1] = &fd_stdout;
+	else
+		files[1] = NULL;
+	
+	if ((stderr != NULL) && (fhandle(stderr, &fd_stderr) == EOK))
+		files[2] = &fd_stderr;
+	else
+		files[2] = NULL;
+	
+	files[3] = NULL;
+	
+	return task_spawnvf(id, path, args, files);
+}
+
+/** Create a new task by running an executable from the filesystem.
+ *
+ * This is really just a convenience wrapper over the more complicated
+ * loader API. Arguments are passed as a null-terminated array of strings.
+ * Files are passed as null-terminated array of pointers to fdi_node_t.
+ *
+ * @param id    If not NULL, the ID of the task is stored here on success.
+ * @param path  Pathname of the binary to execute.
+ * @param argv  Command-line arguments.
+ * @param files Standard files to use.
+ *
+ * @return Zero on success or negative error code.
+ *
+ */
+int task_spawnvf(task_id_t *id, const char *path, const char *const args[],
+    int *const files[])
+{
 	/* Connect to a program loader. */
-	ldr = loader_connect();
+	loader_t *ldr = loader_connect();
 	if (ldr == NULL)
 		return EREFUSED;
 	
 	/* Get task ID. */
-	rc = loader_get_task_id(ldr, &task_id);
+	task_id_t task_id;
+	int rc = loader_get_task_id(ldr, &task_id);
 	if (rc != EOK)
 		goto error;
@@ -125,27 +171,5 @@
 		goto error;
 	
-	/* Send default files */
-	fdi_node_t *files[4];
-	fdi_node_t stdin_node;
-	fdi_node_t stdout_node;
-	fdi_node_t stderr_node;
-	
-	if ((stdin != NULL) && (fnode(stdin, &stdin_node) == EOK))
-		files[0] = &stdin_node;
-	else
-		files[0] = NULL;
-	
-	if ((stdout != NULL) && (fnode(stdout, &stdout_node) == EOK))
-		files[1] = &stdout_node;
-	else
-		files[1] = NULL;
-	
-	if ((stderr != NULL) && (fnode(stderr, &stderr_node) == EOK))
-		files[2] = &stderr_node;
-	else
-		files[2] = NULL;
-	
-	files[3] = NULL;
-	
+	/* Send files */
 	rc = loader_set_files(ldr, files);
 	if (rc != EOK)
@@ -163,6 +187,4 @@
 	
 	/* Success */
-	free(ldr);
-	
 	if (id != NULL)
 		*id = task_id;
@@ -173,5 +195,4 @@
 	/* Error exit */
 	loader_abort(ldr);
-	free(ldr);
 	return rc;
 }
@@ -182,19 +203,20 @@
  * loader API. Arguments are passed as a null-terminated list of arguments.
  *
- * @param id 	If not NULL, the ID of the task is stored here on success.
- * @param path	Pathname of the binary to execute.
- * @param ...	Command-line arguments.
- *
- * @return	Zero on success or negative error code.
+ * @param id   If not NULL, the ID of the task is stored here on success.
+ * @param path Pathname of the binary to execute.
+ * @param ...  Command-line arguments.
+ *
+ * @return Zero on success or negative error code.
+ *
  */
 int task_spawnl(task_id_t *task_id, const char *path, ...)
 {
+	/* Count the number of arguments. */
+	
 	va_list ap;
-	int rc, cnt;
 	const char *arg;
 	const char **arglist;
-
-	/* Count the number of arguments. */
-	cnt = 0;
+	int cnt = 0;
+	
 	va_start(ap, path);
 	do {
@@ -203,10 +225,10 @@
 	} while (arg != NULL);
 	va_end(ap);
-
+	
 	/* Allocate argument list. */
 	arglist = malloc(cnt * sizeof(const char *));
 	if (arglist == NULL)
 		return ENOMEM;
-
+	
 	/* Fill in arguments. */
 	cnt = 0;
@@ -217,8 +239,8 @@
 	} while (arg != NULL);
 	va_end(ap);
-
+	
 	/* Spawn task. */
-	rc = task_spawnv(task_id, path, arglist);
-
+	int rc = task_spawnv(task_id, path, arglist);
+	
 	/* Free argument list. */
 	free(arglist);
@@ -228,12 +250,16 @@
 int task_wait(task_id_t id, task_exit_t *texit, int *retval)
 {
+	assert(texit);
+	assert(retval);
+	
+	async_exch_t *exch = async_exchange_begin(session_ns);
 	sysarg_t te, rv;
-	int rc;
-
-	rc = (int) async_req_2_2(PHONE_NS, NS_TASK_WAIT, LOWER32(id),
+	int rc = (int) async_req_2_2(exch, NS_TASK_WAIT, LOWER32(id),
 	    UPPER32(id), &te, &rv);
+	async_exchange_end(exch);
+	
 	*texit = te;
 	*retval = rv;
-
+	
 	return rc;
 }
@@ -241,5 +267,9 @@
 int task_retval(int val)
 {
-	return (int) async_req_1_0(PHONE_NS, NS_RETVAL, val);
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	int rc = (int) async_req_1_0(exch, NS_RETVAL, val);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
Index: uspace/lib/c/generic/thread.c
===================================================================
--- uspace/lib/c/generic/thread.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/thread.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 #include <stdlib.h>
 #include <libarch/faddr.h>
-#include <kernel/proc/uarg.h>
+#include <abi/proc/uarg.h>
 #include <fibril.h>
 #include <str.h>
@@ -44,5 +44,5 @@
 
 #ifndef THREAD_INITIAL_STACK_PAGES_NO
-#define THREAD_INITIAL_STACK_PAGES_NO 1
+#define THREAD_INITIAL_STACK_PAGES_NO	2 
 #endif
 
Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/time.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,5 +36,5 @@
 #include <time.h>
 #include <bool.h>
-#include <arch/barrier.h>
+#include <libarch/barrier.h>
 #include <macros.h>
 #include <errno.h>
@@ -207,4 +207,10 @@
 }
 
+void udelay(useconds_t time)
+{
+	(void) __SYSCALL1(SYS_THREAD_UDELAY, (sysarg_t) time);
+}
+
+
 /** Wait unconditionally for specified number of seconds
  *
Index: uspace/lib/c/generic/udebug.c
===================================================================
--- uspace/lib/c/generic/udebug.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/udebug.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,102 +35,108 @@
 #include <udebug.h>
 #include <sys/types.h>
+#include <abi/ipc/methods.h>
 #include <async.h>
 
-int udebug_begin(int phoneid)
+int udebug_begin(async_sess_t *sess)
 {
-	return async_req_1_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_BEGIN);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_1_0(exch, IPC_M_DEBUG, UDEBUG_M_BEGIN);
 }
 
-int udebug_end(int phoneid)
+int udebug_end(async_sess_t *sess)
 {
-	return async_req_1_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_END);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_1_0(exch, IPC_M_DEBUG, UDEBUG_M_END);
 }
 
-int udebug_set_evmask(int phoneid, udebug_evmask_t mask)
+int udebug_set_evmask(async_sess_t *sess, udebug_evmask_t mask)
 {
-	return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_SET_EVMASK,
-		mask);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_2_0(exch, IPC_M_DEBUG, UDEBUG_M_SET_EVMASK, mask);
 }
 
-int udebug_thread_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed)
+int udebug_thread_read(async_sess_t *sess, void *buffer, size_t n,
+    size_t *copied, size_t *needed)
 {
 	sysarg_t a_copied, a_needed;
-	int rc;
-
-	rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_THREAD_READ,
-		(sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
-
-	*copied = (size_t)a_copied;
-	*needed = (size_t)a_needed;
-
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_3(exch, IPC_M_DEBUG, UDEBUG_M_THREAD_READ,
+	    (sysarg_t) buffer, n, NULL, &a_copied, &a_needed);
+	
+	*copied = (size_t) a_copied;
+	*needed = (size_t) a_needed;
+	
 	return rc;
 }
 
-int udebug_name_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed)
+int udebug_name_read(async_sess_t *sess, void *buffer, size_t n,
+    size_t *copied, size_t *needed)
 {
 	sysarg_t a_copied, a_needed;
-	int rc;
-
-	rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_NAME_READ,
-		(sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
-
-	*copied = (size_t)a_copied;
-	*needed = (size_t)a_needed;
-
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_3(exch, IPC_M_DEBUG, UDEBUG_M_NAME_READ,
+	    (sysarg_t) buffer, n, NULL, &a_copied, &a_needed);
+	
+	*copied = (size_t) a_copied;
+	*needed = (size_t) a_needed;
+	
 	return rc;
 }
 
-int udebug_areas_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed)
+int udebug_areas_read(async_sess_t *sess, void *buffer, size_t n,
+    size_t *copied, size_t *needed)
 {
 	sysarg_t a_copied, a_needed;
-	int rc;
-
-	rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_AREAS_READ,
-		(sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
-
-	*copied = (size_t)a_copied;
-	*needed = (size_t)a_needed;
-
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_3(exch, IPC_M_DEBUG, UDEBUG_M_AREAS_READ,
+	    (sysarg_t) buffer, n, NULL, &a_copied, &a_needed);
+	
+	*copied = (size_t) a_copied;
+	*needed = (size_t) a_needed;
+	
 	return rc;
 }
 
-int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n)
+int udebug_mem_read(async_sess_t *sess, void *buffer, uintptr_t addr, size_t n)
 {
-	return async_req_4_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_MEM_READ,
-	    (sysarg_t)buffer, addr, n);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_4_0(exch, IPC_M_DEBUG, UDEBUG_M_MEM_READ,
+	    (sysarg_t) buffer, addr, n);
 }
 
-int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer)
+int udebug_args_read(async_sess_t *sess, thash_t tid, sysarg_t *buffer)
 {
-	return async_req_3_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_ARGS_READ,
-	    tid, (sysarg_t)buffer);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_3_0(exch, IPC_M_DEBUG, UDEBUG_M_ARGS_READ,
+	    tid, (sysarg_t) buffer);
 }
 
-int udebug_regs_read(int phoneid, thash_t tid, void *buffer)
+int udebug_regs_read(async_sess_t *sess, thash_t tid, void *buffer)
 {
-	return async_req_3_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_REGS_READ,
-	    tid, (sysarg_t)buffer);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_3_0(exch, IPC_M_DEBUG, UDEBUG_M_REGS_READ,
+	    tid, (sysarg_t) buffer);
 }
 
-int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type,
+int udebug_go(async_sess_t *sess, thash_t tid, udebug_event_t *ev_type,
     sysarg_t *val0, sysarg_t *val1)
 {
 	sysarg_t a_ev_type;
-	int rc;
-
-	rc =  async_req_2_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_GO,
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_2_3(exch, IPC_M_DEBUG, UDEBUG_M_GO,
 	    tid, &a_ev_type, val0, val1);
-
+	
 	*ev_type = a_ev_type;
 	return rc;
 }
 
-int udebug_stop(int phoneid, thash_t tid)
+int udebug_stop(async_sess_t *sess, thash_t tid)
 {
-	return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_STOP,
-	    tid);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_2_0(exch, IPC_M_DEBUG, UDEBUG_M_STOP, tid);
 }
 
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,6 +33,7 @@
  */
 
+#include <vfs/canonify.h>
 #include <vfs/vfs.h>
-#include <vfs/canonify.h>
+#include <vfs/vfs_sess.h>
 #include <macros.h>
 #include <stdlib.h>
@@ -44,5 +45,5 @@
 #include <sys/types.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <fibril_synch.h>
@@ -50,12 +51,10 @@
 #include <assert.h>
 #include <str.h>
-#include <devmap.h>
+#include <loc.h>
 #include <ipc/vfs.h>
-#include <ipc/devmap.h>
-
-static async_sess_t vfs_session;
-
-static FIBRIL_MUTEX_INITIALIZE(vfs_phone_mutex);
-static int vfs_phone = -1;
+#include <ipc/loc.h>
+
+static FIBRIL_MUTEX_INITIALIZE(vfs_mutex);
+static async_sess_t *vfs_sess = NULL;
 
 static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
@@ -65,9 +64,36 @@
 static size_t cwd_size = 0;
 
+/** Start an async exchange on the VFS session.
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *vfs_exchange_begin(void)
+{
+	fibril_mutex_lock(&vfs_mutex);
+	
+	while (vfs_sess == NULL)
+		vfs_sess = service_connect_blocking(EXCHANGE_PARALLEL, SERVICE_VFS,
+		    0, 0);
+	
+	fibril_mutex_unlock(&vfs_mutex);
+	
+	return async_exchange_begin(vfs_sess);
+}
+
+/** Finish an async exchange on the VFS session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+void vfs_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
+}
+
 char *absolutize(const char *path, size_t *retlen)
 {
 	char *ncwd_path;
 	char *ncwd_path_nc;
-	size_t total_size; 
 
 	fibril_mutex_lock(&cwd_mutex);
@@ -78,16 +104,14 @@
 			return NULL;
 		}
-		total_size = cwd_size + 1 + size + 1;
-		ncwd_path_nc = malloc(total_size);
+		ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
 		if (!ncwd_path_nc) {
 			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
-		str_cpy(ncwd_path_nc, total_size, cwd_path);
+		str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
 		ncwd_path_nc[cwd_size] = '/';
 		ncwd_path_nc[cwd_size + 1] = '\0';
 	} else {
-		total_size = size + 1;
-		ncwd_path_nc = malloc(total_size);
+		ncwd_path_nc = malloc(size + 1);
 		if (!ncwd_path_nc) {
 			fibril_mutex_unlock(&cwd_mutex);
@@ -96,5 +120,5 @@
 		ncwd_path_nc[0] = '\0';
 	}
-	str_append(ncwd_path_nc, total_size, path);
+	str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
 	ncwd_path = canonify(ncwd_path_nc, retlen);
 	if (!ncwd_path) {
@@ -118,59 +142,27 @@
 }
 
-/** Connect to VFS service and create session. */
-static void vfs_connect(void)
-{
-	while (vfs_phone < 0)
-		vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
-	
-	async_session_create(&vfs_session, vfs_phone, 0);
-}
-
-/** Start an async exchange on the VFS session.
- *
- * @return		New phone to be used during the exchange.
- */
-static int vfs_exchange_begin(void)
-{
-	fibril_mutex_lock(&vfs_phone_mutex);
-	if (vfs_phone < 0)
-		vfs_connect();
-	fibril_mutex_unlock(&vfs_phone_mutex);
-
-	return async_exchange_begin(&vfs_session);
-}
-
-/** End an async exchange on the VFS session.
- *
- * @param phone		Phone used during the exchange.
- */
-static void vfs_exchange_end(int phone)
-{
-	async_exchange_end(&vfs_session, phone);
-}
-
-int mount(const char *fs_name, const char *mp, const char *fqdn,
+int mount(const char *fs_name, const char *mp, const char *fqsn,
     const char *opts, unsigned int flags)
 {
 	int null_id = -1;
-	char null[DEVMAP_NAME_MAXLEN];
-	
-	if (str_cmp(fqdn, "") == 0) {
+	char null[LOC_NAME_MAXLEN];
+	
+	if (str_cmp(fqsn, "") == 0) {
 		/* No device specified, create a fresh
 		   null/%d device instead */
-		null_id = devmap_null_create();
+		null_id = loc_null_create();
 		
 		if (null_id == -1)
 			return ENOMEM;
 		
-		snprintf(null, DEVMAP_NAME_MAXLEN, "null/%d", null_id);
-		fqdn = null;
-	}
-	
-	devmap_handle_t devmap_handle;
-	int res = devmap_device_get_handle(fqdn, &devmap_handle, flags);
+		snprintf(null, LOC_NAME_MAXLEN, "null/%d", null_id);
+		fqsn = null;
+	}
+	
+	service_id_t service_id;
+	int res = loc_service_get_id(fqsn, &service_id, flags);
 	if (res != EOK) {
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		return res;
@@ -181,51 +173,51 @@
 	if (!mpa) {
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		return ENOMEM;
 	}
 	
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 
 	sysarg_t rc_orig;
-	aid_t req = async_send_2(vfs_phone, VFS_IN_MOUNT, devmap_handle, flags, NULL);
-	sysarg_t rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	aid_t req = async_send_2(exch, VFS_IN_MOUNT, service_id, flags, NULL);
+	sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
-		
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-	rc = async_data_write_start(vfs_phone, (void *) opts, str_size(opts));
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+			loc_null_destroy(null_id);
+		
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
+	rc = async_data_write_start(exch, (void *) opts, str_size(opts));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
-		
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-	rc = async_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+			loc_null_destroy(null_id);
+		
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
+	rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
+			loc_null_destroy(null_id);
 		
 		if (rc_orig == EOK)
@@ -236,25 +228,25 @@
 	
 	/* Ask VFS whether it likes fs_name. */
-	rc = async_req_0_0(vfs_phone, IPC_M_PING);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	rc = async_req_0_0(exch, VFS_IN_PING);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
 		
 		if (null_id != -1)
-			devmap_null_destroy(null_id);
-		
-		if (rc_orig == EOK)
-			return (int) rc;
-		else
-			return (int) rc_orig;
-	}
-	
-	vfs_exchange_end(vfs_phone);
+			loc_null_destroy(null_id);
+		
+		if (rc_orig == EOK)
+			return (int) rc;
+		else
+			return (int) rc_orig;
+	}
+	
+	vfs_exchange_end(exch);
 	free(mpa);
 	async_wait_for(req, &rc);
 	
 	if ((rc != EOK) && (null_id != -1))
-		devmap_null_destroy(null_id);
+		loc_null_destroy(null_id);
 	
 	return (int) rc;
@@ -273,10 +265,10 @@
 		return ENOMEM;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_0(vfs_phone, VFS_IN_UNMOUNT, NULL);
-	rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
+	rc = async_data_write_start(exch, (void *) mpa, mpa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
@@ -288,5 +280,5 @@
 	
 
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(mpa);
 	async_wait_for(req, &rc);
@@ -297,12 +289,12 @@
 static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
 {
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 	
 	ipc_call_t answer;
-	aid_t req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
-	sysarg_t rc = async_data_write_start(vfs_phone, abs, abs_size);
-	
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	aid_t req = async_send_3(exch, VFS_IN_OPEN, lflag, oflag, 0, &answer);
+	sysarg_t rc = async_data_write_start(exch, abs, abs_size);
+	
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 
 		sysarg_t rc_orig;
@@ -315,5 +307,5 @@
 	}
 	
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
 	
@@ -337,34 +329,13 @@
 }
 
-int open_node(fdi_node_t *node, int oflag)
-{
-	int vfs_phone = vfs_exchange_begin();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle,
-	    node->devmap_handle, node->index, oflag, &answer);
-	
-	vfs_exchange_end(vfs_phone);
-
-	sysarg_t rc;
-	async_wait_for(req, &rc);
-	
-	if (rc != EOK)
-		return (int) rc;
-	
-	return (int) IPC_GET_ARG1(answer);
-}
-
 int close(int fildes)
 {
 	sysarg_t rc;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
-	
-	vfs_exchange_end(vfs_phone);
-	
-	return (int)rc;
+	async_exch_t *exch = vfs_exchange_begin();
+	rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
+	vfs_exchange_end(exch);
+	
+	return (int) rc;
 }
 
@@ -374,11 +345,11 @@
 	ipc_call_t answer;
 	aid_t req;
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
-	rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
+	rc = async_data_read_start(exch, (void *)buf, nbyte);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 
 		sysarg_t rc_orig;
@@ -390,5 +361,5 @@
 			return (ssize_t) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
 	if (rc == EOK)
@@ -403,11 +374,11 @@
 	ipc_call_t answer;
 	aid_t req;
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
-	rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
+	rc = async_data_write_start(exch, (void *)buf, nbyte);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 
 		sysarg_t rc_orig;
@@ -419,5 +390,5 @@
 			return (ssize_t) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
 	if (rc == EOK)
@@ -427,11 +398,71 @@
 }
 
+/** Read entire buffer.
+ *
+ * In face of short reads this function continues reading until either
+ * the entire buffer is read or no more data is available (at end of file).
+ *
+ * @param fildes	File descriptor
+ * @param buf		Buffer, @a nbytes bytes long
+ * @param nbytes	Number of bytes to read
+ *
+ * @return		On success, positive number of bytes read.
+ *			On failure, negative error code from read().
+ */
+ssize_t read_all(int fildes, void *buf, size_t nbyte)
+{
+	ssize_t cnt = 0;
+	size_t nread = 0;
+	uint8_t *bp = (uint8_t *) buf;
+
+	do {
+		bp += cnt;
+		nread += cnt;
+		cnt = read(fildes, bp, nbyte - nread);
+	} while (cnt > 0 && (nbyte - nread - cnt) > 0);
+
+	if (cnt < 0)
+		return cnt;
+
+	return nread + cnt;
+}
+
+/** Write entire buffer.
+ *
+ * This function fails if it cannot write exactly @a len bytes to the file.
+ *
+ * @param fildes	File descriptor
+ * @param buf		Data, @a nbytes bytes long
+ * @param nbytes	Number of bytes to write
+ *
+ * @return		EOK on error, return value from write() if writing
+ *			failed.
+ */
+ssize_t write_all(int fildes, const void *buf, size_t nbyte)
+{
+	ssize_t cnt = 0;
+	ssize_t nwritten = 0;
+	const uint8_t *bp = (uint8_t *) buf;
+
+	do {
+		bp += cnt;
+		nwritten += cnt;
+		cnt = write(fildes, bp, nbyte - nwritten);
+	} while (cnt > 0 && ((ssize_t )nbyte - nwritten - cnt) > 0);
+
+	if (cnt < 0)
+		return cnt;
+
+	if ((ssize_t)nbyte - nwritten - cnt > 0)
+		return EIO;
+
+	return nbyte;
+}
+
 int fsync(int fildes)
 {
-	int vfs_phone = vfs_exchange_begin();
-	
-	sysarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
-	
-	vfs_exchange_end(vfs_phone);
+	async_exch_t *exch = vfs_exchange_begin();
+	sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, fildes);
+	vfs_exchange_end(exch);
 	
 	return (int) rc;
@@ -440,13 +471,13 @@
 off64_t lseek(int fildes, off64_t offset, int whence)
 {
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 	
 	sysarg_t newoff_lo;
 	sysarg_t newoff_hi;
-	sysarg_t rc = async_req_4_2(vfs_phone, VFS_IN_SEEK, fildes,
+	sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
 	    LOWER32(offset), UPPER32(offset), whence,
 	    &newoff_lo, &newoff_hi);
 	
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	
 	if (rc != EOK)
@@ -460,9 +491,8 @@
 	sysarg_t rc;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	rc = async_req_3_0(vfs_phone, VFS_IN_TRUNCATE, fildes,
+	async_exch_t *exch = vfs_exchange_begin();
+	rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
 	    LOWER32(length), UPPER32(length));
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	
 	return (int) rc;
@@ -473,11 +503,11 @@
 	sysarg_t rc;
 	aid_t req;
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
-	rc = async_data_read_start(vfs_phone, (void *) stat, sizeof(struct stat));
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_FSTAT, fildes, NULL);
+	rc = async_data_read_start(exch, (void *) stat, sizeof(struct stat));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 
 		sysarg_t rc_orig;
@@ -489,5 +519,5 @@
 			return (ssize_t) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
 
@@ -506,10 +536,10 @@
 		return ENOMEM;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
-	rc = async_data_write_start(vfs_phone, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_0(exch, VFS_IN_STAT, NULL);
+	rc = async_data_write_start(exch, pa, pa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(pa);
 		async_wait_for(req, &rc_orig);
@@ -519,7 +549,7 @@
 			return (int) rc_orig;
 	}
-	rc = async_data_read_start(vfs_phone, stat, sizeof(struct stat));
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	rc = async_data_read_start(exch, stat, sizeof(struct stat));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(pa);
 		async_wait_for(req, &rc_orig);
@@ -529,5 +559,5 @@
 			return (int) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(pa);
 	async_wait_for(req, &rc);
@@ -590,10 +620,10 @@
 		return ENOMEM;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
-	rc = async_data_write_start(vfs_phone, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
+	rc = async_data_write_start(exch, pa, pa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(pa);
 
@@ -606,5 +636,5 @@
 			return (int) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(pa);
 	async_wait_for(req, &rc);
@@ -621,11 +651,11 @@
 	if (!pa)
 		return ENOMEM;
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
-	rc = async_data_write_start(vfs_phone, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_0(exch, VFS_IN_UNLINK, NULL);
+	rc = async_data_write_start(exch, pa, pa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(pa);
 
@@ -638,5 +668,5 @@
 			return (int) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(pa);
 	async_wait_for(req, &rc);
@@ -671,11 +701,11 @@
 		return ENOMEM;
 	}
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
-	rc = async_data_write_start(vfs_phone, olda, olda_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_0(exch, VFS_IN_RENAME, NULL);
+	rc = async_data_write_start(exch, olda, olda_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(olda);
 		free(newa);
@@ -686,7 +716,7 @@
 			return (int) rc_orig;
 	}
-	rc = async_data_write_start(vfs_phone, newa, newa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	rc = async_data_write_start(exch, newa, newa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(olda);
 		free(newa);
@@ -697,5 +727,5 @@
 			return (int) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(olda);
 	free(newa);
@@ -753,41 +783,29 @@
 }
 
-int fd_phone(int fildes)
+async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
 {
 	struct stat stat;
-	int rc;
-
-	rc = fstat(fildes, &stat);
-
-	if (!stat.device)
-		return -1;
-	
-	return devmap_device_connect(stat.device, 0);
-}
-
-int fd_node(int fildes, fdi_node_t *node)
-{
-	struct stat stat;
-	int rc;
-
-	rc = fstat(fildes, &stat);
-	
-	if (rc == EOK) {
-		node->fs_handle = stat.fs_handle;
-		node->devmap_handle = stat.devmap_handle;
-		node->index = stat.index;
-	}
-	
-	return rc;
+	int rc = fstat(fildes, &stat);
+	if (rc != 0) {
+		errno = rc;
+		return NULL;
+	}
+	
+	if (!stat.service) {
+		errno = ENOENT;
+		return NULL;
+	}
+	
+	return loc_service_connect(mgmt, stat.service, 0);
 }
 
 int dup2(int oldfd, int newfd)
 {
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 	
 	sysarg_t ret;
-	sysarg_t rc = async_req_2_1(vfs_phone, VFS_IN_DUP, oldfd, newfd, &ret);
-	
-	vfs_exchange_end(vfs_phone);
+	sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
+	
+	vfs_exchange_end(exch);
 	
 	if (rc == EOK)
@@ -797,4 +815,19 @@
 }
 
+int fd_wait(void)
+{
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	sysarg_t ret;
+	sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
+	
+	vfs_exchange_end(exch);
+	
+	if (rc == EOK)
+		return (int) ret;
+	
+	return (int) rc;
+}
+
 /** @}
  */
Index: uspace/lib/c/include/adt/fifo.h
===================================================================
--- uspace/lib/c/include/adt/fifo.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/adt/fifo.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -51,10 +51,10 @@
 typedef unsigned long fifo_index_t;
 
-#define FIFO_CREATE_STATIC(name, t, itms)		\
-	struct {					\
-		t fifo[(itms)];				\
-		fifo_count_t items;			\
-		fifo_index_t head;			\
-		fifo_index_t tail;			\
+#define FIFO_CREATE_STATIC(name, t, itms) \
+	struct { \
+		t fifo[(itms)]; \
+		fifo_count_t items; \
+		fifo_index_t head; \
+		fifo_index_t tail; \
 	} name
 
Index: uspace/lib/c/include/adt/generic_char_map.h
===================================================================
--- uspace/lib/c/include/adt/generic_char_map.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/adt/generic_char_map.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -47,4 +47,8 @@
 #define GENERIC_CHAR_MAP_MAGIC_VALUE	0x12345622
 
+/** Generic destructor function pointer. */
+#define DTOR_T(identifier) \
+	void (*identifier)(const void *)
+
 /** Character string to generic type map declaration.
  *  @param[in] name	Name of the map.
@@ -64,6 +68,6 @@
 	int name##_add(name##_t *, const uint8_t *, const size_t, type *); \
 	int name##_count(name##_t *); \
-	void name##_destroy(name##_t *); \
-	void name##_exclude(name##_t *, const uint8_t *, const size_t); \
+	void name##_destroy(name##_t *, DTOR_T()); \
+	void name##_exclude(name##_t *, const uint8_t *, const size_t, DTOR_T()); \
 	type *name##_find(name##_t *, const uint8_t *, const size_t); \
 	int name##_initialize(name##_t *); \
@@ -84,5 +88,4 @@
 	     type *value) \
 	{ \
-		int rc; \
 		int index; \
 		if (!name##_is_valid(map)) \
@@ -91,10 +94,5 @@
 		if (index < 0) \
 			return index; \
-		rc = char_map_add(&map->names, name, length, index); \
-		if (rc != EOK) { \
-			name##_items_exclude_index(&map->values, index); \
-			return rc; \
-		} \
-		return EOK; \
+		return char_map_add(&map->names, name, length, index); \
 	} \
 	\
@@ -105,14 +103,14 @@
 	} \
 	\
-	void name##_destroy(name##_t *map) \
+	void name##_destroy(name##_t *map, DTOR_T(dtor)) \
 	{ \
 		if (name##_is_valid(map)) { \
 			char_map_destroy(&map->names); \
-			name##_items_destroy(&map->values); \
+			name##_items_destroy(&map->values, dtor); \
 		} \
 	} \
 	\
 	void name##_exclude(name##_t *map, const uint8_t *name, \
-	    const size_t length) \
+	    const size_t length, DTOR_T(dtor)) \
 	{ \
 		if (name##_is_valid(map)) { \
@@ -121,5 +119,5 @@
 			if (index != CHAR_MAP_NULL) \
 				name##_items_exclude_index(&map->values, \
-				     index); \
+				     index, dtor); \
 		} \
 	} \
Index: uspace/lib/c/include/adt/generic_field.h
===================================================================
--- uspace/lib/c/include/adt/generic_field.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/adt/generic_field.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -46,4 +46,8 @@
 #define GENERIC_FIELD_MAGIC_VALUE		0x55667788
 
+/** Generic destructor function pointer. */
+#define DTOR_T(identifier) \
+	void (*identifier)(const void *)
+
 /** Generic type field declaration.
  *
@@ -63,6 +67,6 @@
 	int name##_add(name##_t *, type *); \
 	int name##_count(name##_t *); \
-	void name##_destroy(name##_t *); \
-	void name##_exclude_index(name##_t *, int); \
+	void name##_destroy(name##_t *, DTOR_T()); \
+	void name##_exclude_index(name##_t *, int, DTOR_T()); \
 	type **name##_get_field(name##_t *); \
 	type *name##_get_index(name##_t *, int); \
@@ -103,12 +107,14 @@
 	} \
 	\
-	void name##_destroy(name##_t *field) \
+	void name##_destroy(name##_t *field, DTOR_T(dtor)) \
 	{ \
 		if (name##_is_valid(field)) { \
 			int index; \
 			field->magic = 0; \
-			for (index = 0; index < field->next; index++) { \
-				if (field->items[index]) \
-					free(field->items[index]); \
+			if (dtor) { \
+				for (index = 0; index < field->next; index++) { \
+					if (field->items[index]) \
+						dtor(field->items[index]); \
+				} \
 			} \
 			free(field->items); \
@@ -116,9 +122,10 @@
 	} \
 	 \
-	void name##_exclude_index(name##_t *field, int index) \
+	void name##_exclude_index(name##_t *field, int index, DTOR_T(dtor)) \
 	{ \
 		if (name##_is_valid(field) && (index >= 0) && \
 		    (index < field->next) && (field->items[index])) { \
-			free(field->items[index]); \
+			if (dtor) \
+				dtor(field->items[index]); \
 			field->items[index] = NULL; \
 		} \
Index: uspace/lib/c/include/adt/hash_table.h
===================================================================
--- uspace/lib/c/include/adt/hash_table.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/adt/hash_table.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #include <adt/list.h>
 #include <unistd.h>
+#include <bool.h>
 
 typedef unsigned long hash_count_t;
@@ -74,5 +75,5 @@
 /** Hash table structure. */
 typedef struct {
-	link_t *entry;
+	list_t *entry;
 	hash_count_t entries;
 	hash_count_t max_keys;
@@ -83,5 +84,5 @@
     list_get_instance((item), type, member)
 
-extern int hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
+extern bool hash_table_create(hash_table_t *, hash_count_t, hash_count_t,
     hash_table_operations_t *);
 extern void hash_table_insert(hash_table_t *, unsigned long [], link_t *);
Index: uspace/lib/c/include/adt/int_map.h
===================================================================
--- uspace/lib/c/include/adt/int_map.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/adt/int_map.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -49,4 +49,8 @@
 #define INT_MAP_ITEM_MAGIC_VALUE	0x55667788
 
+/** Generic destructor function pointer. */
+#define DTOR_T(identifier) \
+	void (*identifier)(const void *)
+
 /** Integer to generic type map declaration.
  *
@@ -72,9 +76,9 @@
 	\
 	int name##_add(name##_t *, int, type *); \
-	void name##_clear(name##_t *); \
+	void name##_clear(name##_t *, DTOR_T()); \
 	int name##_count(name##_t *); \
-	void name##_destroy(name##_t *); \
-	void name##_exclude(name##_t *, int); \
-	void name##_exclude_index(name##_t *, int); \
+	void name##_destroy(name##_t *, DTOR_T()); \
+	void name##_exclude(name##_t *, int, DTOR_T()); \
+	void name##_exclude_index(name##_t *, int, DTOR_T()); \
 	type *name##_find(name##_t *, int); \
 	int name##_update(name##_t *, int, int); \
@@ -82,5 +86,5 @@
 	int name##_initialize(name##_t *); \
 	int name##_is_valid(name##_t *); \
-	void name##_item_destroy(name##_item_t *); \
+	void name##_item_destroy(name##_item_t *, DTOR_T()); \
 	int name##_item_is_valid(name##_item_t *);
 
@@ -115,5 +119,5 @@
 	} \
 	\
-	void name##_clear(name##_t *map) \
+	void name##_clear(name##_t *map, DTOR_T(dtor)) \
 	{ \
 		if (name##_is_valid(map)) { \
@@ -122,5 +126,5 @@
 				if (name##_item_is_valid(&map->items[index])) { \
 					name##_item_destroy( \
-					    &map->items[index]); \
+					    &map->items[index], dtor); \
 				} \
 			} \
@@ -135,5 +139,5 @@
 	} \
 	\
-	void name##_destroy(name##_t *map) \
+	void name##_destroy(name##_t *map, DTOR_T(dtor)) \
 	{ \
 		if (name##_is_valid(map)) { \
@@ -143,5 +147,5 @@
 				if (name##_item_is_valid(&map->items[index])) { \
 					name##_item_destroy( \
-					    &map->items[index]); \
+					    &map->items[index], dtor); \
 				} \
 			} \
@@ -150,5 +154,5 @@
 	} \
 	\
-	void name##_exclude(name##_t *map, int key) \
+	void name##_exclude(name##_t *map, int key, DTOR_T(dtor)) \
 	{ \
 		if (name##_is_valid(map)) { \
@@ -158,16 +162,16 @@
 				    (map->items[index].key == key)) { \
 					name##_item_destroy( \
-					    &map->items[index]); \
-				} \
-			} \
-		} \
-	} \
-	\
-	void name##_exclude_index(name##_t *map, int index) \
+					    &map->items[index], dtor); \
+				} \
+			} \
+		} \
+	} \
+	\
+	void name##_exclude_index(name##_t *map, int index, DTOR_T(dtor)) \
 	{ \
 		if (name##_is_valid(map) && (index >= 0) && \
 		    (index < map->next) && \
 		    name##_item_is_valid(&map->items[index])) { \
-			name##_item_destroy(&map->items[index]); \
+			name##_item_destroy(&map->items[index], dtor); \
 		} \
 	} \
@@ -236,10 +240,11 @@
 	} \
 	\
-	void name##_item_destroy(name##_item_t *item) \
+	void name##_item_destroy(name##_item_t *item, DTOR_T(dtor)) \
 	{ \
 		if (name##_item_is_valid(item)) { \
 			item->magic = 0; \
 			if (item->value) { \
-				free(item->value); \
+				if (dtor) \
+					dtor(item->value); \
 				item->value = NULL; \
 			} \
Index: uspace/lib/c/include/adt/list.h
===================================================================
--- uspace/lib/c/include/adt/list.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/adt/list.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2001-2004 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,7 +37,8 @@
 #define LIBC_LIST_H_
 
+#include <assert.h>
 #include <unistd.h>
 
-/** Doubly linked list head and link type. */
+/** Doubly linked list link. */
 typedef struct link {
 	struct link *prev;  /**< Pointer to the previous item in the list. */
@@ -44,12 +46,31 @@
 } link_t;
 
+/** Doubly linked list. */
+typedef struct list {
+	link_t head;  /**< List head. Does not have any data. */
+} list_t;
+
 /** Declare and initialize statically allocated list.
  *
  * @param name Name of the new statically allocated list.
- */
-#define LIST_INITIALIZE(name)  link_t name = { \
-	.prev = &name, \
-	.next = &name \
-}
+ *
+ */
+#define LIST_INITIALIZE(name) \
+	list_t name = { \
+		.head = { \
+			.prev = &(name).head, \
+			.next = &(name).head \
+		} \
+	}
+
+#define list_get_instance(link, type, member) \
+	((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
+
+#define list_foreach(list, iterator) \
+	for (link_t *iterator = (list).head.next; \
+	    iterator != &(list).head; iterator = iterator->next)
+
+#define assert_link_not_used(link) \
+	assert((link)->prev == NULL && (link)->next == NULL)
 
 /** Initialize doubly-linked circular list link
@@ -58,4 +79,5 @@
  *
  * @param link Pointer to link_t structure to be initialized.
+ *
  */
 static inline void link_initialize(link_t *link)
@@ -69,10 +91,33 @@
  * Initialize doubly-linked circular list.
  *
- * @param head Pointer to link_t structure representing head of the list.
- */
-static inline void list_initialize(link_t *head)
-{
-	head->prev = head;
-	head->next = head;
+ * @param list Pointer to list_t structure.
+ *
+ */
+static inline void list_initialize(list_t *list)
+{
+	list->head.prev = &list->head;
+	list->head.next = &list->head;
+}
+
+/** Insert item before another item in doubly-linked circular list.
+ *
+ */
+static inline void list_insert_before(link_t *lnew, link_t *lold)
+{
+	lnew->next = lold;
+	lnew->prev = lold->prev;
+	lold->prev->next = lnew;
+	lold->prev = lnew;
+}
+
+/** Insert item after another item in doubly-linked circular list.
+ *
+ */
+static inline void list_insert_after(link_t *lnew, link_t *lold)
+{
+	lnew->prev = lold;
+	lnew->next = lold->next;
+	lold->next->prev = lnew;
+	lold->next = lnew;
 }
 
@@ -82,12 +127,10 @@
  *
  * @param link Pointer to link_t structure to be added.
- * @param head Pointer to link_t structure representing head of the list.
- */
-static inline void list_prepend(link_t *link, link_t *head)
-{
-	link->next = head->next;
-	link->prev = head;
-	head->next->prev = link;
-	head->next = link;
+ * @param list Pointer to list_t structure.
+ *
+ */
+static inline void list_prepend(link_t *link, list_t *list)
+{
+	list_insert_after(link, &list->head);
 }
 
@@ -97,24 +140,10 @@
  *
  * @param link Pointer to link_t structure to be added.
- * @param head Pointer to link_t structure representing head of the list.
- */
-static inline void list_append(link_t *link, link_t *head)
-{
-	link->prev = head->prev;
-	link->next = head;
-	head->prev->next = link;
-	head->prev = link;
-}
-
-/** Insert item before another item in doubly-linked circular list. */
-static inline void list_insert_before(link_t *l, link_t *r)
-{
-	list_append(l, r);
-}
-
-/** Insert item after another item in doubly-linked circular list. */
-static inline void list_insert_after(link_t *r, link_t *l)
-{
-	list_prepend(l, r);
+ * @param list Pointer to list_t structure.
+ *
+ */
+static inline void list_append(link_t *link, list_t *list)
+{
+	list_insert_before(link, &list->head);
 }
 
@@ -123,5 +152,7 @@
  * Remove item from doubly-linked circular list.
  *
- * @param link Pointer to link_t structure to be removed from the list it is contained in.
+ * @param link Pointer to link_t structure to be removed from the list
+ *             it is contained in.
+ *
  */
 static inline void list_remove(link_t *link)
@@ -136,11 +167,37 @@
  * Query emptiness of doubly-linked circular list.
  *
- * @param head Pointer to link_t structure representing head of the list.
- */
-static inline int list_empty(link_t *head)
-{
-	return ((head->next == head) ? 1 : 0);
-}
-
+ * @param list Pointer to lins_t structure.
+ *
+ */
+static inline int list_empty(list_t *list)
+{
+	return (list->head.next == &list->head);
+}
+
+/** Get first item in list.
+ *
+ * @param list Pointer to list_t structure.
+ *
+ * @return Head item of the list.
+ * @return NULL if the list is empty.
+ *
+ */
+static inline link_t *list_first(list_t *list)
+{
+	return ((list->head.next == &list->head) ? NULL : list->head.next);
+}
+
+/** Get last item in list.
+ *
+ * @param list Pointer to list_t structure.
+ *
+ * @return Head item of the list.
+ * @return NULL if the list is empty.
+ *
+ */
+static inline link_t *list_last(list_t *list)
+{
+	return ((list->head.prev == &list->head) ? NULL : list->head.prev);
+}
 
 /** Split or concatenate headless doubly-linked circular list
@@ -151,6 +208,9 @@
  * concatenates splitted lists and splits concatenated lists.
  *
- * @param part1 Pointer to link_t structure leading the first (half of the headless) list.
- * @param part2 Pointer to link_t structure leading the second (half of the headless) list. 
+ * @param part1 Pointer to link_t structure leading the first
+ *              (half of the headless) list.
+ * @param part2 Pointer to link_t structure leading the second
+ *              (half of the headless) list.
+ *
  */
 static inline void headless_list_split_or_concat(link_t *part1, link_t *part2)
@@ -165,11 +225,13 @@
 }
 
-
 /** Split headless doubly-linked circular list
  *
  * Split headless doubly-linked circular list.
  *
- * @param part1 Pointer to link_t structure leading the first half of the headless list.
- * @param part2 Pointer to link_t structure leading the second half of the headless list. 
+ * @param part1 Pointer to link_t structure leading
+ *              the first half of the headless list.
+ * @param part2 Pointer to link_t structure leading
+ *              the second half of the headless list.
+ *
  */
 static inline void headless_list_split(link_t *part1, link_t *part2)
@@ -182,6 +244,9 @@
  * Concatenate two headless doubly-linked circular lists.
  *
- * @param part1 Pointer to link_t structure leading the first headless list.
- * @param part2 Pointer to link_t structure leading the second headless list. 
+ * @param part1 Pointer to link_t structure leading
+ *              the first headless list.
+ * @param part2 Pointer to link_t structure leading
+ *              the second headless list.
+ *
  */
 static inline void headless_list_concat(link_t *part1, link_t *part2)
@@ -190,9 +255,30 @@
 }
 
-#define list_get_instance(link, type, member)  ((type *) (((void *)(link)) - ((void *) &(((type *) NULL)->member))))
-
-extern int list_member(const link_t *link, const link_t *head);
-extern void list_concat(link_t *head1, link_t *head2);
-extern unsigned int list_count(const link_t *link);
+/** Get n-th item in a list.
+ *
+ * @param list Pointer to link_t structure representing the list.
+ * @param n    Item number (indexed from zero).
+ *
+ * @return n-th item of the list.
+ * @return NULL if no n-th item found.
+ *
+ */
+static inline link_t *list_nth(list_t *list, unsigned int n)
+{
+	unsigned int cnt = 0;
+	
+	list_foreach(*list, link) {
+		if (cnt == n)
+			return link;
+		
+		cnt++;
+	}
+	
+	return NULL;
+}
+
+extern int list_member(const link_t *, const list_t *);
+extern void list_concat(list_t *, list_t *);
+extern unsigned int list_count(const list_t *);
 
 #endif
Index: uspace/lib/c/include/adt/measured_strings.h
===================================================================
--- uspace/lib/c/include/adt/measured_strings.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/adt/measured_strings.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,4 +41,5 @@
 
 #include <sys/types.h>
+#include <async.h>
 
 /** Type definition of the character string with measured length.
@@ -61,8 +62,12 @@
 extern measured_string_t *measured_string_create_bulk(const uint8_t *, size_t);
 extern measured_string_t *measured_string_copy(measured_string_t *);
+
 extern int measured_strings_receive(measured_string_t **, uint8_t **, size_t);
 extern int measured_strings_reply(const measured_string_t *, size_t);
-extern int measured_strings_return(int, measured_string_t **, uint8_t **, size_t);
-extern int measured_strings_send(int, const measured_string_t *, size_t);
+
+extern int measured_strings_return(async_exch_t *, measured_string_t **,
+    uint8_t **, size_t);
+extern int measured_strings_send(async_exch_t *, const measured_string_t *,
+    size_t);
 
 #endif
Index: uspace/lib/c/include/adt/prodcons.h
===================================================================
--- uspace/lib/c/include/adt/prodcons.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/adt/prodcons.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRODCONS_H_
+#define LIBC_PRODCONS_H_
+
+#include <adt/list.h>
+#include <fibril_synch.h>
+
+typedef struct {
+	fibril_mutex_t mtx;
+	fibril_condvar_t cv;
+	list_t list;
+} prodcons_t;
+
+extern void prodcons_initialize(prodcons_t *);
+extern void prodcons_produce(prodcons_t *, link_t *);
+extern link_t *prodcons_consume(prodcons_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/as.h
===================================================================
--- uspace/lib/c/include/as.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/as.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,6 +37,6 @@
 
 #include <sys/types.h>
+#include <abi/mm/as.h>
 #include <task.h>
-#include <kernel/mm/as.h>
 #include <libarch/config.h>
 
@@ -54,10 +54,11 @@
 }
 
-extern void *as_area_create(void *address, size_t size, int flags);
-extern int as_area_resize(void *address, size_t size, int flags);
-extern int as_area_change_flags(void *address, int flags);
-extern int as_area_destroy(void *address);
-extern void *set_maxheapsize(size_t mhs);
-extern void * as_get_mappable_page(size_t sz);
+extern void *as_area_create(void *, size_t, unsigned int);
+extern int as_area_resize(void *, size_t, unsigned int);
+extern int as_area_change_flags(void *, unsigned int);
+extern int as_area_destroy(void *);
+extern void *set_maxheapsize(size_t);
+extern void *as_get_mappable_page(size_t);
+extern int as_get_physical_mapping(void *, uintptr_t *);
 
 #endif
Index: uspace/lib/c/include/assert.h
===================================================================
--- uspace/lib/c/include/assert.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/assert.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,5 +40,5 @@
  *
  * If NDEBUG is not set, the assert() macro
- * evaluates expr and if it is false prints 
+ * evaluates expr and if it is false prints
  * error message and terminate program.
  *
@@ -47,16 +47,10 @@
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-
 #ifndef NDEBUG
 
 #define assert(expr) \
 	do { \
-		if (!(expr)) { \
-			printf("Assertion failed (%s) at file '%s', " \
-			    "line %d.\n", #expr, __FILE__, __LINE__); \
-			abort(); \
-		} \
+		if (!(expr)) \
+			assert_abort(#expr, __FILE__, __LINE__); \
 	} while (0)
 
@@ -67,4 +61,7 @@
 #endif /* NDEBUG */
 
+extern void assert_abort(const char *, const char *, unsigned int)
+    __attribute__((noreturn));
+
 #endif
 
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/async.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,5 +41,4 @@
 
 #include <ipc/common.h>
-#include <async_sess.h>
 #include <fibril.h>
 #include <sys/time.h>
@@ -53,5 +52,53 @@
 typedef void (*async_client_data_dtor_t)(void *);
 
-typedef void (*async_client_conn_t)(ipc_callid_t, ipc_call_t *);
+/** Client connection handler
+ *
+ * @param callid ID of incoming call or 0 if connection initiated from
+ *               inside using async_connect_to_me()
+ * @param call   Incoming call or 0 if connection initiated from inside
+ * @param arg    Local argument passed from async_new_connection() or
+ *               async_connect_to_me()
+ */
+typedef void (*async_client_conn_t)(ipc_callid_t, ipc_call_t *, void *);
+
+/** Interrupt handler */
+typedef void (*async_interrupt_handler_t)(ipc_callid_t, ipc_call_t *);
+
+/** Exchange management style
+ *
+ */
+typedef enum {
+	/** No explicit exchange management
+	 *
+	 * Suitable for protocols which use a single
+	 * IPC message per exchange only.
+	 *
+	 */
+	EXCHANGE_ATOMIC = 0,
+	
+	/** Exchange management via phone cloning
+	 *
+	 * Suitable for servers which support client
+	 * data tracking by task hashes and do not
+	 * mind cloned phones.
+	 *
+	 */
+	EXCHANGE_PARALLEL,
+	
+	/** Exchange management via mutual exclusion
+	 *
+	 * Suitable for any kind of client/server communication,
+	 * but can limit parallelism.
+	 *
+	 */
+	EXCHANGE_SERIALIZE
+} exch_mgmt_t;
+
+/** Forward declarations */
+struct _async_exch;
+struct _async_sess;
+
+typedef struct _async_sess async_sess_t;
+typedef struct _async_exch async_exch_t;
 
 extern atomic_t threads_in_ipc_wait;
@@ -68,32 +115,32 @@
  * User-friendly wrappers for async_send_fast() and async_send_slow(). The
  * macros are in the form async_send_m(), where m denotes the number of payload
- * arguments.  Each macros chooses between the fast and the slow version based
+ * arguments. Each macros chooses between the fast and the slow version based
  * on m.
  */
 
-#define async_send_0(phoneid, method, dataptr) \
-	async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
-#define async_send_1(phoneid, method, arg1, dataptr) \
-	async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
-#define async_send_2(phoneid, method, arg1, arg2, dataptr) \
-	async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
-#define async_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
-	async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
-#define async_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
-	async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (dataptr))
-#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
-	async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (dataptr))
-
-extern aid_t async_send_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, ipc_call_t *);
-extern aid_t async_send_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+#define async_send_0(exch, method, dataptr) \
+	async_send_fast(exch, method, 0, 0, 0, 0, dataptr)
+#define async_send_1(exch, method, arg1, dataptr) \
+	async_send_fast(exch, method, arg1, 0, 0, 0, dataptr)
+#define async_send_2(exch, method, arg1, arg2, dataptr) \
+	async_send_fast(exch, method, arg1, arg2, 0, 0, dataptr)
+#define async_send_3(exch, method, arg1, arg2, arg3, dataptr) \
+	async_send_fast(exch, method, arg1, arg2, arg3, 0, dataptr)
+#define async_send_4(exch, method, arg1, arg2, arg3, arg4, dataptr) \
+	async_send_fast(exch, method, arg1, arg2, arg3, arg4, dataptr)
+#define async_send_5(exch, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
+	async_send_slow(exch, method, arg1, arg2, arg3, arg4, arg5, dataptr)
+
+extern aid_t async_send_fast(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, ipc_call_t *);
+extern aid_t async_send_slow(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, ipc_call_t *);
+
 extern void async_wait_for(aid_t, sysarg_t *);
 extern int async_wait_timeout(aid_t, sysarg_t *, suseconds_t);
 
-extern fid_t async_new_connection(sysarg_t, sysarg_t, ipc_callid_t,
-    ipc_call_t *, void (*)(ipc_callid_t, ipc_call_t *));
+extern fid_t async_new_connection(task_id_t, sysarg_t, ipc_callid_t,
+    ipc_call_t *, async_client_conn_t, void *);
+
 extern void async_usleep(suseconds_t);
 extern void async_create_manager(void);
@@ -102,9 +149,10 @@
 extern void async_set_client_data_constructor(async_client_data_ctor_t);
 extern void async_set_client_data_destructor(async_client_data_dtor_t);
-
-extern void *async_client_data_get(void);
+extern void *async_get_client_data(void);
+extern void *async_get_client_data_by_id(task_id_t);
+extern void async_put_client_data_by_id(task_id_t);
 
 extern void async_set_client_connection(async_client_conn_t);
-extern void async_set_interrupt_received(async_client_conn_t);
+extern void async_set_interrupt_received(async_interrupt_handler_t);
 
 /*
@@ -112,11 +160,12 @@
  */
 
-extern void async_msg_0(int, sysarg_t);
-extern void async_msg_1(int, sysarg_t, sysarg_t);
-extern void async_msg_2(int, sysarg_t, sysarg_t, sysarg_t);
-extern void async_msg_3(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
-extern void async_msg_4(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
-extern void async_msg_5(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+extern void async_msg_0(async_exch_t *, sysarg_t);
+extern void async_msg_1(async_exch_t *, sysarg_t, sysarg_t);
+extern void async_msg_2(async_exch_t *, sysarg_t, sysarg_t, sysarg_t);
+extern void async_msg_3(async_exch_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void async_msg_4(async_exch_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t);
+extern void async_msg_5(async_exch_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t);
 
 /*
@@ -138,8 +187,8 @@
  */
 
-extern int async_forward_fast(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
-    unsigned int);
-extern int async_forward_slow(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, sysarg_t, unsigned int);
+extern int async_forward_fast(ipc_callid_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,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t, unsigned int);
 
 /*
@@ -150,161 +199,160 @@
  */
 
-#define async_req_0_0(phoneid, method) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
-	    NULL)
-#define async_req_0_1(phoneid, method, r1) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
-	    NULL)
-#define async_req_0_2(phoneid, method, r1, r2) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
-	    NULL)
-#define async_req_0_3(phoneid, method, r1, r2, r3) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
-	    NULL)
-#define async_req_0_4(phoneid, method, r1, r2, r3, r4) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
-	    NULL)
-#define async_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
-	    (r5))
-#define async_req_1_0(phoneid, method, arg1) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
-	    NULL, NULL)
-#define async_req_1_1(phoneid, method, arg1, rc1) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
-	    NULL, NULL)
-#define async_req_1_2(phoneid, method, arg1, rc1, rc2) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
-	    NULL, NULL)
-#define async_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
-	    NULL, NULL)
-#define async_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
-	    (rc4), NULL)
-#define async_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
-	    (rc4), (rc5))
-#define async_req_2_0(phoneid, method, arg1, arg2) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
+#define async_req_0_0(exch, method) \
+	async_req_fast(exch, method, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)
+#define async_req_0_1(exch, method, r1) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, NULL, NULL, NULL, NULL)
+#define async_req_0_2(exch, method, r1, r2) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, r2, NULL, NULL, NULL)
+#define async_req_0_3(exch, method, r1, r2, r3) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, r2, r3, NULL, NULL)
+#define async_req_0_4(exch, method, r1, r2, r3, r4) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, r2, r3, r4, NULL)
+#define async_req_0_5(exch, method, r1, r2, r3, r4, r5) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, r2, r3, r4, r5)
+
+#define async_req_1_0(exch, method, arg1) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, NULL, NULL, NULL, NULL, \
+	    NULL)
+#define async_req_1_1(exch, method, arg1, rc1) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, NULL, NULL, NULL, \
+	    NULL)
+#define async_req_1_2(exch, method, arg1, rc1, rc2) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, rc2, NULL, NULL, \
+	    NULL)
+#define async_req_1_3(exch, method, arg1, rc1, rc2, rc3) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, rc2, rc3, NULL, \
+	    NULL)
+#define async_req_1_4(exch, method, arg1, rc1, rc2, rc3, rc4) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, rc2, rc3, rc4, \
+	    NULL)
+#define async_req_1_5(exch, method, arg1, rc1, rc2, rc3, rc4, rc5) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, rc2, rc3, rc4, \
+	    rc5)
+
+#define async_req_2_0(exch, method, arg1, arg2) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, NULL, NULL, NULL, \
+	    NULL, NULL)
+#define async_req_2_1(exch, method, arg1, arg2, rc1) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, NULL, NULL, \
+	    NULL, NULL)
+#define async_req_2_2(exch, method, arg1, arg2, rc1, rc2) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, rc2, NULL, NULL, \
+	    NULL)
+#define async_req_2_3(exch, method, arg1, arg2, rc1, rc2, rc3) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, rc2, rc3, NULL, \
+	    NULL)
+#define async_req_2_4(exch, method, arg1, arg2, rc1, rc2, rc3, rc4) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, rc2, rc3, rc4, \
+	    NULL)
+#define async_req_2_5(exch, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, rc2, rc3, rc4, \
+	    rc5)
+
+#define async_req_3_0(exch, method, arg1, arg2, arg3) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, NULL, NULL, NULL, \
+	    NULL, NULL)
+#define async_req_3_1(exch, method, arg1, arg2, arg3, rc1) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, NULL, NULL, \
+	    NULL, NULL)
+#define async_req_3_2(exch, method, arg1, arg2, arg3, rc1, rc2) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, rc2, NULL, \
+	    NULL, NULL)
+#define async_req_3_3(exch, method, arg1, arg2, arg3, rc1, rc2, rc3) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, rc2, rc3, \
+	    NULL, NULL)
+#define async_req_3_4(exch, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, rc2, rc3, \
+	    rc4, NULL)
+#define async_req_3_5(exch, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
+    rc5) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, rc2, rc3, \
+	    rc4, rc5)
+
+#define async_req_4_0(exch, method, arg1, arg2, arg3, arg4) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, NULL, NULL, \
 	    NULL, NULL, NULL)
-#define async_req_2_1(phoneid, method, arg1, arg2, rc1) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
+#define async_req_4_1(exch, method, arg1, arg2, arg3, arg4, rc1) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, NULL, \
 	    NULL, NULL, NULL)
-#define async_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+#define async_req_4_2(exch, method, arg1, arg2, arg3, arg4, rc1, rc2) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, NULL, \
+	    NULL, NULL)
+#define async_req_4_3(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+	    NULL, NULL)
+#define async_req_4_4(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+    rc4) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+	    rc4, NULL)
+#define async_req_4_5(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+    rc4, rc5) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+	    rc4, rc5)
+
+#define async_req_5_0(exch, method, arg1, arg2, arg3, arg4, arg5) \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, NULL, \
+	    NULL, NULL, NULL, NULL)
+#define async_req_5_1(exch, method, arg1, arg2, arg3, arg4, arg5, rc1) \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, \
+	    NULL, NULL, NULL, NULL)
+#define async_req_5_2(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
 	    NULL, NULL, NULL)
-#define async_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
-	    (rc3), NULL, NULL)
-#define async_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
-	    (rc3), (rc4), NULL)
-#define async_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
-	    (rc3), (rc4), (rc5))
-#define async_req_3_0(phoneid, method, arg1, arg2, arg3) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
-	    NULL, NULL, NULL)
-#define async_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    NULL, NULL, NULL, NULL)
-#define async_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    (rc2), NULL, NULL, NULL)
-#define async_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    (rc2), (rc3), NULL, NULL)
-#define async_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    (rc2), (rc3), (rc4), NULL)
-#define async_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
-    rc5) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    (rc2), (rc3), (rc4), (rc5))
-#define async_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
-	    NULL, NULL, NULL, NULL)
-#define async_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
-	    NULL, NULL, NULL, NULL)
-#define async_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
-	    (rc2), NULL, NULL, NULL)
-#define async_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
-	    (rc2), (rc3), NULL, NULL)
-#define async_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
-    rc4) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (rc1), (rc2), (rc3), (rc4), NULL)
-#define async_req_4_5(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
-    rc4, rc5) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (rc1), (rc2), (rc3), (rc4), (rc5))
-#define async_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), NULL, NULL, NULL, NULL, NULL)
-#define async_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), NULL, NULL, NULL, NULL)
-#define async_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), (rc2), NULL, NULL, NULL)
-#define async_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+#define async_req_5_3(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
     rc3) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), (rc2), (rc3), NULL, NULL)
-#define async_req_5_4(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	    rc3, NULL, NULL)
+#define async_req_5_4(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
     rc3, rc4) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), (rc2), (rc3), (rc4), NULL)
-#define async_req_5_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	    rc3, rc4, NULL)
+#define async_req_5_5(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
     rc3, rc4, rc5) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), (rc2), (rc3), (rc4), (rc5))
-
-extern sysarg_t async_req_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *);
-extern sysarg_t async_req_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	    rc3, rc4, rc5)
+
+extern sysarg_t async_req_fast(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *,
     sysarg_t *);
-
-static inline void async_serialize_start(void)
-{
-	fibril_inc_sercount();
-}
-
-static inline void async_serialize_end(void)
-{
-	fibril_dec_sercount();
-}
-
-extern int async_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t,
-    async_client_conn_t);
-extern int async_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
-extern int async_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
-extern int async_connect_kbox(task_id_t);
-extern int async_hangup(int);
+extern sysarg_t async_req_slow(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *,
+    sysarg_t *, sysarg_t *);
+
+extern async_sess_t *async_connect_me(exch_mgmt_t, async_exch_t *);
+extern async_sess_t *async_connect_me_to(exch_mgmt_t, async_exch_t *, sysarg_t,
+    sysarg_t, sysarg_t);
+extern async_sess_t *async_connect_me_to_blocking(exch_mgmt_t, async_exch_t *,
+    sysarg_t, sysarg_t, sysarg_t);
+extern async_sess_t *async_connect_kbox(task_id_t);
+
+extern int async_connect_to_me(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
+    async_client_conn_t, void *);
+
+extern int async_hangup(async_sess_t *);
 extern void async_poke(void);
 
+extern async_exch_t *async_exchange_begin(async_sess_t *);
+extern void async_exchange_end(async_exch_t *);
+
 /*
  * User-friendly wrappers for async_share_in_start().
  */
 
-#define async_share_in_start_0_0(phoneid, dst, size) \
-	async_share_in_start((phoneid), (dst), (size), 0, NULL)
-#define async_share_in_start_0_1(phoneid, dst, size, flags) \
-	async_share_in_start((phoneid), (dst), (size), 0, (flags))
-#define async_share_in_start_1_0(phoneid, dst, size, arg) \
-	async_share_in_start((phoneid), (dst), (size), (arg), NULL)
-#define async_share_in_start_1_1(phoneid, dst, size, arg, flags) \
-	async_share_in_start((phoneid), (dst), (size), (arg), (flags))
-
-extern int async_share_in_start(int, void *, size_t, sysarg_t, unsigned int *);
+#define async_share_in_start_0_0(exch, dst, size) \
+	async_share_in_start(exch, dst, size, 0, NULL)
+#define async_share_in_start_0_1(exch, dst, size, flags) \
+	async_share_in_start(exch, dst, size, 0, flags)
+#define async_share_in_start_1_0(exch, dst, size, arg) \
+	async_share_in_start(exch, dst, size, arg, NULL)
+#define async_share_in_start_1_1(exch, dst, size, arg, flags) \
+	async_share_in_start(exch, dst, size, arg, flags)
+
+extern int async_share_in_start(async_exch_t *, void *, size_t, sysarg_t,
+    unsigned int *);
 extern bool async_share_in_receive(ipc_callid_t *, size_t *);
 extern int async_share_in_finalize(ipc_callid_t, void *, unsigned int);
 
-extern int async_share_out_start(int, 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 *);
@@ -314,36 +362,37 @@
  */
 
-#define async_data_read_forward_0_0(phoneid, method, answer) \
-	async_data_read_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
-#define async_data_read_forward_0_1(phoneid, method, answer) \
-	async_data_read_forward_fast((phoneid), (method), 0, 0, 0, 0, (answer))
-#define async_data_read_forward_1_0(phoneid, method, arg1, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), 0, 0, 0, NULL)
-#define async_data_read_forward_1_1(phoneid, method, arg1, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), 0, 0, 0, (answer))
-#define async_data_read_forward_2_0(phoneid, method, arg1, arg2, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL)
-#define async_data_read_forward_2_1(phoneid, method, arg1, arg2, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
-	    (answer))
-#define async_data_read_forward_3_0(phoneid, method, arg1, arg2, arg3, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
-	    NULL)
-#define async_data_read_forward_3_1(phoneid, method, arg1, arg2, arg3, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
-	    (answer))
-#define async_data_read_forward_4_0(phoneid, method, arg1, arg2, arg3, arg4, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), NULL)
-#define async_data_read_forward_4_1(phoneid, method, arg1, arg2, arg3, arg4, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (answer))
-
-extern int async_data_read_start(int, void *, size_t);
+#define async_data_read_forward_0_0(exch, method, answer) \
+	async_data_read_forward_fast(exch, method, 0, 0, 0, 0, NULL)
+#define async_data_read_forward_0_1(exch, method, answer) \
+	async_data_read_forward_fast(exch, method, 0, 0, 0, 0, answer)
+#define async_data_read_forward_1_0(exch, method, arg1, answer) \
+	async_data_read_forward_fast(exch, method, arg1, 0, 0, 0, NULL)
+#define async_data_read_forward_1_1(exch, method, arg1, answer) \
+	async_data_read_forward_fast(exch, method, arg1, 0, 0, 0, answer)
+#define async_data_read_forward_2_0(exch, method, arg1, arg2, answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, 0, 0, NULL)
+#define async_data_read_forward_2_1(exch, method, arg1, arg2, answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, 0, 0, answer)
+#define async_data_read_forward_3_0(exch, method, arg1, arg2, arg3, answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, arg3, 0, NULL)
+#define async_data_read_forward_3_1(exch, method, arg1, arg2, arg3, answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, arg3, 0, \
+	    answer)
+#define async_data_read_forward_4_0(exch, method, arg1, arg2, arg3, arg4, \
+    answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, arg3, arg4, \
+	    NULL)
+#define async_data_read_forward_4_1(exch, method, arg1, arg2, arg3, arg4, \
+    answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, arg3, arg4, \
+	    answer)
+
+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 int async_data_read_finalize(ipc_callid_t, const void *, size_t);
 
-extern int async_data_read_forward_fast(int, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, ipc_call_t *);
+extern int async_data_read_forward_fast(async_exch_t *, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, ipc_call_t *);
 
 /*
@@ -351,33 +400,32 @@
  */
 
-#define async_data_write_forward_0_0(phoneid, method, answer) \
-	async_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
-#define async_data_write_forward_0_1(phoneid, method, answer) \
-	async_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, (answer))
-#define async_data_write_forward_1_0(phoneid, method, arg1, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, NULL)
-#define async_data_write_forward_1_1(phoneid, method, arg1, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, \
-	    (answer))
-#define async_data_write_forward_2_0(phoneid, method, arg1, arg2, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
-	    NULL)
-#define async_data_write_forward_2_1(phoneid, method, arg1, arg2, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
-	    (answer))
-#define async_data_write_forward_3_0(phoneid, method, arg1, arg2, arg3, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    0, NULL)
-#define async_data_write_forward_3_1(phoneid, method, arg1, arg2, arg3, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    0, (answer))
-#define async_data_write_forward_4_0(phoneid, method, arg1, arg2, arg3, arg4, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), NULL)
-#define async_data_write_forward_4_1(phoneid, method, arg1, arg2, arg3, arg4, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (answer))
-
-extern int async_data_write_start(int, const void *, size_t);
+#define async_data_write_forward_0_0(exch, method, answer) \
+	async_data_write_forward_fast(exch, method, 0, 0, 0, 0, NULL)
+#define async_data_write_forward_0_1(exch, method, answer) \
+	async_data_write_forward_fast(exch, method, 0, 0, 0, 0, answer)
+#define async_data_write_forward_1_0(exch, method, arg1, answer) \
+	async_data_write_forward_fast(exch, method, arg1, 0, 0, 0, NULL)
+#define async_data_write_forward_1_1(exch, method, arg1, answer) \
+	async_data_write_forward_fast(exch, method, arg1, 0, 0, 0, answer)
+#define async_data_write_forward_2_0(exch, method, arg1, arg2, answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, 0, 0, NULL)
+#define async_data_write_forward_2_1(exch, method, arg1, arg2, answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, 0, 0, answer)
+#define async_data_write_forward_3_0(exch, method, arg1, arg2, arg3, answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, arg3, 0, \
+	    NULL)
+#define async_data_write_forward_3_1(exch, method, arg1, arg2, arg3, answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, arg3, 0, \
+	    answer)
+#define async_data_write_forward_4_0(exch, method, arg1, arg2, arg3, arg4, \
+    answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, arg3, arg4, \
+	    NULL)
+#define async_data_write_forward_4_1(exch, method, arg1, arg2, arg3, arg4, \
+    answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, arg3, arg4, \
+	    answer)
+
+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 int async_data_write_finalize(ipc_callid_t, void *, size_t);
@@ -387,6 +435,22 @@
 extern void async_data_write_void(sysarg_t);
 
-extern int async_data_write_forward_fast(int, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, ipc_call_t *);
+extern int async_data_write_forward_fast(async_exch_t *, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, ipc_call_t *);
+
+extern int async_exchange_clone(async_exch_t *, async_exch_t *);
+extern async_sess_t *async_clone_receive(exch_mgmt_t);
+extern async_sess_t *async_callback_receive(exch_mgmt_t);
+extern async_sess_t *async_callback_receive_start(exch_mgmt_t, ipc_call_t *);
+
+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 *,
+    sysarg_t *);
+extern int async_state_change_finalize(ipc_callid_t, async_exch_t *);
+
+extern void *async_remote_state_acquire(async_sess_t *);
+extern void async_remote_state_update(async_sess_t *, void *);
+extern void async_remote_state_release(async_sess_t *);
+extern void async_remote_state_release_exchange(async_exch_t *);
 
 #endif
Index: uspace/lib/c/include/async_obsolete.h
===================================================================
--- uspace/lib/c/include/async_obsolete.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/async_obsolete.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#if ((defined(LIBC_IPC_H_)) && (!defined(LIBC_ASYNC_OBSOLETE_C_)))
+	#error Do not intermix low-level IPC interface and async framework
+#endif
+
+#ifndef LIBC_ASYNC_OBSOLETE_H_
+#define LIBC_ASYNC_OBSOLETE_H_
+
+#define async_obsolete_send_0(phoneid, method, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
+#define async_obsolete_send_1(phoneid, method, arg1, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
+#define async_obsolete_send_2(phoneid, method, arg1, arg2, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
+#define async_obsolete_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
+#define async_obsolete_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (dataptr))
+#define async_obsolete_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
+	async_obsolete_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (dataptr))
+
+extern aid_t async_obsolete_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr);
+extern aid_t async_obsolete_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
+    ipc_call_t *dataptr);
+
+#define async_obsolete_req_0_0(phoneid, method) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
+	    NULL)
+#define async_obsolete_req_0_1(phoneid, method, r1) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
+	    NULL)
+#define async_obsolete_req_0_2(phoneid, method, r1, r2) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
+	    NULL)
+#define async_obsolete_req_0_3(phoneid, method, r1, r2, r3) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
+	    NULL)
+#define async_obsolete_req_0_4(phoneid, method, r1, r2, r3, r4) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
+	    NULL)
+#define async_obsolete_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
+	    (r5))
+#define async_obsolete_req_1_0(phoneid, method, arg1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
+	    NULL, NULL)
+#define async_obsolete_req_1_1(phoneid, method, arg1, rc1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
+	    NULL, NULL)
+#define async_obsolete_req_1_2(phoneid, method, arg1, rc1, rc2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
+	    NULL, NULL)
+#define async_obsolete_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
+	    NULL, NULL)
+#define async_obsolete_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
+	    (rc4), NULL)
+#define async_obsolete_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
+	    (rc4), (rc5))
+#define async_obsolete_req_2_0(phoneid, method, arg1, arg2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
+	    NULL, NULL, NULL)
+#define async_obsolete_req_2_1(phoneid, method, arg1, arg2, rc1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
+	    NULL, NULL, NULL)
+#define async_obsolete_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+	    NULL, NULL, NULL)
+#define async_obsolete_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+	    (rc3), NULL, NULL)
+#define async_obsolete_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+	    (rc3), (rc4), NULL)
+#define async_obsolete_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+	    (rc3), (rc4), (rc5))
+#define async_obsolete_req_3_0(phoneid, method, arg1, arg2, arg3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
+	    NULL, NULL, NULL)
+#define async_obsolete_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    NULL, NULL, NULL, NULL)
+#define async_obsolete_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    (rc2), NULL, NULL, NULL)
+#define async_obsolete_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    (rc2), (rc3), NULL, NULL)
+#define async_obsolete_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    (rc2), (rc3), (rc4), NULL)
+#define async_obsolete_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
+    rc5) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    (rc2), (rc3), (rc4), (rc5))
+#define async_obsolete_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
+	    NULL, NULL, NULL, NULL)
+#define async_obsolete_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
+	    NULL, NULL, NULL, NULL)
+#define async_obsolete_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
+	    (rc2), NULL, NULL, NULL)
+#define async_obsolete_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
+	    (rc2), (rc3), NULL, NULL)
+#define async_obsolete_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+    rc4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (rc1), (rc2), (rc3), (rc4), NULL)
+#define async_obsolete_req_4_5(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+    rc4, rc5) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (rc1), (rc2), (rc3), (rc4), (rc5))
+#define async_obsolete_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), NULL, NULL, NULL, NULL, NULL)
+#define async_obsolete_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), NULL, NULL, NULL, NULL)
+#define async_obsolete_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), (rc2), NULL, NULL, NULL)
+#define async_obsolete_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+    rc3) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), (rc2), (rc3), NULL, NULL)
+#define async_obsolete_req_5_4(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+    rc3, rc4) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), (rc2), (rc3), (rc4), NULL)
+#define async_obsolete_req_5_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+    rc3, rc4, rc5) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), (rc2), (rc3), (rc4), (rc5))
+
+extern sysarg_t async_obsolete_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
+    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5);
+extern sysarg_t async_obsolete_req_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
+    sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5);
+
+extern void async_obsolete_msg_0(int, sysarg_t);
+extern void async_obsolete_msg_1(int, sysarg_t, sysarg_t);
+extern void async_obsolete_msg_2(int, sysarg_t, sysarg_t, sysarg_t);
+extern void async_obsolete_msg_3(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void async_obsolete_msg_4(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void async_obsolete_msg_5(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t);
+
+extern int async_obsolete_forward_slow(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, unsigned int);
+
+extern int async_obsolete_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t,
+    async_client_conn_t, void *);
+extern int async_obsolete_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
+extern int async_obsolete_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
+extern int async_obsolete_hangup(int);
+
+#define async_obsolete_share_in_start_0_0(phoneid, dst, size) \
+	async_obsolete_share_in_start((phoneid), (dst), (size), 0, NULL)
+#define async_obsolete_share_in_start_0_1(phoneid, dst, size, flags) \
+	async_obsolete_share_in_start((phoneid), (dst), (size), 0, (flags))
+#define async_obsolete_share_in_start_1_0(phoneid, dst, size, arg) \
+	async_obsolete_share_in_start((phoneid), (dst), (size), (arg), NULL)
+#define async_obsolete_share_in_start_1_1(phoneid, dst, size, arg, flags) \
+	async_obsolete_share_in_start((phoneid), (dst), (size), (arg), (flags))
+
+extern int async_obsolete_share_in_start(int, void *, size_t, sysarg_t,
+    unsigned int *);
+extern int async_obsolete_share_out_start(int, void *, unsigned int);
+
+#define async_obsolete_data_write_start(p, buf, len) \
+	async_obsolete_data_write_start_generic((p), (buf), (len), IPC_XF_NONE)
+
+#define async_obsolete_data_read_start(p, buf, len) \
+	async_obsolete_data_read_start_generic((p), (buf), (len), IPC_XF_NONE)
+
+#define async_obsolete_data_write_forward_0_0(phoneid, method, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
+#define async_obsolete_data_write_forward_0_1(phoneid, method, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, (answer))
+#define async_obsolete_data_write_forward_1_0(phoneid, method, arg1, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, NULL)
+#define async_obsolete_data_write_forward_1_1(phoneid, method, arg1, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, \
+	    (answer))
+#define async_obsolete_data_write_forward_2_0(phoneid, method, arg1, arg2, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
+	    NULL)
+#define async_obsolete_data_write_forward_2_1(phoneid, method, arg1, arg2, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
+	    (answer))
+#define async_obsolete_data_write_forward_3_0(phoneid, method, arg1, arg2, arg3, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    0, NULL)
+#define async_obsolete_data_write_forward_3_1(phoneid, method, arg1, arg2, arg3, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    0, (answer))
+#define async_obsolete_data_write_forward_4_0(phoneid, method, arg1, arg2, arg3, arg4, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    (arg4), NULL)
+#define async_obsolete_data_write_forward_4_1(phoneid, method, arg1, arg2, arg3, arg4, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    (arg4), (answer))
+
+extern aid_t async_obsolete_data_read(int, void *, size_t, ipc_call_t *);
+extern int async_obsolete_data_read_start_generic(int, void *, size_t, int);
+
+extern int async_obsolete_data_write_start_generic(int, const void *, size_t, int);
+extern void async_obsolete_data_write_void(const int);
+
+extern int async_obsolete_forward_fast(ipc_callid_t, int, sysarg_t, sysarg_t,
+    sysarg_t, unsigned int);
+
+extern int async_obsolete_data_write_forward_fast(int, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, ipc_call_t *);
+
+#endif
+
+/** @}
+ */
Index: pace/lib/c/include/async_sess.h
===================================================================
--- uspace/lib/c/include/async_sess.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2010 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ASYNC_SESS_H_
-#define LIBC_ASYNC_SESS_H_
-
-#include <adt/list.h>
-
-typedef struct {
-	int sess_phone;		/**< Phone for cloning off the connections. */
-	sysarg_t connect_arg1;  /**< Argument for CONNECT_ME_TO. */
-	link_t conn_head;	/**< List of open data connections. */
-	link_t sess_link;	/**< Link in global list of open sessions. */
-} async_sess_t;
-
-extern void async_session_create(async_sess_t *, int, sysarg_t);
-extern void async_session_destroy(async_sess_t *);
-extern int async_exchange_begin(async_sess_t *);
-extern void async_exchange_end(async_sess_t *, int);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/bitops.h
===================================================================
--- uspace/lib/c/include/bitops.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/bitops.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,19 @@
 #include <sys/types.h>
 
+/** Mask with bit @a n set. */
+#define BIT_V(type, n) \
+    ((type)1 << ((n) - 1))
+
+/** Mask with rightmost @a n bits set. */
+#define BIT_RRANGE(type, n) \
+    (BIT_V(type, (n) + 1) - 1)
+
+/** Mask with bits @a hi .. @a lo set. @a hi >= @a lo. */
+#define BIT_RANGE(type, hi, lo) \
+    (BIT_RRANGE(type, (hi) - (lo) + 1) << (lo))
+
+/** Extract range of bits @a hi .. @a lo from @a value. */
+#define BIT_RANGE_EXTRACT(type, hi, lo, value) \
+    (((value) >> (lo)) & BIT_RRANGE(type, (hi) - (lo) + 1))
 
 /** Return position of first non-zero bit from left (i.e. [log_2(arg)]).
Index: uspace/lib/c/include/ddi.h
===================================================================
--- uspace/lib/c/include/ddi.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ddi.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 
 #include <sys/types.h>
-#include <kernel/ddi/irq.h>
+#include <abi/ddi/irq.h>
 #include <task.h>
 
Index: uspace/lib/c/include/device/char_dev.h
===================================================================
--- uspace/lib/c/include/device/char_dev.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/device/char_dev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,4 +36,6 @@
 #define LIBC_DEVICE_CHAR_DEV_H_
 
+#include <async.h>
+
 typedef enum {
 	CHAR_DEV_READ = 0,
@@ -41,6 +43,6 @@
 } char_dev_method_t;
 
-ssize_t char_dev_read(int dev_phone, void *buf, size_t len);
-ssize_t char_dev_write(int dev_phone, void *buf, size_t len);
+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/c/include/device/hw_res.h
===================================================================
--- uspace/lib/c/include/device/hw_res.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/device/hw_res.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -26,5 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
- 
+
 /** @addtogroup libc
  * @{
@@ -32,9 +32,10 @@
 /** @file
  */
- 
+
 #ifndef LIBC_DEVICE_HW_RES_H_
 #define LIBC_DEVICE_HW_RES_H_
 
 #include <ipc/dev_iface.h>
+#include <async.h>
 #include <bool.h>
 
@@ -48,5 +49,5 @@
 typedef enum {
 	INTERRUPT,
-	IO_RANGE, 
+	IO_RANGE,
 	MEM_RANGE
 } hw_res_type_t;
@@ -66,5 +67,5 @@
 			size_t size;
 		} mem_range;
-
+		
 		struct {
 			uint64_t address;
@@ -72,5 +73,5 @@
 			size_t size;
 		} io_range;
-
+		
 		struct {
 			int irq;
@@ -88,13 +89,12 @@
 	if (hw_res->resources != NULL) {
 		free(hw_res->resources);
-
 		hw_res->resources = NULL;
 	}
-
+	
 	hw_res->count = 0;
 }
 
-extern int hw_res_get_resource_list(int, hw_resource_list_t *);
-extern bool hw_res_enable_interrupt(int);
+extern int hw_res_get_resource_list(async_sess_t *, hw_resource_list_t *);
+extern bool hw_res_enable_interrupt(async_sess_t *);
 
 #endif
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/devman.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,21 +38,32 @@
 
 #include <ipc/devman.h>
+#include <ipc/loc.h>
 #include <async.h>
 #include <bool.h>
 
-extern int devman_get_phone(devman_interface_t, unsigned int);
-extern void devman_hangup_phone(devman_interface_t);
+extern async_exch_t *devman_exchange_begin_blocking(devman_interface_t);
+extern async_exch_t *devman_exchange_begin(devman_interface_t);
+extern void devman_exchange_end(async_exch_t *);
 
 extern int devman_driver_register(const char *, async_client_conn_t);
 extern int devman_add_function(const char *, fun_type_t, match_id_list_t *,
     devman_handle_t, devman_handle_t *);
+extern int devman_remove_function(devman_handle_t);
 
-extern int devman_device_connect(devman_handle_t, unsigned int);
-extern int devman_parent_device_connect(devman_handle_t, unsigned int);
-
-extern int devman_device_get_handle(const char *, devman_handle_t *,
+extern async_sess_t *devman_device_connect(exch_mgmt_t, devman_handle_t,
+    unsigned int);
+extern async_sess_t *devman_parent_device_connect(exch_mgmt_t, devman_handle_t,
     unsigned int);
 
-extern int devman_add_device_to_class(devman_handle_t, const char *);
+extern int devman_fun_get_handle(const char *, devman_handle_t *,
+    unsigned int);
+extern int devman_fun_get_child(devman_handle_t, devman_handle_t *);
+extern int devman_dev_get_functions(devman_handle_t, devman_handle_t **,
+    size_t *);
+extern int devman_fun_get_name(devman_handle_t, char *, size_t);
+extern int devman_fun_get_path(devman_handle_t, char *, size_t);
+
+extern int devman_add_device_to_category(devman_handle_t, const char *);
+extern int devman_fun_sid_to_handle(service_id_t, devman_handle_t *);
 
 #endif
Index: pace/lib/c/include/devmap.h
===================================================================
--- uspace/lib/c/include/devmap.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,67 +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 libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_DEVMAP_H_
-#define LIBC_DEVMAP_H_
-
-#include <ipc/devmap.h>
-#include <async.h>
-#include <bool.h>
-
-extern int devmap_get_phone(devmap_interface_t, unsigned int);
-extern void devmap_hangup_phone(devmap_interface_t iface);
-
-extern int devmap_driver_register(const char *, async_client_conn_t);
-extern int devmap_device_register(const char *, devmap_handle_t *);
-extern int devmap_device_register_with_iface(const char *, devmap_handle_t *, sysarg_t);
-
-extern int devmap_device_get_handle(const char *, devmap_handle_t *, unsigned int);
-extern int devmap_namespace_get_handle(const char *, devmap_handle_t *, unsigned int);
-extern devmap_handle_type_t devmap_handle_probe(devmap_handle_t);
-
-extern int devmap_device_connect(devmap_handle_t, unsigned int);
-
-extern int devmap_null_create(void);
-extern void devmap_null_destroy(int);
-
-extern size_t devmap_count_namespaces(void);
-extern size_t devmap_count_devices(devmap_handle_t);
-
-extern size_t devmap_get_namespaces(dev_desc_t **);
-extern size_t devmap_get_devices(devmap_handle_t, dev_desc_t **);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/dlfcn.h
===================================================================
--- uspace/lib/c/include/dlfcn.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/dlfcn.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+/*
+ * 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 rtld
+ * @{
+ */
+/** @file
+ * @brief UNIX-like dynamic linker interface.
+ */
+
+#ifndef LIBC_DLFCN_H_
+#define LIBC_DLFCN_H_
+
+void *dlopen(const char *, int);
+void *dlsym(void *, const char *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/c/include/elf/elf.h
===================================================================
--- uspace/lib/c/include/elf/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/elf/elf.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ELF_H_
+#define LIBC_ELF_H_
+
+#include <sys/types.h>
+#include <abi/elf.h>
+#include <libarch/elf.h>
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/elf/elf_linux.h
===================================================================
--- uspace/lib/c/include/elf/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/elf/elf_linux.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup generic
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ELF_LINUX_H_
+#define LIBC_ELF_LINUX_H_
+
+#include <elf/elf.h>
+#include <libarch/elf_linux.h>
+
+/*
+ * Note types
+ */
+#define NT_PRSTATUS	1
+
+typedef int pid_t;
+typedef struct {
+	long tv_sec;
+	long tv_usec;
+} linux_timeval_t;
+
+typedef struct {
+	int sig_info[3];
+	short cursig;
+	unsigned long sigpend;
+	unsigned long sighold;
+	pid_t pid;
+	pid_t ppid;
+	pid_t pgrp;
+	pid_t sid;
+	linux_timeval_t pr_utime;
+	linux_timeval_t pr_stime;
+	linux_timeval_t pr_cutime;
+	linux_timeval_t pr_sid;
+	elf_regs_t regs;
+	int fpvalid;
+} elf_prstatus_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/elf/elf_load.h
===================================================================
--- uspace/lib/c/include/elf/elf_load.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/elf/elf_load.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2006 Sergey Bondari
+ * 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 generic
+ * @{
+ */
+/** @file
+ * @brief ELF loader structures and public functions.
+ */
+
+#ifndef ELF_LOAD_H_
+#define ELF_LOAD_H_
+
+#include <elf/elf.h>
+#include <sys/types.h>
+#include <loader/pcb.h>
+
+/**
+ * ELF error return codes
+ */
+#define EE_OK			0	/* No error */
+#define EE_INVALID		1	/* Invalid ELF image */
+#define EE_MEMORY		2	/* Cannot allocate address space */
+#define EE_INCOMPATIBLE		3	/* ELF image is not compatible with current architecture */
+#define EE_UNSUPPORTED		4	/* Non-supported ELF (e.g. dynamic ELFs) */
+#define EE_LOADER		5	/* The image is actually a program loader. */
+#define EE_IRRECOVERABLE	6
+
+typedef enum {
+	/** Leave all segments in RW access mode. */
+	ELDF_RW = 1
+} eld_flags_t;
+
+/**
+ * Some data extracted from the headers are stored here
+ */
+typedef struct {
+	/** Entry point */
+	entry_point_t entry;
+
+	/** ELF interpreter name or NULL if statically-linked */
+	const char *interp;
+
+	/** Pointer to the dynamic section */
+	void *dynamic;
+} elf_info_t;
+
+/**
+ * Holds information about an ELF binary being loaded.
+ */
+typedef struct {
+	/** Filedescriptor of the file from which we are loading */
+	int fd;
+
+	/** Difference between run-time addresses and link-time addresses */
+	uintptr_t bias;
+
+	/** Flags passed to the ELF loader. */
+	eld_flags_t flags;
+
+	/** A copy of the ELF file header */
+	elf_header_t *header;
+
+	/** Store extracted info here */
+	elf_info_t *info;
+} elf_ld_t;
+
+extern const char *elf_error(unsigned int);
+extern int elf_load_file(const char *, size_t, eld_flags_t, elf_info_t *);
+extern void elf_create_pcb(elf_info_t *, pcb_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/entry_point.h
===================================================================
--- uspace/lib/c/include/entry_point.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/entry_point.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_ENTRY_POINT_H_
+#define LIBC_ENTRY_POINT_H_
+
+/* Defined in arch/ARCH/src/entryjmp.[c|s] */
+void entry_point_jmp(void *, void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/errno.h
===================================================================
--- uspace/lib/c/include/errno.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/errno.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,10 +36,10 @@
 #define LIBC_ERRNO_H_
 
-#include <kernel/errno.h>
+#include <abi/errno.h>
 #include <fibril.h>
 
-#define errno _errno
+#define errno  (*(__errno()))
 
-extern int _errno;
+extern int *__errno(void) __attribute__((const));
 
 #define EMFILE        (-18)
@@ -55,4 +55,16 @@
 #define EIO           (-265)
 #define EMLINK        (-266)
+
+/** Bad checksum. */
+#define EBADCHECKSUM  (-300)
+
+/** USB: stalled operation. */
+#define ESTALL (-301)
+
+/** Empty resource (no data). */
+#define EEMPTY (-302)
+
+/** Negative acknowledgment. */
+#define ENAK (-303)
 
 /** An API function is called while another blocking function is in progress. */
Index: uspace/lib/c/include/event.h
===================================================================
--- uspace/lib/c/include/event.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/event.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,7 +36,11 @@
 #define LIBC_EVENT_H_
 
-#include <kernel/ipc/event_types.h>
+#include <abi/ipc/event.h>
+#include <libarch/types.h>
 
 extern int event_subscribe(event_type_t, sysarg_t);
+extern int event_task_subscribe(event_task_type_t, sysarg_t);
+extern int event_unmask(event_type_t);
+extern int event_task_unmask(event_task_type_t);
 
 #endif
Index: uspace/lib/c/include/fibril.h
===================================================================
--- uspace/lib/c/include/fibril.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/fibril.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -70,9 +70,9 @@
 	int (*func)(void *);
 	tcb_t *tcb;
-
+	
 	struct fibril *clean_after_me;
 	int retval;
 	int flags;
-
+	
 	fibril_owner_info_t *waits_for;
 } fibril_t;
Index: uspace/lib/c/include/fibril_synch.h
===================================================================
--- uspace/lib/c/include/fibril_synch.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/fibril_synch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,14 +36,14 @@
 #define LIBC_FIBRIL_SYNCH_H_
 
-#include <async.h>
 #include <fibril.h>
 #include <adt/list.h>
 #include <libarch/tls.h>
 #include <sys/time.h>
+#include <bool.h>
 
 typedef struct {
-	fibril_owner_info_t oi;		/* Keep this the first thing. */
+	fibril_owner_info_t oi;  /**< Keep this the first thing. */
 	int counter;
-	link_t waiters;
+	list_t waiters;
 } fibril_mutex_t;
 
@@ -55,6 +55,8 @@
 		.counter = 1, \
 		.waiters = { \
-			.prev = &name.waiters, \
-			.next = &name.waiters, \
+			.head = { \
+				.prev = &(name).waiters.head, \
+				.next = &(name).waiters.head, \
+			} \
 		} \
 	}
@@ -64,8 +66,8 @@
 
 typedef struct {
-	fibril_owner_info_t oi;	/* Keep this the first thing. */
+	fibril_owner_info_t oi;  /**< Keep this the first thing. */
 	unsigned writers;
 	unsigned readers;
-	link_t waiters;
+	list_t waiters;
 } fibril_rwlock_t;
 
@@ -78,6 +80,8 @@
 		.writers = 0, \
 		.waiters = { \
-			.prev = &name.waiters, \
-			.next = &name.waiters, \
+			.head = { \
+				.prev = &(name).waiters.head, \
+				.next = &(name).waiters.head, \
+			} \
 		} \
 	}
@@ -87,5 +91,5 @@
 
 typedef struct {
-	link_t waiters;
+	list_t waiters;
 } fibril_condvar_t;
 
@@ -93,6 +97,8 @@
 	{ \
 		.waiters = { \
-			.next = &name.waiters, \
-			.prev = &name.waiters, \
+			.head = { \
+				.next = &(name).waiters.head, \
+				.prev = &(name).waiters.head, \
+			} \
 		} \
 	}
Index: uspace/lib/c/include/fourcc.h
===================================================================
--- uspace/lib/c/include/fourcc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/fourcc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_FOURCC_H_
+#define LIBC_FOURCC_H_
+
+#include <libarch/common.h>
+
+#define FOURCC(a, b, c, d) \
+	(((UINT32_T) (a)) | (((UINT32_T) (b)) << 8) | \
+	    (((UINT32_T) (c)) << 16) | (((UINT32_T) (d)) << 24))
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/console.h
===================================================================
--- uspace/lib/c/include/io/console.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/io/console.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,10 +36,8 @@
 #define LIBC_IO_CONSOLE_H_
 
+#include <sys/time.h>
+#include <async.h>
 #include <bool.h>
-
-typedef enum {
-	KEY_PRESS,
-	KEY_RELEASE
-} console_ev_type_t;
+#include <stdio.h>
 
 typedef enum {
@@ -50,8 +48,34 @@
 } console_caps_t;
 
+/** Console control structure. */
+typedef struct {
+	/** Console input file */
+	FILE *input;
+	
+	/** Console output file */
+	FILE *output;
+	
+	/** Console input session */
+	async_sess_t *input_sess;
+	
+	/** Console output session */
+	async_sess_t *output_sess;
+	
+	/** Input request call with timeout */
+	ipc_call_t input_call;
+	
+	/** Input response with timeout */
+	aid_t input_aid;
+} console_ctrl_t;
+
+typedef enum {
+	KEY_PRESS,
+	KEY_RELEASE
+} kbd_event_type_t;
+
 /** Console event structure. */
 typedef struct {
 	/** Press or release event. */
-	console_ev_type_t type;
+	kbd_event_type_t type;
 	
 	/** Keycode of the key that was pressed or released. */
@@ -63,22 +87,26 @@
 	/** The character that was generated or '\0' for none. */
 	wchar_t c;
-} console_event_t;
+} kbd_event_t;
 
-extern void console_clear(int phone);
+extern console_ctrl_t *console_init(FILE *, FILE *);
+extern void console_done(console_ctrl_t *);
+extern bool console_kcon(void);
 
-extern int console_get_size(int phone, sysarg_t *cols, sysarg_t *rows);
-extern int console_get_pos(int phone, sysarg_t *col, sysarg_t *row);
-extern void console_set_pos(int phone, sysarg_t col, sysarg_t row);
+extern void console_flush(console_ctrl_t *);
+extern void console_clear(console_ctrl_t *);
 
-extern void console_set_style(int phone, uint8_t style);
-extern void console_set_color(int phone, uint8_t fg_color, uint8_t bg_color,
-    uint8_t flags);
-extern void console_set_rgb_color(int phone, uint32_t fg_color, uint32_t bg_color);
+extern int console_get_size(console_ctrl_t *, sysarg_t *, sysarg_t *);
+extern int console_get_pos(console_ctrl_t *, sysarg_t *, sysarg_t *);
+extern void console_set_pos(console_ctrl_t *, sysarg_t, sysarg_t);
 
-extern void console_cursor_visibility(int phone, bool show);
-extern int console_get_color_cap(int phone, sysarg_t *ccap);
-extern void console_kcon_enable(int phone);
+extern void console_set_style(console_ctrl_t *, uint8_t);
+extern void console_set_color(console_ctrl_t *, uint8_t, uint8_t, uint8_t);
+extern void console_set_rgb_color(console_ctrl_t *, uint32_t, uint32_t);
 
-extern bool console_get_event(int phone, console_event_t *event);
+extern void console_cursor_visibility(console_ctrl_t *, bool);
+extern int console_get_color_cap(console_ctrl_t *, sysarg_t *);
+extern bool console_get_kbd_event(console_ctrl_t *, kbd_event_t *);
+extern bool console_get_kbd_event_timeout(console_ctrl_t *, kbd_event_t *,
+    suseconds_t *);
 
 #endif
Index: uspace/lib/c/include/io/klog.h
===================================================================
--- uspace/lib/c/include/io/klog.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/io/klog.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,7 +37,10 @@
 
 #include <sys/types.h>
+#include <stdarg.h>
 
 extern size_t klog_write(const void *, size_t);
 extern void klog_update(void);
+extern int klog_printf(const char *, ...);
+extern int klog_vprintf(const char *, va_list);
 
 #endif
Index: uspace/lib/c/include/io/log.h
===================================================================
--- uspace/lib/c/include/io/log.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/io/log.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+
+#ifndef LIBC_IO_LOG_H_
+#define LIBC_IO_LOG_H_
+
+#include <stdarg.h>
+
+typedef enum {
+	LVL_FATAL,
+	LVL_ERROR,
+	LVL_WARN,
+	LVL_NOTE,
+	LVL_DEBUG,
+	LVL_DEBUG2,
+
+	/** For checking range of values */
+	LVL_LIMIT
+} log_level_t;
+
+extern int log_init(const char *, log_level_t);
+extern void log_msg(log_level_t, const char *, ...);
+extern void log_msgv(log_level_t, const char *, va_list);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ipc/clipboard.h
===================================================================
--- uspace/lib/c/include/ipc/clipboard.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/clipboard.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,4 +36,6 @@
 #define LIBC_IPC_CLIPBOARD_H_
 
+#include <ipc/common.h>
+
 typedef enum {
 	CLIPBOARD_PUT_DATA = IPC_FIRST_USER_METHOD,
Index: uspace/lib/c/include/ipc/common.h
===================================================================
--- uspace/lib/c/include/ipc/common.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/common.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,6 +37,7 @@
 
 #include <sys/types.h>
+#include <abi/ipc/ipc.h>
 #include <atomic.h>
-#include <kernel/ipc/ipc.h>
+#include <task.h>
 
 #define IPC_FLAG_BLOCKING  0x01
@@ -44,5 +45,5 @@
 typedef struct {
 	sysarg_t args[IPC_CALL_LEN];
-	sysarg_t in_task_hash;
+	task_id_t in_task_id;
 	sysarg_t in_phone_hash;
 } ipc_call_t;
Index: uspace/lib/c/include/ipc/console.h
===================================================================
--- uspace/lib/c/include/ipc/console.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/console.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -48,6 +48,5 @@
 	CONSOLE_SET_COLOR,
 	CONSOLE_SET_RGB_COLOR,
-	CONSOLE_CURSOR_VISIBILITY,
-	CONSOLE_KCON_ENABLE
+	CONSOLE_CURSOR_VISIBILITY
 } console_request_t;
 
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,4 +37,15 @@
 	HW_RES_DEV_IFACE = 0,
 	CHAR_DEV_IFACE,
+
+	/** Interface provided by any PCI device. */
+	PCI_DEV_IFACE,
+
+	/** Interface provided by any USB device. */
+	USB_DEV_IFACE,
+	/** Interface provided by USB host controller. */
+	USBHC_DEV_IFACE,
+	/** Interface provided by USB HID devices. */
+	USBHID_DEV_IFACE,
+
 	DEV_IFACE_MAX
 } dev_inferface_idx_t;
@@ -48,4 +59,14 @@
 	DEV_IFACE_ID(DEV_FIRST_CUSTOM_METHOD_IDX)
 
+/*
+ * The first argument is actually method (as the "real" method is used
+ * for indexing into interfaces.
+ */
+
+#define DEV_IPC_GET_ARG1(call) IPC_GET_ARG2((call))
+#define DEV_IPC_GET_ARG2(call) IPC_GET_ARG3((call))
+#define DEV_IPC_GET_ARG3(call) IPC_GET_ARG4((call))
+#define DEV_IPC_GET_ARG4(call) IPC_GET_ARG5((call))
+
 
 #endif
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/devman.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -72,5 +72,5 @@
  */
 typedef struct match_id_list {
-	link_t ids;
+	list_t ids;
 } match_id_list_t;
 
@@ -95,11 +95,11 @@
 {
 	match_id_t *mid = NULL;
-	link_t *link = ids->ids.next;
+	link_t *link = ids->ids.head.next;
 	
-	while (link != &ids->ids) {
+	while (link != &ids->ids.head) {
 		mid = list_get_instance(link, match_id_t,link);
 		if (mid->score < id->score) {
 			break;
-		}	
+		}
 		link = link->next;
 	}
@@ -118,10 +118,10 @@
 	match_id_t *id;
 	
-	while(!list_empty(&ids->ids)) {
-		link = ids->ids.next;
-		list_remove(link);		
+	while (!list_empty(&ids->ids)) {
+		link = list_first(&ids->ids);
+		list_remove(link);
 		id = list_get_instance(link, match_id_t, link);
-		delete_match_id(id);		
-	}	
+		delete_match_id(id);
+	}
 }
 
@@ -130,5 +130,5 @@
 	DEVMAN_CLIENT,
 	DEVMAN_CONNECT_TO_DEVICE,
-	DEVMAN_CONNECT_FROM_DEVMAP,
+	DEVMAN_CONNECT_FROM_LOC,
 	DEVMAN_CONNECT_TO_PARENTS_DEVICE
 } devman_interface_t;
@@ -138,6 +138,6 @@
 	DEVMAN_ADD_FUNCTION,
 	DEVMAN_ADD_MATCH_ID,
-	DEVMAN_ADD_DEVICE_TO_CLASS
-
+	DEVMAN_ADD_DEVICE_TO_CATEGORY,
+	DEVMAN_REMOVE_FUNCTION
 } driver_to_devman_t;
 
@@ -148,5 +148,10 @@
 
 typedef enum {
-	DEVMAN_DEVICE_GET_HANDLE = IPC_FIRST_USER_METHOD
+	DEVMAN_DEVICE_GET_HANDLE = IPC_FIRST_USER_METHOD,
+	DEVMAN_DEV_GET_FUNCTIONS,
+	DEVMAN_FUN_GET_CHILD,
+	DEVMAN_FUN_GET_NAME,
+	DEVMAN_FUN_GET_PATH,
+	DEVMAN_FUN_SID_TO_HANDLE
 } client_to_devman_t;
 
Index: pace/lib/c/include/ipc/devmap.h
===================================================================
--- uspace/lib/c/include/ipc/devmap.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * Copyright (c) 2007 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup devmap
- * @{
- */
-
-#ifndef DEVMAP_DEVMAP_H_
-#define DEVMAP_DEVMAP_H_
-
-#include <ipc/common.h>
-
-#define DEVMAP_NAME_MAXLEN  255
-
-typedef sysarg_t devmap_handle_t;
-
-typedef enum {
-	DEV_HANDLE_NONE,
-	DEV_HANDLE_NAMESPACE,
-	DEV_HANDLE_DEVICE
-} devmap_handle_type_t;
-
-typedef enum {
-	DEVMAP_DRIVER_REGISTER = IPC_FIRST_USER_METHOD,
-	DEVMAP_DRIVER_UNREGISTER,
-	DEVMAP_DEVICE_REGISTER,
-	DEVMAP_DEVICE_UNREGISTER,
-	DEVMAP_DEVICE_GET_HANDLE,
-	DEVMAP_NAMESPACE_GET_HANDLE,
-	DEVMAP_HANDLE_PROBE,
-	DEVMAP_NULL_CREATE,
-	DEVMAP_NULL_DESTROY,
-	DEVMAP_GET_NAMESPACE_COUNT,
-	DEVMAP_GET_DEVICE_COUNT,
-	DEVMAP_GET_NAMESPACES,
-	DEVMAP_GET_DEVICES
-} devmap_request_t;
-
-/** Interface provided by devmap.
- *
- * Every process that connects to devmap must ask one of following
- * interfaces otherwise connection will be refused.
- *
- */
-typedef enum {
-	/** Connect as device driver */
-	DEVMAP_DRIVER = 1,
-	/** Connect as client */
-	DEVMAP_CLIENT,
-	/** Create new connection to instance of device that
-	    is specified by second argument of call. */
-	DEVMAP_CONNECT_TO_DEVICE
-} devmap_interface_t;
-
-typedef struct {
-	devmap_handle_t handle;
-	char name[DEVMAP_NAME_MAXLEN + 1];
-} dev_desc_t;
-
-#endif
Index: uspace/lib/c/include/ipc/fb.h
===================================================================
--- uspace/lib/c/include/ipc/fb.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/fb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -55,14 +55,14 @@
 	FB_DRAW_TEXT_DATA,
 	FB_FLUSH,
-	FB_DRAW_PPM,
+	FB_DRAW_IMGMAP,
 	FB_PREPARE_SHM,
 	FB_DROP_SHM,
-	FB_SHM2PIXMAP,
-	FB_VP_DRAW_PIXMAP,
-	FB_VP2PIXMAP,
-	FB_DROP_PIXMAP,
+	FB_SHM2IMGMAP,
+	FB_VP_DRAW_IMGMAP,
+	FB_VP2IMGMAP,
+	FB_DROP_IMGMAP,
 	FB_ANIM_CREATE,
 	FB_ANIM_DROP,
-	FB_ANIM_ADDPIXMAP,
+	FB_ANIM_ADDIMGMAP,
 	FB_ANIM_CHGVP,
 	FB_ANIM_START,
Index: uspace/lib/c/include/ipc/input.h
===================================================================
--- uspace/lib/c/include/ipc/input.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/ipc/input.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_INPUT_H_
+#define LIBC_IPC_INPUT_H_
+
+#include <ipc/common.h>
+
+typedef enum {
+	INPUT_YIELD = IPC_FIRST_USER_METHOD,
+	INPUT_RECLAIM
+} input_request_t;
+
+typedef enum {
+	INPUT_EVENT_KEY = IPC_FIRST_USER_METHOD,
+	INPUT_EVENT_MOVE,
+	INPUT_EVENT_BUTTON
+} input_notif_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/ipc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,5 +42,6 @@
 #include <sys/types.h>
 #include <ipc/common.h>
-#include <kernel/synch/synch.h>
+#include <abi/ipc/methods.h>
+#include <abi/synch.h>
 #include <task.h>
 
@@ -253,6 +254,7 @@
     sysarg_t, sysarg_t, void *, ipc_async_callback_t, bool);
 
-extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t *,
+extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, task_id_t *,
     sysarg_t *);
+extern int ipc_connect_me(int);
 extern int ipc_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
 extern int ipc_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
Index: pace/lib/c/include/ipc/kbd.h
===================================================================
--- uspace/lib/c/include/ipc/kbd.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,55 +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 kbdgen generic
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_IPC_KBD_H_
-#define LIBC_IPC_KBD_H_
-
-#include <ipc/common.h>
-
-typedef enum {
-	KBD_YIELD = IPC_FIRST_USER_METHOD,
-	KBD_RECLAIM
-} kbd_request_t;
-
-typedef enum {
-	KBD_EVENT = IPC_FIRST_USER_METHOD
-} kbd_notif_t;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/c/include/ipc/kbdev.h
===================================================================
--- uspace/lib/c/include/ipc/kbdev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/ipc/kbdev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libcipc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_KBDEV_H_
+#define LIBC_IPC_KBDEV_H_
+
+#include <ipc/common.h>
+#include <ipc/dev_iface.h>
+
+typedef enum {
+	KBDEV_YIELD = DEV_FIRST_CUSTOM_METHOD,
+	KBDEV_RECLAIM,
+	KBDEV_SET_IND
+} kbdev_request_t;
+
+typedef enum {
+	KBDEV_EVENT = IPC_FIRST_USER_METHOD
+} kbdev_notif_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/c/include/ipc/loc.h
===================================================================
--- uspace/lib/c/include/ipc/loc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/ipc/loc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup loc
+ * @{
+ */
+
+#ifndef LIBC_IPC_LOC_H_
+#define LIBC_IPC_LOC_H_
+
+#include <ipc/common.h>
+
+#define LOC_NAME_MAXLEN  255
+
+typedef sysarg_t service_id_t;
+typedef sysarg_t category_id_t;
+
+typedef enum {
+	LOC_OBJECT_NONE,
+	LOC_OBJECT_NAMESPACE,
+	LOC_OBJECT_SERVICE
+} loc_object_type_t;
+
+typedef enum {
+	LOC_SERVER_REGISTER = IPC_FIRST_USER_METHOD,
+	LOC_SERVER_UNREGISTER,
+	LOC_SERVICE_ADD_TO_CAT,
+	LOC_SERVICE_REGISTER,
+	LOC_SERVICE_UNREGISTER,
+	LOC_SERVICE_GET_ID,
+	LOC_SERVICE_GET_NAME,
+	LOC_NAMESPACE_GET_ID,
+	LOC_CALLBACK_CREATE,
+	LOC_CATEGORY_GET_ID,
+	LOC_CATEGORY_GET_NAME,
+	LOC_CATEGORY_GET_SVCS,
+	LOC_ID_PROBE,
+	LOC_NULL_CREATE,
+	LOC_NULL_DESTROY,
+	LOC_GET_NAMESPACE_COUNT,
+	LOC_GET_SERVICE_COUNT,
+	LOC_GET_CATEGORIES,
+	LOC_GET_NAMESPACES,
+	LOC_GET_SERVICES
+} loc_request_t;
+
+typedef enum {
+	LOC_EVENT_CAT_CHANGE = IPC_FIRST_USER_METHOD
+} loc_event_t;
+
+/** Ports provided by location service.
+ *
+ * Every process that connects to loc must ask one of following
+ * ports, otherwise connection will be refused.
+ *
+ */
+typedef enum {
+	/** Service supplier (server) port */
+	LOC_PORT_SUPPLIER = 1,
+	/** Service consumer (client) port */
+	LOC_PORT_CONSUMER,
+	/** Create new connection to instance of device that
+	    is specified by second argument of call. */
+	LOC_CONNECT_TO_SERVICE
+} loc_interface_t;
+
+typedef struct {
+	service_id_t id;
+	char name[LOC_NAME_MAXLEN + 1];
+} loc_sdesc_t;
+
+#endif
Index: pace/lib/c/include/ipc/mouse.h
===================================================================
--- uspace/lib/c/include/ipc/mouse.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,50 +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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_IPC_MOUSE_H_
-#define LIBC_IPC_MOUSE_H_
-
-#include <ipc/common.h>
-
-typedef enum {
-	MEVENT_BUTTON = IPC_FIRST_USER_METHOD,
-	MEVENT_MOVE
-} mouse_notif_t;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/c/include/ipc/mouseev.h
===================================================================
--- uspace/lib/c/include/ipc/mouseev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/ipc/mouseev.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,56 @@
+/*
+ * 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 mouse
+ * @brief
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_IPC_MOUSEEV_H_
+#define LIBC_IPC_MOUSEEV_H_
+
+#include <ipc/common.h>
+#include <ipc/dev_iface.h>
+
+typedef enum {
+	MOUSEEV_YIELD = DEV_FIRST_CUSTOM_METHOD,
+	MOUSEEV_RECLAIM
+} mouseev_request_t;
+
+typedef enum {
+	MOUSEEV_MOVE_EVENT = IPC_FIRST_USER_METHOD,
+	MOUSEEV_BUTTON_EVENT
+} mouseev_notif_t;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/c/include/ipc/net.h
===================================================================
--- uspace/lib/c/include/ipc/net.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/net.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -335,11 +335,4 @@
 #define IPC_GET_ERROR(call)  ((services_t) IPC_GET_ARG4(call))
 
-/** Return the phone message argument.
- *
- * @param[in] call Message call structure.
- *
- */
-#define IPC_GET_PHONE(call)  ((int) IPC_GET_ARG5(call))
-
 /** Set the device identifier in the message answer.
  *
Index: uspace/lib/c/include/ipc/ns.h
===================================================================
--- uspace/lib/c/include/ipc/ns.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/ns.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -33,8 +33,7 @@
  */
 
-#ifndef LIBC_NS_H_
-#define LIBC_NS_H_
+#ifndef LIBC_IPC_NS_H_
+#define LIBC_IPC_NS_H_
 
-#include <sys/types.h>
 #include <ipc/common.h>
 
@@ -46,8 +45,4 @@
 } ns_request_t;
 
-extern int service_register(sysarg_t);
-extern int service_connect(sysarg_t, sysarg_t, sysarg_t);
-extern int service_connect_blocking(sysarg_t, sysarg_t, sysarg_t);
-
 #endif
 
Index: uspace/lib/c/include/ipc/serial_ctl.h
===================================================================
--- uspace/lib/c/include/ipc/serial_ctl.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/serial_ctl.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,11 +32,13 @@
 #include <ipc/dev_iface.h>
 
-/** ipc methods for getting/setting serial communication properties
- * 	1st ipc arg: baud rate
- * 	2nd ipc arg: parity
- *	3rd ipc arg: number of bits in one word
- *	4th ipc arg: number of stop bits
+/** IPC methods for getting/setting serial communication properties
+ *
+ * 1st IPC arg: baud rate
+ * 2nd IPC arg: parity
+ * 3rd IPC arg: number of bits in one word
+ * 4th IPC arg: number of stop bits
+ *
  */
-typedef enum {	
+typedef enum {
 	SERIAL_GET_COM_PROPS = DEV_FIRST_CUSTOM_METHOD,
 	SERIAL_SET_COM_PROPS
@@ -48,5 +50,5 @@
 	SERIAL_EVEN_PARITY = 3,
 	SERIAL_MARK_PARITY = 5,
-	SERIAL_SPACE_PARITY = 7	
+	SERIAL_SPACE_PARITY = 7
 } serial_parity_t;
 
Index: uspace/lib/c/include/ipc/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/services.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,30 +38,25 @@
 #define LIBC_SERVICES_H_
 
+#include <fourcc.h>
+
 typedef enum {
-	SERVICE_NONE = 0,
-	SERVICE_LOAD,
-	SERVICE_PCI,
-	SERVICE_VIDEO,
-	SERVICE_CONSOLE,
-	SERVICE_VFS,
-	SERVICE_DEVMAP,
-	SERVICE_DEVMAN,
-	SERVICE_FHC,
-	SERVICE_OBIO,
-	SERVICE_APIC,
-	SERVICE_I8259,
-	SERVICE_CLIPBOARD,
-	SERVICE_NETWORKING,
-	SERVICE_LO,
-	SERVICE_NE2000,
-	SERVICE_ETHERNET,
-	SERVICE_NILDUMMY,
-	SERVICE_IP,
-	SERVICE_ARP,
-	SERVICE_RARP,
-	SERVICE_ICMP,
-	SERVICE_UDP,
-	SERVICE_TCP,
-	SERVICE_SOCKET
+	SERVICE_NONE       = 0,
+	SERVICE_LOAD       = FOURCC('l', 'o', 'a', 'd'),
+	SERVICE_VIDEO      = FOURCC('v', 'i', 'd', ' '),
+	SERVICE_VFS        = FOURCC('v', 'f', 's', ' '),
+	SERVICE_LOC        = FOURCC('l', 'o', 'c', ' '),
+	SERVICE_DEVMAN     = FOURCC('d', 'e', 'v', 'n'),
+	SERVICE_IRC        = FOURCC('i', 'r', 'c', ' '),
+	SERVICE_CLIPBOARD  = FOURCC('c', 'l', 'i', 'p'),
+	SERVICE_NETWORKING = FOURCC('n', 'e', 't', ' '),
+	SERVICE_LO         = FOURCC('l', 'o', ' ', ' '),
+	SERVICE_NE2000     = FOURCC('n', 'e', '2', 'k'),
+	SERVICE_ETHERNET   = FOURCC('e', 't', 'h', ' '),
+	SERVICE_NILDUMMY   = FOURCC('n', 'i', 'l', 'd'),
+	SERVICE_IP         = FOURCC('i', 'p', 'v', '4'),
+	SERVICE_ARP        = FOURCC('a', 'r', 'p', ' '),
+	SERVICE_ICMP       = FOURCC('i', 'c', 'm', 'p'),
+	SERVICE_UDP        = FOURCC('u', 'd', 'p', ' '),
+	SERVICE_TCP        = FOURCC('t', 'c', 'p', ' ')
 } services_t;
 
Index: uspace/lib/c/include/ipc/vfs.h
===================================================================
--- uspace/lib/c/include/ipc/vfs.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/ipc/vfs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -62,5 +62,4 @@
 typedef enum {
 	VFS_IN_OPEN = IPC_FIRST_USER_METHOD,
-	VFS_IN_OPEN_NODE,
 	VFS_IN_READ,
 	VFS_IN_WRITE,
@@ -69,4 +68,5 @@
 	VFS_IN_FSTAT,
 	VFS_IN_CLOSE,
+	VFS_IN_PING,
 	VFS_IN_MOUNT,
 	VFS_IN_UNMOUNT,
@@ -77,5 +77,6 @@
 	VFS_IN_RENAME,
 	VFS_IN_STAT,
-	VFS_IN_DUP
+	VFS_IN_DUP,
+	VFS_IN_WAIT_HANDLE,
 } vfs_in_request_t;
 
Index: uspace/lib/c/include/l18n/langs.h
===================================================================
--- uspace/lib/c/include/l18n/langs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/l18n/langs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ * Language and locale ids.
+ */
+
+#ifndef LIBC_L18N_LANGS_H_
+#define LIBC_L18N_LANGS_H_
+
+/** Windows locale IDs.
+ * Codes taken from
+ * Developing International Software For Windows 95 and Windows NT
+ * by Nadine Kano (Microsoft Press).
+ * FIXME: add missing codes.
+ */
+typedef enum {
+	L18N_WIN_LOCALE_AFRIKAANS = 0x0436,
+	/* ... */
+	L18N_WIN_LOCALE_CZECH = 0x0405,
+	/* ... */
+	L18N_WIN_LOCALE_ENGLISH_UNITED_STATES = 0x0409,
+	/* ... */
+	L18N_WIN_LOCALE_SLOVAK = 0x041B,
+	/* ... */
+	L18N_WIN_LOCALE_SPANISH_TRADITIONAL = 0x040A,
+	/* ... */
+	L18N_WIN_LOCALE_ZULU = 0x0435
+} l18_win_locales_t;
+
+const char *str_l18_win_locale(l18_win_locales_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/libc.h
===================================================================
--- uspace/lib/c/include/libc.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/libc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 #include <libarch/syscall.h>
 
Index: uspace/lib/c/include/loader/loader.h
===================================================================
--- uspace/lib/c/include/loader/loader.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/loader/loader.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,11 +38,8 @@
 
 #include <task.h>
-#include <vfs/vfs.h>
 
-/** Abstraction of a loader connection */
-typedef struct {
-	/** ID of the phone connected to the loader. */
-	int phone_id;
-} loader_t;
+/** Forward declararion */
+struct loader;
+typedef struct loader loader_t;
 
 extern int loader_spawn(const char *);
@@ -52,5 +49,5 @@
 extern int loader_set_pathname(loader_t *, const char *);
 extern int loader_set_args(loader_t *, const char *const[]);
-extern int loader_set_files(loader_t *, fdi_node_t *const[]);
+extern int loader_set_files(loader_t *, int *const[]);
 extern int loader_load_program(loader_t *);
 extern int loader_run(loader_t *);
Index: uspace/lib/c/include/loader/pcb.h
===================================================================
--- uspace/lib/c/include/loader/pcb.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/loader/pcb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,4 @@
 
 #include <sys/types.h>
-#include <vfs/vfs.h>
 
 typedef void (*entry_point_t)(void);
@@ -62,7 +61,5 @@
 	
 	/** Number of preset files. */
-	int filc;
-	/** Preset files. */
-	fdi_node_t **filv;
+	unsigned int filc;
 	
 	/*
@@ -72,4 +69,6 @@
 	/** Pointer to ELF dynamic section of the program. */
 	void *dynamic;
+	/** Pointer to dynamic linker state structure (runtime_env_t). */
+	void *rtld_runtime;
 } pcb_t;
 
Index: uspace/lib/c/include/loc.h
===================================================================
--- uspace/lib/c/include/loc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/loc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,84 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_LOC_H_
+#define LIBC_LOC_H_
+
+#include <ipc/loc.h>
+#include <async.h>
+#include <bool.h>
+
+typedef void (*loc_cat_change_cb_t)(void);
+
+extern async_exch_t *loc_exchange_begin_blocking(loc_interface_t);
+extern async_exch_t *loc_exchange_begin(loc_interface_t);
+extern void loc_exchange_end(async_exch_t *);
+
+extern int loc_server_register(const char *, async_client_conn_t);
+extern int loc_service_register(const char *, service_id_t *);
+extern int loc_service_register_with_iface(const char *, service_id_t *,
+    sysarg_t);
+extern int loc_service_unregister(service_id_t);
+extern int loc_service_add_to_cat(service_id_t, category_id_t);
+
+extern int loc_service_get_id(const char *, service_id_t *,
+    unsigned int);
+extern int loc_service_get_name(service_id_t, char **);
+extern int loc_namespace_get_id(const char *, service_id_t *,
+    unsigned int);
+extern int loc_category_get_id(const char *, category_id_t *,
+    unsigned int);
+extern int loc_category_get_name(category_id_t, char **);
+extern int loc_category_get_svcs(category_id_t, category_id_t **, size_t *);
+extern loc_object_type_t loc_id_probe(service_id_t);
+
+extern async_sess_t *loc_service_connect(exch_mgmt_t, service_id_t,
+    unsigned int);
+
+extern int loc_null_create(void);
+extern void loc_null_destroy(int);
+
+extern size_t loc_count_namespaces(void);
+extern size_t loc_count_services(service_id_t);
+
+extern size_t loc_get_namespaces(loc_sdesc_t **);
+extern size_t loc_get_services(service_id_t, loc_sdesc_t **);
+extern int loc_get_categories(category_id_t **, size_t *);
+extern int loc_register_cat_change_cb(loc_cat_change_cb_t);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/macros.h
===================================================================
--- uspace/lib/c/include/macros.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/macros.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,9 +39,6 @@
 #define max(a, b)  ((a) > (b) ? (a) : (b))
 
-#define SIZE2KB(size)  ((size) >> 10)
-#define SIZE2MB(size)  ((size) >> 20)
-
-#define KB2SIZE(kb)  ((kb) << 10)
-#define MB2SIZE(mb)  ((mb) << 20)
+#define KiB2SIZE(kb)  ((kb) << 10)
+#define MiB2SIZE(mb)  ((mb) << 20)
 
 #define STRING(arg)      STRING_ARG(arg)
Index: uspace/lib/c/include/malloc.h
===================================================================
--- uspace/lib/c/include/malloc.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/malloc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -46,4 +46,5 @@
 extern void *realloc(const void *addr, const size_t size);
 extern void free(const void *addr);
+extern void *heap_check(void);
 
 #endif
Index: uspace/lib/c/include/net/icmp_api.h
===================================================================
--- uspace/lib/c/include/net/icmp_api.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/net/icmp_api.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -42,9 +42,9 @@
 #include <sys/types.h>
 #include <sys/time.h>
-
 #include <adt/measured_strings.h>
 #include <net/ip_codes.h>
 #include <net/icmp_codes.h>
 #include <net/icmp_common.h>
+#include <async.h>
 
 /** @name ICMP module application interface
@@ -53,6 +53,6 @@
 /*@{*/
 
-extern int icmp_echo_msg(int, size_t, mseconds_t, ip_ttl_t, ip_tos_t, int,
-    const struct sockaddr *, socklen_t);
+extern int icmp_echo_msg(async_sess_t *, size_t, mseconds_t, ip_ttl_t, ip_tos_t,
+    int, const struct sockaddr *, socklen_t);
 
 /*@}*/
Index: uspace/lib/c/include/net/icmp_common.h
===================================================================
--- uspace/lib/c/include/net/icmp_common.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/net/icmp_common.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,9 +40,7 @@
 #include <ipc/services.h>
 #include <sys/time.h>
+#include <async.h>
 
-/** Default timeout for incoming connections in microseconds (1 sec). */
-#define ICMP_CONNECT_TIMEOUT  1000000
-
-extern int icmp_connect_module(suseconds_t);
+extern async_sess_t *icmp_connect_module(void);
 
 #endif
Index: uspace/lib/c/include/net/modules.h
===================================================================
--- uspace/lib/c/include/net/modules.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/net/modules.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -46,20 +46,15 @@
 #include <sys/time.h>
 
-/** Connect to the needed module function type definition.
+/** Connect to module function type definition.
  *
- * @param[in] need The needed module service.
- *
- * @return The phone of the needed service.
+ * @return Session to the service.
  *
  */
-typedef int connect_module_t(services_t need);
+typedef async_sess_t *connect_module_t(services_t);
 
 extern void answer_call(ipc_callid_t, int, ipc_call_t *, size_t);
-extern int bind_service(services_t, sysarg_t, sysarg_t, sysarg_t,
+extern async_sess_t *bind_service(services_t, sysarg_t, sysarg_t, sysarg_t,
     async_client_conn_t);
-extern int bind_service_timeout(services_t, sysarg_t, sysarg_t, sysarg_t,
-    async_client_conn_t, suseconds_t);
-extern int connect_to_service(services_t);
-extern int connect_to_service_timeout(services_t, suseconds_t);
+extern async_sess_t *connect_to_service(services_t);
 extern int data_reply(void *, size_t);
 extern void refresh_answer(ipc_call_t *, size_t *);
Index: uspace/lib/c/include/ns.h
===================================================================
--- uspace/lib/c/include/ns.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/ns.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_NS_H_
+#define LIBC_NS_H_
+
+#include <sys/types.h>
+#include <task.h>
+#include <async.h>
+
+extern int service_register(sysarg_t);
+extern async_sess_t *service_connect(exch_mgmt_t, sysarg_t, sysarg_t, sysarg_t);
+extern async_sess_t *service_connect_blocking(exch_mgmt_t, sysarg_t, sysarg_t,
+    sysarg_t);
+
+extern int ns_ping(void);
+extern int ns_intro(task_id_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ns_obsolete.h
===================================================================
--- uspace/lib/c/include/ns_obsolete.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/ns_obsolete.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_NS_OBSOLETE_H_
+#define LIBC_NS_OBSOLETE_H_
+
+#include <sys/types.h>
+#include <task.h>
+
+extern int service_obsolete_connect(sysarg_t, sysarg_t, sysarg_t);
+extern int service_obsolete_connect_blocking(sysarg_t, sysarg_t,
+    sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/rtld/dynamic.h
===================================================================
--- uspace/lib/c/include/rtld/dynamic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/rtld/dynamic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,107 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_RTLD_DYNAMIC_H_
+#define LIBC_RTLD_DYNAMIC_H_
+
+#include <bool.h>
+#include <rtld/elf_dyn.h>
+#include <libarch/rtld/dynamic.h>
+
+/**
+ * Holds the data extracted from an ELF Dynamic section.
+ *
+ * The data is already pre-processed: Pointers are adjusted
+ * to their final run-time values by adding the load bias
+ * and indices into the symbol table are converted to pointers.
+ */
+typedef struct dyn_info {
+	/** Type of relocations used for the PLT, either DT_REL or DT_RELA */
+	int plt_rel;
+
+	/** Relocation table without explicit addends */
+	void *rel;
+	size_t rel_sz;
+	size_t rel_ent;
+
+	/** Relocation table with explicit addends */
+	void *rela;
+	size_t rela_sz;
+	size_t rela_ent;
+
+	/** PLT relocation table */
+	void *jmp_rel;
+	size_t plt_rel_sz;
+
+	/** Pointer to PLT/GOT (processor-specific) */
+	void *plt_got;
+
+	/** Hash table */
+	elf_word *hash;
+
+	/** String table */
+	char *str_tab;
+	size_t str_sz;
+
+	/** Symbol table */
+	void *sym_tab;
+	size_t sym_ent;
+
+	void *init;		/**< Module initialization code */
+	void *fini;		/**< Module cleanup code */
+
+	const char *soname;	/**< Library identifier */
+	char *rpath;		/**< Library search path list */
+
+	bool symbolic;
+	bool text_rel;
+	bool bind_now;
+
+	/* Assume for now that there's at most one needed library */
+	char *needed;
+
+	/** Pointer to the module's dynamic section */
+	elf_dyn_t *dynamic;
+
+	/** Architecture-specific info. */
+	dyn_info_arch_t arch;
+} dyn_info_t;
+
+void dynamic_parse(elf_dyn_t *dyn_ptr, size_t bias, dyn_info_t *info);
+void dyn_parse_arch(elf_dyn_t *dp, size_t bias, dyn_info_t *info);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/rtld/elf_dyn.h
===================================================================
--- uspace/lib/c/include/rtld/elf_dyn.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/rtld/elf_dyn.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,120 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_RTLD_ELF_DYN_H_
+#define LIBC_RTLD_ELF_DYN_H_
+
+#include <sys/types.h>
+#include <elf/elf.h>
+#include <libarch/rtld/elf_dyn.h>
+
+#define ELF32_R_SYM(i) ((i)>>8)
+#define ELF32_R_TYPE(i) ((unsigned char)(i))
+
+struct elf32_dyn {
+	elf_sword d_tag;
+	union {
+		elf_word d_val;
+		elf32_addr d_ptr;
+	} d_un;
+};
+
+struct elf32_rel {
+	elf32_addr r_offset;
+	elf_word r_info;
+};
+
+struct elf32_rela {
+	elf32_addr r_offset;
+	elf_word r_info;
+	elf_sword r_addend;
+};
+
+#ifdef __32_BITS__
+typedef struct elf32_dyn elf_dyn_t;
+typedef struct elf32_rel elf_rel_t;
+typedef struct elf32_rela elf_rela_t;
+#endif
+
+/*
+ * Dynamic array tags
+ */
+#define DT_NULL		0
+#define DT_NEEDED	1
+#define DT_PLTRELSZ	2
+#define DT_PLTGOT	3
+#define DT_HASH		4
+#define DT_STRTAB	5
+#define DT_SYMTAB	6
+#define DT_RELA		7
+#define DT_RELASZ	8
+#define DT_RELAENT	9
+#define DT_STRSZ	10
+#define DT_SYMENT	11
+#define DT_INIT		12
+#define DT_FINI		13
+#define DT_SONAME	14
+#define DT_RPATH	15
+#define DT_SYMBOLIC	16
+#define DT_REL		17
+#define DT_RELSZ	18
+#define DT_RELENT	19
+#define DT_PLTREL	20
+#define DT_DEBUG	21
+#define DT_TEXTREL	22
+#define DT_JMPREL	23
+#define DT_BIND_NOW	24
+#define DT_LOPROC	0x70000000
+#define DT_HIPROC	0x7fffffff
+
+/*
+ * Special section indexes
+ */
+#define SHN_UNDEF	0
+#define SHN_LORESERVE	0xff00
+#define SHN_LOPROC	0xff00
+#define SHN_HIPROC	0xff1f
+#define SHN_ABS		0xfff1
+#define SHN_COMMON	0xfff2
+#define SHN_HIRESERVE	0xffff
+
+/*
+ * Special symbol table index
+ */
+#define STN_UNDEF	0
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/rtld/module.h
===================================================================
--- uspace/lib/c/include/rtld/module.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/rtld/module.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,74 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_RTLD_MODULE_H_
+#define LIBC_RTLD_MODULE_H_
+
+#include <sys/types.h>
+#include <rtld/dynamic.h>
+#include <adt/list.h>
+
+typedef struct module {
+	dyn_info_t dyn;
+	size_t bias;
+
+	/** Array of pointers to directly dependent modules */
+	struct module **deps;
+	/** Number of fields in deps */
+	size_t n_deps;
+
+	/** True iff relocations have already been processed in this module. */
+	bool relocated;
+
+	/** Link to list of all modules in runtime environment */
+	link_t modules_link;
+
+	/** Link to BFS queue. Only used when doing a BFS of the module graph */
+	link_t queue_link;
+	/** Tag for modules already processed during a BFS */
+	bool bfs_tag;
+} module_t;
+
+void module_process_relocs(module_t *m);
+module_t *module_find(const char *name);
+module_t *module_load(const char *name);
+void module_load_deps(module_t *m);
+
+void modules_process_relocs(module_t *start);
+void modules_untag(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/rtld/rtld.h
===================================================================
--- uspace/lib/c/include/rtld/rtld.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/rtld/rtld.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,64 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_RTLD_H_
+#define LIBC_RTLD_H_
+
+#include <sys/types.h>
+#include <adt/list.h>
+
+#include <rtld/dynamic.h>
+#include <rtld/module.h>
+
+typedef struct {
+	elf_dyn_t *rtld_dynamic;
+	module_t rtld;
+
+	module_t *program;
+
+	/** List of all loaded modules including rtld and the program */
+	list_t modules;
+
+	/** Temporary hack to place each module at different address. */
+	uintptr_t next_bias;
+} runtime_env_t;
+
+extern runtime_env_t *runtime_env;
+
+extern void rtld_init_static(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/rtld/rtld_arch.h
===================================================================
--- uspace/lib/c/include/rtld/rtld_arch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/rtld/rtld_arch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_RTLD_RTLD_ARCH_H_
+#define LIBC_RTLD_RTLD_ARCH_H_
+
+#include <rtld/rtld.h>
+#include <loader/pcb.h>
+
+void module_process_pre_arch(module_t *m);
+
+void rel_table_process(module_t *m, elf_rel_t *rt, size_t rt_size);
+void rela_table_process(module_t *m, elf_rela_t *rt, size_t rt_size);
+
+void program_run(void *entry, pcb_t *pcb);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/rtld/rtld_debug.h
===================================================================
--- uspace/lib/c/include/rtld/rtld_debug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/rtld/rtld_debug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_RTLD_RTLD_DEBUG_H_
+#define LIBC_RTLD_RTLD_DEBUG_H_
+
+/* Define to enable debugging mode. */
+#undef RTLD_DEBUG
+
+#ifdef RTLD_DEBUG
+	#define DPRINTF(format, ...) printf(format, ##__VA_ARGS__)
+#else
+	#define DPRINTF(format, ...) if (0) printf(format, ##__VA_ARGS__)
+#endif
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/rtld/symbol.h
===================================================================
--- uspace/lib/c/include/rtld/symbol.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/rtld/symbol.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * 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 libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_RTLD_SYMBOL_H_
+#define LIBC_RTLD_SYMBOL_H_
+
+#include <elf/elf.h>
+#include <rtld/rtld.h>
+
+elf_symbol_t *symbol_bfs_find(const char *name, module_t *start, module_t **mod);
+elf_symbol_t *symbol_def_find(const char *name, module_t *origin, module_t **mod);
+void *symbol_get_addr(elf_symbol_t *sym, module_t *m);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/stats.h
===================================================================
--- uspace/lib/c/include/stats.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/stats.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,5 +40,6 @@
 #include <stdint.h>
 #include <bool.h>
-#include <kernel/sysinfo/abi.h>
+#include <sys/types.h>
+#include <abi/sysinfo.h>
 
 extern stats_cpu_t *stats_get_cpus(size_t *);
Index: uspace/lib/c/include/stdio.h
===================================================================
--- uspace/lib/c/include/stdio.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/stdio.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -97,47 +97,7 @@
 };
 
-typedef struct {
-	/** Linked list pointer. */
-	link_t link;
-	
-	/** Underlying file descriptor. */
-	int fd;
-	
-	/** Error indicator. */
-	int error;
-	
-	/** End-of-file indicator. */
-	int eof;
-	
-	/** Klog indicator */
-	int klog;
-	
-	/** Phone to the file provider */
-	int phone;
-
-	/**
-	 * Non-zero if the stream needs sync on fflush(). XXX change
-	 * console semantics so that sync is not needed.
-	 */
-	int need_sync;
-
-	/** Buffering type */
-	enum _buffer_type btype;
-
-	/** Buffer */
-	uint8_t *buf;
-
-	/** Buffer size */
-	size_t buf_size;
-
-	/** Buffer state */
-	enum _buffer_state buf_state;
-
-	/** Buffer I/O pointer */
-	uint8_t *buf_head;
-
-	/** Points to end of occupied space when in read mode. */
-	uint8_t *buf_tail;
-} FILE;
+/** Forward declaration */
+struct _IO_FILE;
+typedef struct _IO_FILE FILE;
 
 extern FILE *stdin;
Index: uspace/lib/c/include/str.h
===================================================================
--- uspace/lib/c/include/str.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/str.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -48,4 +48,10 @@
 #define STR_BOUNDS(length)  ((length) << 2)
 
+/**
+ * Maximum size of a buffer needed to a string converted from space-padded
+ * ASCII of size @a spa_size using spascii_to_str().
+ */
+#define SPASCII_STR_BUFSIZE(spa_size) ((spa_size) + 1)
+
 extern wchar_t str_decode(const char *str, size_t *offset, size_t sz);
 extern int chr_encode(const wchar_t ch, char *str, size_t *offset, size_t sz);
@@ -73,4 +79,5 @@
 extern void str_append(char *dest, size_t size, const char *src);
 
+extern int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n);
 extern void wstr_to_str(char *dest, size_t size, const wchar_t *src);
 extern char *wstr_to_astr(const wchar_t *src);
@@ -89,5 +96,6 @@
 extern int str_size_t(const char *, char **, unsigned int, bool, size_t *);
 
-extern void order_suffix(const uint64_t val, uint64_t *rv, char *suffix);
+extern void order_suffix(const uint64_t, uint64_t *, char *);
+extern void bin_order_suffix(const uint64_t, uint64_t *, const char **, bool);
 
 /*
Index: uspace/lib/c/include/sys/stat.h
===================================================================
--- uspace/lib/c/include/sys/stat.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/sys/stat.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,9 +39,9 @@
 #include <bool.h>
 #include <ipc/vfs.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 
 struct stat {
 	fs_handle_t fs_handle;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	fs_index_t index;
 	unsigned int lnkcnt;
@@ -49,5 +49,5 @@
 	bool is_directory;
 	aoff64_t size;
-	devmap_handle_t device;
+	service_id_t service;
 };
 
Index: uspace/lib/c/include/sys/time.h
===================================================================
--- uspace/lib/c/include/sys/time.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/sys/time.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -62,4 +62,6 @@
 extern int gettimeofday(struct timeval *tv, struct timezone *tz);
 
+extern void udelay(useconds_t);
+
 #endif
 
Index: uspace/lib/c/include/syscall.h
===================================================================
--- uspace/lib/c/include/syscall.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/syscall.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,5 +45,5 @@
 
 #include <sys/types.h>
-#include <kernel/syscall/syscall.h>
+#include <abi/syscall.h>
 
 #define __syscall0  __syscall
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/task.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -51,4 +51,6 @@
 extern task_id_t task_spawn(const char *, const char *const[], int *);
 extern int task_spawnv(task_id_t *, const char *path, const char *const []);
+extern int task_spawnvf(task_id_t *, const char *path, const char *const [],
+    int *const []);
 extern int task_spawnl(task_id_t *, const char *path, ...);
 
Index: uspace/lib/c/include/udebug.h
===================================================================
--- uspace/lib/c/include/udebug.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/udebug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,20 +36,25 @@
 #define LIBC_UDEBUG_H_
 
-#include <kernel/udebug/udebug.h>
+#include <abi/udebug.h>
 #include <sys/types.h>
+#include <async.h>
 
 typedef sysarg_t thash_t;
 
-int udebug_begin(int);
-int udebug_end(int);
-int udebug_set_evmask(int, udebug_evmask_t);
-int udebug_thread_read(int, void *, size_t , size_t *, size_t *);
-int udebug_name_read(int, void *, size_t, size_t *, size_t *);
-int udebug_areas_read(int, void *, size_t, size_t *, size_t *);
-int udebug_mem_read(int, void *, uintptr_t, size_t);
-int udebug_args_read(int, thash_t, sysarg_t *);
-int udebug_regs_read(int, thash_t, void *);
-int udebug_go(int, thash_t, udebug_event_t *, sysarg_t *, sysarg_t *);
-int udebug_stop(int, thash_t);
+extern int udebug_begin(async_sess_t *);
+extern int udebug_end(async_sess_t *);
+extern int udebug_set_evmask(async_sess_t *, udebug_evmask_t);
+extern int udebug_thread_read(async_sess_t *, void *, size_t , size_t *,
+    size_t *);
+extern int udebug_name_read(async_sess_t *, void *, size_t, size_t *,
+    size_t *);
+extern int udebug_areas_read(async_sess_t *, void *, size_t, size_t *,
+    size_t *);
+extern int udebug_mem_read(async_sess_t *, void *, uintptr_t, size_t);
+extern int udebug_args_read(async_sess_t *, thash_t, sysarg_t *);
+extern int udebug_regs_read(async_sess_t *, thash_t, void *);
+extern int udebug_go(async_sess_t *, thash_t, udebug_event_t *, sysarg_t *,
+    sysarg_t *);
+extern int udebug_stop(async_sess_t *, thash_t);
 
 #endif
Index: uspace/lib/c/include/unistd.h
===================================================================
--- uspace/lib/c/include/unistd.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/unistd.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -63,4 +63,7 @@
 extern ssize_t read(int, void *, size_t);
 
+extern ssize_t read_all(int, void *, size_t);
+extern ssize_t write_all(int, const void *, size_t);
+
 extern off64_t lseek(int, off64_t, int);
 extern int ftruncate(int, aoff64_t);
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/c/include/vfs/vfs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,16 +38,11 @@
 #include <sys/types.h>
 #include <ipc/vfs.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <stdio.h>
+#include <async.h>
 
-/**
- * This type is a libc version of the VFS triplet.
- * It uniquely identifies a file system node within a file system instance.
- */
-typedef struct {
-	fs_handle_t fs_handle;
-	devmap_handle_t devmap_handle;
-	fs_index_t index;
-} fdi_node_t;
+enum vfs_change_state_type {
+	VFS_PASS_HANDLE
+};
 
 extern char *absolutize(const char *, size_t *);
@@ -57,11 +52,10 @@
 extern int unmount(const char *);
 
-extern int open_node(fdi_node_t *, int);
-extern int fd_phone(int);
-extern int fd_node(int, fdi_node_t *);
+extern int fhandle(FILE *, int *);
 
-extern FILE *fopen_node(fdi_node_t *, const char *);
-extern int fphone(FILE *);
-extern int fnode(FILE *, fdi_node_t *);
+extern int fd_wait(void);
+
+extern async_exch_t *vfs_exchange_begin(void);
+extern void vfs_exchange_end(async_exch_t *);
 
 #endif
Index: uspace/lib/c/include/vfs/vfs_sess.h
===================================================================
--- uspace/lib/c/include/vfs/vfs_sess.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/c/include/vfs/vfs_sess.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_VFS_SESS_H_
+#define LIBC_VFS_SESS_H_
+
+#include <async.h>
+#include <stdio.h>
+
+extern async_sess_t *fd_session(exch_mgmt_t, int);
+extern async_sess_t *fsession(exch_mgmt_t, FILE *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/clui/tinput.c
===================================================================
--- uspace/lib/clui/tinput.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/clui/tinput.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -27,4 +27,5 @@
  */
 
+#include <sort.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,4 +43,7 @@
 #include <tinput.h>
 
+#define LIN_TO_COL(ti, lpos) ((lpos) % ((ti)->con_cols))
+#define LIN_TO_ROW(ti, lpos) ((lpos) / ((ti)->con_cols))
+
 /** Seek direction */
 typedef enum {
@@ -54,11 +58,17 @@
 static void tinput_sel_all(tinput_t *);
 static void tinput_sel_delete(tinput_t *);
-static void tinput_key_ctrl(tinput_t *, console_event_t *);
-static void tinput_key_shift(tinput_t *, console_event_t *);
-static void tinput_key_ctrl_shift(tinput_t *, console_event_t *);
-static void tinput_key_unmod(tinput_t *, console_event_t *);
+static void tinput_key_ctrl(tinput_t *, kbd_event_t *);
+static void tinput_key_shift(tinput_t *, kbd_event_t *);
+static void tinput_key_ctrl_shift(tinput_t *, kbd_event_t *);
+static void tinput_key_unmod(tinput_t *, kbd_event_t *);
 static void tinput_pre_seek(tinput_t *, bool);
 static void tinput_post_seek(tinput_t *, bool);
 
+static void tinput_console_set_lpos(tinput_t *ti, unsigned lpos)
+{
+	console_set_pos(ti->console, LIN_TO_COL(ti, lpos),
+	    LIN_TO_ROW(ti, lpos));
+}
+
 /** Create a new text input field. */
 tinput_t *tinput_new(void)
@@ -66,5 +76,5 @@
 	tinput_t *ti;
 	
-	ti = malloc(sizeof(tinput_t));
+	ti = calloc(1, sizeof(tinput_t));
 	if (ti == NULL)
 		return NULL;
@@ -77,5 +87,17 @@
 void tinput_destroy(tinput_t *ti)
 {
+	if (ti->prompt != NULL)
+		free(ti->prompt);
 	free(ti);
+}
+
+static void tinput_display_prompt(tinput_t *ti)
+{
+	tinput_console_set_lpos(ti, ti->prompt_coord);
+
+	console_set_style(ti->console, STYLE_EMPHASIS);
+	printf("%s", ti->prompt);
+	console_flush(ti->console);
+	console_set_style(ti->console, STYLE_NORMAL);
 }
 
@@ -88,7 +110,6 @@
 	tinput_sel_get_bounds(ti, &sa, &sb);
 	
-	console_set_pos(fphone(stdout), (ti->col0 + start) % ti->con_cols,
-	    ti->row0 + (ti->col0 + start) / ti->con_cols);
-	console_set_style(fphone(stdout), STYLE_NORMAL);
+	tinput_console_set_lpos(ti, ti->text_coord + start);
+	console_set_style(ti->console, STYLE_NORMAL);
 	
 	size_t p = start;
@@ -101,6 +122,7 @@
 	
 	if (p < sb) {
-		fflush(stdout);
-		console_set_style(fphone(stdout), STYLE_SELECTED);
+		console_flush(ti->console);
+		console_set_style(ti->console, STYLE_SELECTED);
+		
 		memcpy(dbuf, ti->buffer + p,
 		    (sb - p) * sizeof(wchar_t));
@@ -110,6 +132,6 @@
 	}
 	
-	fflush(stdout);
-	console_set_style(fphone(stdout), STYLE_NORMAL);
+	console_flush(ti->console);
+	console_set_style(ti->console, STYLE_NORMAL);
 	
 	if (p < ti->nc) {
@@ -123,5 +145,5 @@
 		putchar(' ');
 	
-	fflush(stdout);
+	console_flush(ti->console);
 }
 
@@ -133,17 +155,45 @@
 static void tinput_position_caret(tinput_t *ti)
 {
-	console_set_pos(fphone(stdout), (ti->col0 + ti->pos) % ti->con_cols,
-	    ti->row0 + (ti->col0 + ti->pos) / ti->con_cols);
-}
-
-/** Update row0 in case the screen could have scrolled. */
+	tinput_console_set_lpos(ti, ti->text_coord + ti->pos);
+}
+
+/** Update text_coord, prompt_coord in case the screen could have scrolled. */
 static void tinput_update_origin(tinput_t *ti)
 {
-	sysarg_t width = ti->col0 + ti->nc;
-	sysarg_t rows = (width / ti->con_cols) + 1;
-	
-	/* Update row0 if the screen scrolled. */
-	if (ti->row0 + rows > ti->con_rows)
-		ti->row0 = ti->con_rows - rows;
+	unsigned end_coord = ti->text_coord + ti->nc;
+	unsigned end_row = LIN_TO_ROW(ti, end_coord);
+
+	unsigned scroll_rows;
+
+	/* Update coords if the screen scrolled. */
+	if (end_row >= ti->con_rows) {
+		scroll_rows = end_row - ti->con_rows + 1;
+		ti->text_coord -= ti->con_cols * scroll_rows;
+		ti->prompt_coord -= ti->con_cols * scroll_rows;
+	}
+}
+
+static void tinput_jump_after(tinput_t *ti)
+{
+	tinput_console_set_lpos(ti, ti->text_coord + ti->nc);
+	console_flush(ti->console);
+	putchar('\n');
+}
+
+static int tinput_display(tinput_t *ti)
+{
+	sysarg_t col0, row0;
+	
+	if (console_get_pos(ti->console, &col0, &row0) != EOK)
+		return EIO;
+	
+	ti->prompt_coord = row0 * ti->con_cols + col0;
+	ti->text_coord = ti->prompt_coord + str_length(ti->prompt);
+
+	tinput_display_prompt(ti);
+	tinput_display_tail(ti, 0, 0);
+	tinput_position_caret(ti);
+
+	return EOK;
 }
 
@@ -153,5 +203,5 @@
 		return;
 	
-	sysarg_t new_width = ti->col0 + ti->nc + 1;
+	unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + 1;
 	if (new_width % ti->con_cols == 0) {
 		/* Advancing to new line. */
@@ -184,6 +234,6 @@
 		return;
 	
-	sysarg_t new_width = ti->col0 + ti->nc + ilen;
-	sysarg_t new_height = (new_width / ti->con_cols) + 1;
+	unsigned new_width = LIN_TO_COL(ti, ti->text_coord) + ti->nc + ilen;
+	unsigned new_height = (new_width / ti->con_cols) + 1;
 	if (new_height >= ti->con_rows) {
 		/* Disallow text longer than 1 page for now. */
@@ -510,4 +560,179 @@
 }
 
+/** Compare two entries in array of completions. */
+static int compl_cmp(void *va, void *vb, void *arg)
+{
+	const char *a = *(const char **) va;
+	const char *b = *(const char **) vb;
+
+	return str_cmp(a, b);
+}
+
+static size_t common_pref_len(const char *a, const char *b)
+{
+	size_t i;
+	size_t a_off, b_off;
+	wchar_t ca, cb;
+
+	i = 0;
+	a_off = 0;
+	b_off = 0;
+
+	while (true) {
+		ca = str_decode(a, &a_off, STR_NO_LIMIT);
+		cb = str_decode(b, &b_off, STR_NO_LIMIT);
+
+		if (ca == '\0' || cb == '\0' || ca != cb)
+			break;
+		++i;
+	}
+
+	return i;
+}
+
+/* Print a list of completions */
+static void tinput_show_completions(tinput_t *ti, char **compl, size_t cnum)
+{
+	unsigned int i;
+	/* Determine the maximum length of the completion in chars */
+	size_t max_length = 0;
+	for (i = 0; i < cnum; i++)
+		max_length = max(max_length, str_length(compl[i]));
+	
+	unsigned int cols = max(1, (ti->con_cols + 1) / (max_length + 1));
+	unsigned int col_width = ti->con_cols / cols;
+	unsigned int rows = cnum / cols + ((cnum % cols) != 0);
+	
+	unsigned int row, col;
+	
+	for (row = 0; row < rows; row++) {
+		bool wlc = false;
+		for (col = 0; col < cols; col++) {
+			size_t compl_idx = col * rows + row;
+			if (compl_idx >= cnum)
+				break;
+			if (col)
+				printf(" ");
+			printf("%s", compl[compl_idx]);
+			size_t compl_len = str_length(compl[compl_idx]);
+			if (col == cols -1) {
+				wlc = (compl_len == max_length);
+			}
+			else {
+				for (i = compl_len; i < col_width; i++) {
+					printf(" ");
+				}
+			}
+		}
+		if (!wlc) printf("\n");
+	}
+}
+
+
+static void tinput_text_complete(tinput_t *ti)
+{
+	void *state;
+	size_t cstart;
+	char *ctmp;
+	char **compl;     	/* Array of completions */
+	size_t compl_len;	/* Current length of @c compl array */
+	size_t cnum;
+	size_t i;
+	int rc;
+
+	if (ti->compl_ops == NULL)
+		return;
+
+	/*
+	 * Obtain list of all possible completions (growing array).
+	 */
+
+	rc = (*ti->compl_ops->init)(ti->buffer, ti->pos, &cstart, &state);
+	if (rc != EOK)
+		return;
+
+	cnum = 0;
+
+	compl_len = 1;
+	compl = malloc(compl_len * sizeof(char *));
+	if (compl == NULL) {
+		printf("Error: Out of memory.\n");
+		return;
+	}
+
+	while (true) {
+		rc = (*ti->compl_ops->get_next)(state, &ctmp);
+		if (rc != EOK)
+			break;
+
+		if (cnum >= compl_len) {
+			/* Extend array */
+			compl_len = 2 * compl_len;
+			compl = realloc(compl, compl_len * sizeof(char *));
+			if (compl == NULL) {
+				printf("Error: Out of memory.\n");
+				break;
+			}
+		}
+
+		compl[cnum] = str_dup(ctmp);
+		if (compl[cnum] == NULL) {
+			printf("Error: Out of memory.\n");
+			break;
+		}
+		cnum++;
+	}
+
+	(*ti->compl_ops->fini)(state);
+
+	if (cnum > 1) {
+		/*
+		 * More than one match. Determine maximum common prefix.
+		 */
+		size_t cplen;
+
+		cplen = str_length(compl[0]);
+		for (i = 1; i < cnum; i++)
+			cplen = min(cplen, common_pref_len(compl[0], compl[i]));
+
+		/* Compute how many bytes we should skip. */
+		size_t istart = str_lsize(compl[0], ti->pos - cstart);
+
+		if (cplen > istart) {
+			/* Insert common prefix. */
+
+			/* Copy remainder of common prefix. */
+			char *cpref = str_ndup(compl[0] + istart,
+			    str_lsize(compl[0], cplen - istart));
+
+			/* Insert it. */
+			tinput_insert_string(ti, cpref);
+			free(cpref);
+		} else {
+			/* No common prefix. Sort and display all entries. */
+
+			qsort(compl, cnum, sizeof(char *), compl_cmp, NULL);
+
+			tinput_jump_after(ti);
+			tinput_show_completions(ti, compl, cnum);
+			tinput_display(ti);
+		}
+	} else if (cnum == 1) {
+		/*
+		 * We have exactly one match. Insert it.
+		 */
+
+		/* Compute how many bytes of completion string we should skip. */
+		size_t istart = str_lsize(compl[0], ti->pos - cstart);
+
+		/* Insert remainder of completion string at current position. */
+		tinput_insert_string(ti, compl[0] + istart);
+	}
+
+	for (i = 0; i < cnum; i++)
+		free(compl[i]);
+	free(compl);
+}
+
 /** Initialize text input field.
  *
@@ -516,7 +741,37 @@
 static void tinput_init(tinput_t *ti)
 {
+	ti->console = console_init(stdin, stdout);
 	ti->hnum = 0;
 	ti->hpos = 0;
 	ti->history[0] = NULL;
+}
+
+/** Set prompt string.
+ *
+ * @param ti		Text input
+ * @param prompt	Prompt string
+ *
+ * @return		EOK on success, ENOMEM if out of memory.
+ */
+int tinput_set_prompt(tinput_t *ti, const char *prompt)
+{
+	if (ti->prompt != NULL)
+		free(ti->prompt);
+	
+	ti->prompt = str_dup(prompt);
+	if (ti->prompt == NULL)
+		return ENOMEM;
+	
+	return EOK;
+}
+
+/** Set completion ops.
+ *
+ * Set pointer to completion ops structure that will be used for text
+ * completion.
+ */
+void tinput_set_compl_ops(tinput_t *ti, tinput_compl_ops_t *compl_ops)
+{
+	ti->compl_ops = compl_ops;
 }
 
@@ -533,9 +788,6 @@
 int tinput_read(tinput_t *ti, char **dstr)
 {
-	fflush(stdout);
-	if (console_get_size(fphone(stdin), &ti->con_cols, &ti->con_rows) != EOK)
-		return EIO;
-	
-	if (console_get_pos(fphone(stdin), &ti->col0, &ti->row0) != EOK)
+	console_flush(ti->console);
+	if (console_get_size(ti->console, &ti->con_cols, &ti->con_rows) != EOK)
 		return EIO;
 	
@@ -547,9 +799,12 @@
 	ti->exit_clui = false;
 	
+	if (tinput_display(ti) != EOK)
+		return EIO;
+	
 	while (!ti->done) {
-		fflush(stdout);
-		
-		console_event_t ev;
-		if (!console_get_event(fphone(stdin), &ev))
+		console_flush(ti->console);
+		
+		kbd_event_t ev;
+		if (!console_get_kbd_event(ti->console, &ev))
 			return EIO;
 		
@@ -596,5 +851,5 @@
 }
 
-static void tinput_key_ctrl(tinput_t *ti, console_event_t *ev)
+static void tinput_key_ctrl(tinput_t *ti, kbd_event_t *ev)
 {
 	switch (ev->key) {
@@ -635,5 +890,5 @@
 }
 
-static void tinput_key_ctrl_shift(tinput_t *ti, console_event_t *ev)
+static void tinput_key_ctrl_shift(tinput_t *ti, kbd_event_t *ev)
 {
 	switch (ev->key) {
@@ -655,5 +910,5 @@
 }
 
-static void tinput_key_shift(tinput_t *ti, console_event_t *ev)
+static void tinput_key_shift(tinput_t *ti, kbd_event_t *ev)
 {
 	switch (ev->key) {
@@ -681,5 +936,5 @@
 }
 
-static void tinput_key_unmod(tinput_t *ti, console_event_t *ev)
+static void tinput_key_unmod(tinput_t *ti, kbd_event_t *ev)
 {
 	switch (ev->key) {
@@ -712,4 +967,7 @@
 		tinput_history_seek(ti, -1);
 		break;
+	case KC_TAB:
+		tinput_text_complete(ti);
+		break;
 	default:
 		break;
Index: uspace/lib/clui/tinput.h
===================================================================
--- uspace/lib/clui/tinput.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/clui/tinput.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -37,6 +37,65 @@
 #define LIBCLUI_TINPUT_H_
 
+#include <adt/list.h>
+#include <async.h>
+#include <inttypes.h>
+#include <io/console.h>
+#include <stdio.h>
+
 #define HISTORY_LEN     10
 #define INPUT_MAX_SIZE  1024
+
+/** Begin enumeration of text completions.
+ *
+ * When user requests text completion, tinput will call this function to start
+ * text completion operation. @a *cstart should be set to the position
+ * (character index) of the first character of the 'word' that is being
+ * completed. The resulting text is obtained by replacing the range of text
+ * starting at @a *cstart and ending at @a pos with the completion text.
+ *
+ * The function can pass information to the get_next and fini functions
+ * via @a state. The init function allocates the state object and stores
+ * a pointer to it to @a *state. The fini function destroys the state object.
+ *
+ * @param text		Current contents of edit buffer (null-terminated).
+ * @param pos		Current caret position.
+ * @param cstart	Output, position in text where completion begins from.
+ * @param state		Output, pointer to a client state object.
+ *
+ * @return		EOK on success, negative error code on failure.
+ */
+typedef int (*tinput_compl_init_fn)(wchar_t *text, size_t pos, size_t *cstart,
+    void **state);
+
+/** Obtain one text completion alternative.
+ *
+ * Upon success the function sets @a *compl to point to a string, the
+ * completion text. The caller (Tinput) should not modify or free the text.
+ * The pointer is only valid until the next invocation of any completion
+ * function.
+ *
+ * @param state		Pointer to state object created by the init funtion.
+ * @param compl		Output, the completion text, ownership retained.
+ *
+ * @return		EOK on success, negative error code on failure.
+ */
+typedef int (*tinput_compl_get_next_fn)(void *state, char **compl);
+
+
+/** Finish enumeration of text completions.
+ *
+ * The function must deallocate any state information allocated by the init
+ * function or temporary data allocated by the get_next function.
+ *
+ * @param state		Pointer to state object created by the init funtion.
+ */
+typedef void (*tinput_compl_fini_fn)(void *state);
+
+/** Text completion ops. */
+typedef struct {
+	tinput_compl_init_fn init;
+	tinput_compl_get_next_fn get_next;
+	tinput_compl_fini_fn fini;
+} tinput_compl_ops_t;
 
 /** Text input field (command line).
@@ -45,10 +104,20 @@
  */
 typedef struct {
+	/** Console */
+	console_ctrl_t *console;
+	
+	/** Prompt string */
+	char *prompt;
+	
+	/** Completion ops. */
+	tinput_compl_ops_t *compl_ops;
+	
 	/** Buffer holding text currently being edited */
 	wchar_t buffer[INPUT_MAX_SIZE + 1];
 	
-	/** Screen coordinates of the top-left corner of the text field */
-	sysarg_t col0;
-	sysarg_t row0;
+	/** Linear position on screen where the prompt starts */
+	unsigned prompt_coord;
+	/** Linear position on screen where the text field starts */
+	unsigned text_coord;
 	
 	/** Screen dimensions */
@@ -82,4 +151,6 @@
 
 extern tinput_t *tinput_new(void);
+extern int tinput_set_prompt(tinput_t *, const char *);
+extern void tinput_set_compl_ops(tinput_t *, tinput_compl_ops_t *);
 extern void tinput_destroy(tinput_t *);
 extern int tinput_read(tinput_t *, char **);
Index: uspace/lib/drv/Makefile
===================================================================
--- uspace/lib/drv/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/drv/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,5 +29,5 @@
 
 USPACE_PREFIX = ../..
-EXTRA_CFLAGS = -Iinclude
+EXTRA_CFLAGS = -Iinclude -I$(LIBUSB_PREFIX)/include
 LIBRARY = libdrv
 
@@ -35,6 +35,12 @@
 	generic/driver.c \
 	generic/dev_iface.c \
+	generic/log.c \
+	generic/logbuf.c \
 	generic/remote_hw_res.c \
-	generic/remote_char_dev.c
+	generic/remote_char_dev.c \
+	generic/remote_usb.c \
+	generic/remote_pci.c \
+	generic/remote_usbhc.c \
+	generic/remote_usbhid.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/drv/generic/dev_iface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,9 +41,19 @@
 #include "remote_hw_res.h"
 #include "remote_char_dev.h"
+#include "remote_usb.h"
+#include "remote_usbhc.h"
+#include "remote_usbhid.h"
+#include "remote_pci.h"
+
+#include <stdio.h>
 
 static iface_dipatch_table_t remote_ifaces = {
 	.ifaces = {
 		&remote_hw_res_iface,
-		&remote_char_dev_iface
+		&remote_char_dev_iface,
+		&remote_pci_iface,
+		&remote_usb_iface,
+		&remote_usbhc_iface,
+		&remote_usbhid_iface
 	}
 };
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/drv/generic/driver.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -47,4 +47,5 @@
 #include <stdlib.h>
 #include <str.h>
+#include <str_error.h>
 #include <ctype.h>
 #include <errno.h>
@@ -138,10 +139,9 @@
 find_interrupt_context_by_id(interrupt_context_list_t *list, int id)
 {
+	interrupt_context_t *ctx;
+	
 	fibril_mutex_lock(&list->mutex);
 	
-	link_t *link = list->contexts.next;
-	interrupt_context_t *ctx;
-	
-	while (link != &list->contexts) {
+	list_foreach(list->contexts, link) {
 		ctx = list_get_instance(link, interrupt_context_t, link);
 		if (ctx->id == id) {
@@ -149,5 +149,4 @@
 			return ctx;
 		}
-		link = link->next;
 	}
 	
@@ -159,10 +158,9 @@
 find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)
 {
+	interrupt_context_t *ctx;
+	
 	fibril_mutex_lock(&list->mutex);
 	
-	link_t *link = list->contexts.next;
-	interrupt_context_t *ctx;
-	
-	while (link != &list->contexts) {
+	list_foreach(list->contexts, link) {
 		ctx = list_get_instance(link, interrupt_context_t, link);
 		if (ctx->irq == irq && ctx->dev == dev) {
@@ -170,5 +168,4 @@
 			return ctx;
 		}
-		link = link->next;
 	}
 	
@@ -230,12 +227,11 @@
 }
 
-static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle)
+static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle)
 {
 	ddf_fun_t *fun = NULL;
 	
 	fibril_mutex_lock(&functions_mutex);
-	link_t *link = functions->next;
-	
-	while (link != functions) {
+	
+	list_foreach(*functions, link) {
 		fun = list_get_instance(link, ddf_fun_t, link);
 		if (fun->handle == handle) {
@@ -243,6 +239,4 @@
 			return fun;
 		}
-		
-		link = link->next;
 	}
 	
@@ -273,12 +267,6 @@
 	
 	res = driver->driver_ops->add_device(dev);
-	if (res == EOK) {
-		printf("%s: new device with handle=%" PRIun " was added.\n",
-		    driver->name, dev_handle);
-	} else {
-		printf("%s: failed to add a new device with handle = %" PRIun ".\n",
-		    driver->name, dev_handle);
+	if (res != EOK)
 		delete_device(dev);
-	}
 	
 	async_answer_0(iid, res);
@@ -290,13 +278,12 @@
 	async_answer_0(iid, EOK);
 	
-	bool cont = true;
-	while (cont) {
+	while (true) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case DRIVER_ADD_DEVICE:
 			driver_add_device(callid, &call);
@@ -308,9 +295,9 @@
 }
 
-/**
- * Generic client connection handler both for applications and drivers.
- *
- * @param drv		True for driver client, false for other clients
- *			(applications, services etc.).
+/** Generic client connection handler both for applications and drivers.
+ *
+ * @param drv True for driver client, false for other clients
+ *            (applications, services, etc.).
+ *
  */
 static void driver_connection_gen(ipc_callid_t iid, ipc_call_t *icall, bool drv)
@@ -322,5 +309,5 @@
 	devman_handle_t handle = IPC_GET_ARG2(*icall);
 	ddf_fun_t *fun = driver_get_function(&functions, handle);
-
+	
 	if (fun == NULL) {
 		printf("%s: driver_connection_gen error - no function with handle"
@@ -330,4 +317,9 @@
 	}
 	
+	if (fun->conn_handler != NULL) {
+		/* Driver has a custom connection handler. */
+		(*fun->conn_handler)(iid, icall, (void *)fun);
+		return;
+	}
 	
 	/*
@@ -345,13 +337,11 @@
 		return;
 	
-	while (1) {
+	while (true) {
 		ipc_callid_t callid;
 		ipc_call_t call;
 		callid = async_get_call(&call);
 		sysarg_t method = IPC_GET_IMETHOD(call);
-		int iface_idx;
-		
-		switch  (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* Close device function */
 			if (fun->ops != NULL && fun->ops->close != NULL)
@@ -359,69 +349,67 @@
 			async_answer_0(callid, EOK);
 			return;
-		default:
-			/* convert ipc interface id to interface index */
-			
-			iface_idx = DEV_IFACE_IDX(method);
-			
-			if (!is_valid_iface_idx(iface_idx)) {
-				remote_handler_t *default_handler =
-				    function_get_default_handler(fun);
-				if (default_handler != NULL) {
-					(*default_handler)(fun, callid, &call);
-					break;
-				}
-				
-				/*
-				 * Function has no such interface and
-				 * default handler is not provided.
-				 */
-				printf("%s: driver_connection_gen error - "
-				    "invalid interface id %d.",
-				    driver->name, iface_idx);
-				async_answer_0(callid, ENOTSUP);
-				break;
-			}
-			
-			/* calling one of the function's interfaces */
-			
-			/* Get the interface ops structure. */
-			void *ops = function_get_ops(fun, iface_idx);
-			if (ops == NULL) {
-				printf("%s: driver_connection_gen error - ",
-				    driver->name);
-				printf("Function with handle %" PRIun " has no interface "
-				    "with id %d.\n", handle, iface_idx);
-				async_answer_0(callid, ENOTSUP);
-				break;
+		}
+		
+		/* Convert ipc interface id to interface index */
+		
+		int iface_idx = DEV_IFACE_IDX(method);
+		
+		if (!is_valid_iface_idx(iface_idx)) {
+			remote_handler_t *default_handler =
+			    function_get_default_handler(fun);
+			if (default_handler != NULL) {
+				(*default_handler)(fun, callid, &call);
+				continue;
 			}
 			
 			/*
-			 * Get the corresponding interface for remote request
-			 * handling ("remote interface").
+			 * Function has no such interface and
+			 * default handler is not provided.
 			 */
-			remote_iface_t *rem_iface = get_remote_iface(iface_idx);
-			assert(rem_iface != NULL);
-			
-			/* get the method of the remote interface */
-			sysarg_t iface_method_idx = IPC_GET_ARG1(call);
-			remote_iface_func_ptr_t iface_method_ptr =
-			    get_remote_method(rem_iface, iface_method_idx);
-			if (iface_method_ptr == NULL) {
-				// the interface has not such method
-				printf("%s: driver_connection_gen error - "
-				    "invalid interface method.", driver->name);
-				async_answer_0(callid, ENOTSUP);
-				break;
-			}
-			
-			/*
-			 * Call the remote interface's method, which will
-			 * receive parameters from the remote client and it will
-			 * pass it to the corresponding local interface method
-			 * associated with the function by its driver.
-			 */
-			(*iface_method_ptr)(fun, ops, callid, &call);
-			break;
+			printf("%s: driver_connection_gen error - "
+			    "invalid interface id %d.",
+			    driver->name, iface_idx);
+			async_answer_0(callid, ENOTSUP);
+			continue;
 		}
+		
+		/* Calling one of the function's interfaces */
+		
+		/* Get the interface ops structure. */
+		void *ops = function_get_ops(fun, iface_idx);
+		if (ops == NULL) {
+			printf("%s: driver_connection_gen error - ", driver->name);
+			printf("Function with handle %" PRIun " has no interface "
+			    "with id %d.\n", handle, iface_idx);
+			async_answer_0(callid, ENOTSUP);
+			continue;
+		}
+		
+		/*
+		 * Get the corresponding interface for remote request
+		 * handling ("remote interface").
+		 */
+		remote_iface_t *rem_iface = get_remote_iface(iface_idx);
+		assert(rem_iface != NULL);
+		
+		/* get the method of the remote interface */
+		sysarg_t iface_method_idx = IPC_GET_ARG1(call);
+		remote_iface_func_ptr_t iface_method_ptr =
+		    get_remote_method(rem_iface, iface_method_idx);
+		if (iface_method_ptr == NULL) {
+			/* The interface has not such method */
+			printf("%s: driver_connection_gen error - "
+			    "invalid interface method.", driver->name);
+			async_answer_0(callid, ENOTSUP);
+			continue;
+		}
+		
+		/*
+		 * Call the remote interface's method, which will
+		 * receive parameters from the remote client and it will
+		 * pass it to the corresponding local interface method
+		 * associated with the function by its driver.
+		 */
+		(*iface_method_ptr)(fun, ops, callid, &call);
 	}
 }
@@ -438,8 +426,18 @@
 
 /** Function for handling connections to device driver. */
-static void driver_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
+static void driver_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	sysarg_t conn_type;
+
+	if (iid == 0) {
+		/* Callback connection from devman */
+		/* XXX Use separate handler for this type of connection */
+		conn_type = DRIVER_DEVMAN;
+	} else {
+		conn_type = IPC_GET_ARG1(*icall);
+	}
+
 	/* Select interface */
-	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
+	switch (conn_type) {
 	case DRIVER_DEVMAN:
 		/* Handle request from device manager */
@@ -594,4 +592,5 @@
 int ddf_fun_bind(ddf_fun_t *fun)
 {
+	assert(fun->bound == false);
 	assert(fun->name != NULL);
 	
@@ -610,4 +609,29 @@
 }
 
+/** Unbind a function node.
+ *
+ * Unbind the specified function from the system. This effectively makes
+ * the function invisible to the system.
+ *
+ * @param fun		Function to bind
+ * @return		EOK on success or negative error code
+ */
+int ddf_fun_unbind(ddf_fun_t *fun)
+{
+	int res;
+	
+	assert(fun->bound == true);
+	
+	add_to_functions_list(fun);
+	res = devman_remove_function(fun->handle);
+	if (res != EOK)
+		return res;
+
+	remove_from_functions_list(fun);
+	
+	fun->bound = false;
+	return EOK;
+}
+
 /** Add single match ID to inner function.
  *
@@ -632,5 +656,5 @@
 		return ENOMEM;
 	
-	match_id->id = match_id_str;
+	match_id->id = str_dup(match_id_str);
 	match_id->score = 90;
 	
@@ -647,18 +671,20 @@
 }
 
-/** Add exposed function to class.
+/** Add exposed function to category.
  *
  * Must only be called when the function is bound.
  */
-int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name)
+int ddf_fun_add_to_category(ddf_fun_t *fun, const char *cat_name)
 {
 	assert(fun->bound == true);
 	assert(fun->ftype == fun_exposed);
 	
-	return devman_add_device_to_class(fun->handle, class_name);
+	return devman_add_device_to_category(fun->handle, cat_name);
 }
 
 int ddf_driver_main(driver_t *drv)
 {
+	int rc;
+
 	/*
 	 * Remember the driver structure - driver_ops will be called by generic
@@ -674,9 +700,21 @@
 	
 	/*
-	 * Register driver by device manager with generic handler for incoming
-	 * connections.
+	 * Register driver with device manager using generic handler for
+	 * incoming connections.
 	 */
-	devman_driver_register(driver->name, driver_connection);
-	
+	rc = devman_driver_register(driver->name, driver_connection);
+	if (rc != EOK) {
+		printf("Error: Failed to register driver with device manager "
+		    "(%s).\n", (rc == EEXISTS) ? "driver already started" :
+		    str_error(rc));
+		
+		return 1;
+	}
+	
+	/* Return success from the task since server has started. */
+	rc = task_retval(0);
+	if (rc != EOK)
+		return 1;
+
 	async_manager();
 	
Index: uspace/lib/drv/generic/log.c
===================================================================
--- uspace/lib/drv/generic/log.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/generic/log.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+
+#include <io/log.h>
+#include <stdarg.h>
+
+#include <ddf/log.h>
+
+/** Initialize the logging system.
+ *
+ * @param drv_name	Driver name, will be printed as part of message
+ * @param level		Minimum message level to print
+ */
+int ddf_log_init(const char *drv_name, log_level_t level)
+{
+	return log_init(drv_name, level);
+}
+
+/** Log a driver message.
+ *
+ * @param level		Message verbosity level. Message is only printed
+ *			if verbosity is less than or equal to current
+ *			reporting level.
+ * @param fmt		Format string (no trailing newline)
+ */
+void ddf_msg(log_level_t level, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	log_msgv(level, fmt, args);
+	va_end(args);
+}
+
+/** @}
+ */
Index: uspace/lib/drv/generic/logbuf.c
===================================================================
--- uspace/lib/drv/generic/logbuf.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/generic/logbuf.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2011 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 libdrv
+ * @{
+ */
+
+#include <libarch/common.h>
+#include <stdio.h>
+#include <ddf/log.h>
+#include <assert.h>
+
+/** Formatting string for printing number of not-printed items. */
+#define REMAINDER_STR_FMT " (%zu)..."
+/** Expected max size of the remainder string.
+ * String + terminator + number width (enough for 4GB).*/
+#define REMAINDER_STR_LEN (5 + 1 + 10)
+
+/** Groups size. */
+#define BUFFER_DUMP_GROUP_SIZE 4
+
+/** Space between two items. */
+#define SPACE_NORMAL " "
+/** Space between two groups. */
+#define SPACE_GROUP "  "
+
+/** Dump one item into given buffer.
+ *
+ * @param buffer Data buffer.
+ * @param item_size Size of the item (1, 2, 4).
+ * @param index Index into the @p buffer (respecting @p item_size).
+ * @param dump Where to store the dump.
+ * @param dump_size Size of @p dump size.
+ * @return Number of characters printed (see snprintf).
+ */
+static int dump_one_item(const void *buffer, size_t item_size, size_t index,
+    char *dump, size_t dump_size)
+{
+	/* Determine space before the number. */
+	const char *space_before;
+	if (index == 0) {
+		space_before = "";
+	} else if ((index % BUFFER_DUMP_GROUP_SIZE) == 0) {
+		space_before = SPACE_GROUP;
+	} else {
+		space_before = SPACE_NORMAL;
+	}
+
+	/* Let buf point to the item to be printed. */
+	const uint8_t *buf = (const uint8_t *) buffer;
+	buf += index * item_size;
+
+/* Formats the dump with space before, takes care of type casting (ugly). */
+#define _FORMAT(digits, bits) \
+	snprintf(dump, dump_size, "%s%0" #digits PRIx##bits, \
+	    space_before, ((uint##bits##_t *)buf)[0]);
+
+	switch (item_size) {
+	case 4:
+		return _FORMAT(8, 32);
+	case 2:
+		return _FORMAT(4, 16);
+	default:
+		return _FORMAT(2, 8);
+	}
+#undef _FORMAT
+}
+
+/** Count number of characters needed for dumping buffer of given size.
+ *
+ * @param item_size Item size in bytes.
+ * @param items Number of items to print.
+ * @return Number of characters the full dump would occupy.
+ */
+static size_t count_dump_length(size_t item_size, size_t items)
+{
+	size_t group_space_count = items / BUFFER_DUMP_GROUP_SIZE - 1;
+	size_t normal_space_count = items - 1 - group_space_count;
+
+	size_t dump_itself = item_size * 2 * items;
+	size_t group_spaces = str_size(SPACE_GROUP) * group_space_count;
+	size_t normal_spaces = str_size(SPACE_NORMAL) * normal_space_count;
+
+	return dump_itself + group_spaces + normal_spaces;
+}
+
+
+/** Dumps data buffer to a string in hexadecimal format.
+ *
+ * Setting @p items_to_print to zero would dump the whole buffer together
+ * with information how many items were omitted. Otherwise, no information
+ * about omitted items is printed.
+ *
+ * @param dump Where to store the dumped buffer.
+ * @param dump_size Size of @p dump in bytes.
+ * @param buffer Data buffer to be dumped.
+ * @param item_size Size of items in the @p buffer in bytes (1,2,4 allowed).
+ * @param items Number of items in the @p buffer.
+ * @param items_to_print How many items to actually print.
+ */
+void ddf_dump_buffer(char *dump, size_t dump_size,
+    const void *buffer, size_t item_size, size_t items, size_t items_to_print)
+{
+	if ((dump_size == 0) || (dump == NULL)) {
+		return;
+	}
+	/* We need space for one byte at least. */
+	if (dump_size < 3) {
+		str_cpy(dump, dump_size, "...");
+		return;
+	}
+
+	/* Special cases first. */
+	if (buffer == NULL) {
+		str_cpy(dump, dump_size, "(null)");
+		return;
+	}
+	if (items == 0) {
+		str_cpy(dump, dump_size, "(empty)");
+	}
+
+	if (items_to_print > items) {
+		items_to_print = items;
+	}
+
+	bool print_remainder = items_to_print == 0;
+
+	/* How many available bytes we do have. */
+	size_t dump_size_remaining = dump_size - 1;
+
+	if (print_remainder) {
+		/* Can't do much when user supplied small buffer. */
+		if (dump_size_remaining < REMAINDER_STR_LEN) {
+			print_remainder = false;
+		} else {
+			size_t needed_size = count_dump_length(item_size, items);
+			if (needed_size > dump_size_remaining) {
+				dump_size_remaining -= REMAINDER_STR_LEN;
+			} else {
+				print_remainder = false;
+			}
+		}
+		items_to_print = items;
+	}
+
+	str_cpy(dump, dump_size, "");
+
+	size_t index = 0;
+	while (index < items) {
+		char current_item[32];
+		int printed = dump_one_item(buffer, item_size, index,
+		    current_item, 32);
+		assert(printed >= 0);
+
+		if ((size_t) printed > dump_size_remaining) {
+			break;
+		}
+
+		str_append(dump, dump_size, current_item);
+
+		dump_size_remaining -= printed;
+		index++;
+
+		if (index >= items_to_print) {
+			break;
+		}
+	}
+
+	if (print_remainder && (index < items)) {
+		size_t s = str_size(dump);
+		snprintf(dump + s, dump_size - s ,REMAINDER_STR_FMT,
+		    items - index);
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/drv/generic/remote_pci.c
===================================================================
--- uspace/lib/drv/generic/remote_pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/generic/remote_pci.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,179 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+#include <assert.h>
+#include <async.h>
+#include <errno.h>
+
+#include "pci_dev_iface.h"
+#include "ddf/driver.h"
+
+static void remote_config_space_read_8(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_config_space_read_16(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_config_space_read_32(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+
+static void remote_config_space_write_8(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_config_space_write_16(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_config_space_write_32(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+
+/** Remote USB interface operations. */
+static remote_iface_func_ptr_t remote_pci_iface_ops [] = {
+	remote_config_space_read_8,
+	remote_config_space_read_16,
+	remote_config_space_read_32,
+
+	remote_config_space_write_8,
+	remote_config_space_write_16,
+	remote_config_space_write_32
+};
+
+/** Remote USB interface structure.
+ */
+remote_iface_t remote_pci_iface = {
+	.method_count = sizeof(remote_pci_iface_ops) /
+	    sizeof(remote_pci_iface_ops[0]),
+	.methods = remote_pci_iface_ops
+};
+
+void remote_config_space_read_8(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_read_8 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint8_t value;
+	int ret = pci_iface->config_space_read_8(fun, address, &value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_1(callid, EOK, value);
+	}
+}
+
+void remote_config_space_read_16(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_read_16 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint16_t value;
+	int ret = pci_iface->config_space_read_16(fun, address, &value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_1(callid, EOK, value);
+	}
+}
+void remote_config_space_read_32(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_read_32 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint32_t value;
+	int ret = pci_iface->config_space_read_32(fun, address, &value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_1(callid, EOK, value);
+	}
+}
+
+void remote_config_space_write_8(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_write_8 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint8_t value = DEV_IPC_GET_ARG2(*call);
+	int ret = pci_iface->config_space_write_8(fun, address, value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_0(callid, EOK);
+	}
+}
+
+void remote_config_space_write_16(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_write_16 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint16_t value = DEV_IPC_GET_ARG2(*call);
+	int ret = pci_iface->config_space_write_16(fun, address, value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_0(callid, EOK);
+	}
+}
+
+void remote_config_space_write_32(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(iface);
+	pci_dev_iface_t *pci_iface = (pci_dev_iface_t *)iface;
+	if (pci_iface->config_space_write_32 == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	uint32_t address = DEV_IPC_GET_ARG1(*call);
+	uint32_t value = DEV_IPC_GET_ARG2(*call);
+	int ret = pci_iface->config_space_write_32(fun, address, value);
+	if (ret != EOK) {
+		async_answer_0(callid, ret);
+	} else {
+		async_answer_0(callid, EOK);
+	}
+}
+
+
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/generic/remote_usb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,128 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+
+#include "usb_iface.h"
+#include "ddf/driver.h"
+
+
+static void remote_usb_get_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_get_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+//static void remote_usb(device_t *, void *, ipc_callid_t, ipc_call_t *);
+
+/** Remote USB interface operations. */
+static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
+	remote_usb_get_address,
+	remote_usb_get_interface,
+	remote_usb_get_hc_handle
+};
+
+/** Remote USB interface structure.
+ */
+remote_iface_t remote_usb_iface = {
+	.method_count = sizeof(remote_usb_iface_ops) /
+	    sizeof(remote_usb_iface_ops[0]),
+	.methods = remote_usb_iface_ops
+};
+
+
+void remote_usb_get_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->get_address == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
+
+	usb_address_t address;
+	int rc = usb_iface->get_address(fun, handle, &address);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+	} else {
+		async_answer_1(callid, EOK, address);
+	}
+}
+
+void remote_usb_get_interface(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->get_interface == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
+
+	int iface_no;
+	int rc = usb_iface->get_interface(fun, handle, &iface_no);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+	} else {
+		async_answer_1(callid, EOK, iface_no);
+	}
+}
+
+void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->get_hc_handle == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	devman_handle_t handle;
+	int rc = usb_iface->get_hc_handle(fun, &handle);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+	}
+
+	async_answer_1(callid, EOK, (sysarg_t) handle);
+}
+
+
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2010-2011 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "usbhc_iface.h"
+#include "ddf/driver.h"
+
+#define USB_MAX_PAYLOAD_SIZE 1020
+#define HACK_MAX_PACKET_SIZE 8
+#define HACK_MAX_PACKET_SIZE_INTERRUPT_IN 4
+
+static void remote_usbhc_interrupt_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_interrupt_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_find_by_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+
+/** Remote USB host controller interface operations. */
+static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
+	remote_usbhc_request_address,
+	remote_usbhc_bind_address,
+	remote_usbhc_find_by_address,
+	remote_usbhc_release_address,
+
+	remote_usbhc_interrupt_out,
+	remote_usbhc_interrupt_in,
+
+	remote_usbhc_bulk_out,
+	remote_usbhc_bulk_in,
+
+	remote_usbhc_control_write,
+	remote_usbhc_control_read,
+
+	remote_usbhc_register_endpoint,
+	remote_usbhc_unregister_endpoint
+};
+
+/** Remote USB host controller interface structure.
+ */
+remote_iface_t remote_usbhc_iface = {
+	.method_count = sizeof(remote_usbhc_iface_ops) /
+	    sizeof(remote_usbhc_iface_ops[0]),
+	.methods = remote_usbhc_iface_ops
+};
+
+typedef struct {
+	ipc_callid_t caller;
+	ipc_callid_t data_caller;
+	void *buffer;
+	void *setup_packet;
+	size_t size;
+} async_transaction_t;
+
+static void async_transaction_destroy(async_transaction_t *trans)
+{
+	if (trans == NULL) {
+		return;
+	}
+
+	if (trans->setup_packet != NULL) {
+		free(trans->setup_packet);
+	}
+	if (trans->buffer != NULL) {
+		free(trans->buffer);
+	}
+
+	free(trans);
+}
+
+static async_transaction_t *async_transaction_create(ipc_callid_t caller)
+{
+	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
+	if (trans == NULL) {
+		return NULL;
+	}
+
+	trans->caller = caller;
+	trans->data_caller = 0;
+	trans->buffer = NULL;
+	trans->setup_packet = NULL;
+	trans->size = 0;
+
+	return trans;
+}
+
+void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->request_address) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+	
+	usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
+
+	usb_address_t address;
+	int rc = usb_iface->request_address(fun, speed, &address);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+	} else {
+		async_answer_1(callid, EOK, (sysarg_t) address);
+	}
+}
+
+void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->bind_address) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
+	devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
+
+	int rc = usb_iface->bind_address(fun, address, handle);
+
+	async_answer_0(callid, rc);
+}
+
+void remote_usbhc_find_by_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->find_by_address) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
+	devman_handle_t handle;
+	int rc = usb_iface->find_by_address(fun, address, &handle);
+
+	if (rc == EOK) {
+		async_answer_1(callid, EOK, handle);
+	} else {
+		async_answer_0(callid, rc);
+	}
+}
+
+void remote_usbhc_release_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->release_address) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
+
+	int rc = usb_iface->release_address(fun, address);
+
+	async_answer_0(callid, rc);
+}
+
+
+static void callback_out(ddf_fun_t *fun,
+    int outcome, void *arg)
+{
+	async_transaction_t *trans = (async_transaction_t *)arg;
+
+	async_answer_0(trans->caller, outcome);
+
+	async_transaction_destroy(trans);
+}
+
+static void callback_in(ddf_fun_t *fun,
+    int outcome, size_t actual_size, void *arg)
+{
+	async_transaction_t *trans = (async_transaction_t *)arg;
+
+	if (outcome != EOK) {
+		async_answer_0(trans->caller, outcome);
+		if (trans->data_caller) {
+			async_answer_0(trans->data_caller, EINTR);
+		}
+		async_transaction_destroy(trans);
+		return;
+	}
+
+	trans->size = actual_size;
+
+	if (trans->data_caller) {
+		async_data_read_finalize(trans->data_caller,
+		    trans->buffer, actual_size);
+	}
+
+	async_answer_0(trans->caller, EOK);
+
+	async_transaction_destroy(trans);
+}
+
+/** Process an outgoing transfer (both OUT and SETUP).
+ *
+ * @param device Target device.
+ * @param callid Initiating caller.
+ * @param call Initiating call.
+ * @param transfer_func Transfer function (might be NULL).
+ */
+static void remote_usbhc_out_transfer(ddf_fun_t *fun,
+    ipc_callid_t callid, ipc_call_t *call,
+    usbhc_iface_transfer_out_t transfer_func)
+{
+	if (!transfer_func) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_target_t target = {
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
+	};
+
+	size_t len = 0;
+	void *buffer = NULL;
+
+	int rc = async_data_write_accept(&buffer, false,
+	    1, USB_MAX_PAYLOAD_SIZE,
+	    0, &len);
+
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		if (buffer != NULL) {
+			free(buffer);
+		}
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	trans->buffer = buffer;
+	trans->size = len;
+
+	rc = transfer_func(fun, target,
+	    buffer, len,
+	    callback_out, trans);
+
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
+}
+
+/** Process an incoming transfer.
+ *
+ * @param device Target device.
+ * @param callid Initiating caller.
+ * @param call Initiating call.
+ * @param transfer_func Transfer function (might be NULL).
+ */
+static void remote_usbhc_in_transfer(ddf_fun_t *fun,
+    ipc_callid_t callid, ipc_call_t *call,
+    usbhc_iface_transfer_in_t transfer_func)
+{
+	if (!transfer_func) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_target_t target = {
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
+	};
+
+	size_t len;
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &len)) {
+		async_answer_0(callid, EPARTY);
+		return;
+	}
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+	trans->data_caller = data_callid;
+	trans->buffer = malloc(len);
+	trans->size = len;
+
+	int rc = transfer_func(fun, target,
+	    trans->buffer, len,
+	    callback_in, trans);
+
+	if (rc != EOK) {
+		async_answer_0(data_callid, rc);
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
+}
+
+void remote_usbhc_interrupt_out(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	return remote_usbhc_out_transfer(fun, callid, call,
+	    usb_iface->interrupt_out);
+}
+
+void remote_usbhc_interrupt_in(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	return remote_usbhc_in_transfer(fun, callid, call,
+	    usb_iface->interrupt_in);
+}
+
+void remote_usbhc_bulk_out(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	return remote_usbhc_out_transfer(fun, callid, call,
+	    usb_iface->bulk_out);
+}
+
+void remote_usbhc_bulk_in(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	return remote_usbhc_in_transfer(fun, callid, call,
+	    usb_iface->bulk_in);
+}
+
+void remote_usbhc_control_write(ddf_fun_t *fun, void *iface,
+ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	if (!usb_iface->control_write) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_target_t target = {
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
+	};
+	size_t data_buffer_len = DEV_IPC_GET_ARG3(*call);
+
+	int rc;
+
+	void *setup_packet = NULL;
+	void *data_buffer = NULL;
+	size_t setup_packet_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (data_buffer_len > 0) {
+		rc = async_data_write_accept(&data_buffer, false,
+		    1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			free(setup_packet);
+			return;
+		}
+	}
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		async_answer_0(callid, ENOMEM);
+		free(setup_packet);
+		free(data_buffer);
+		return;
+	}
+	trans->setup_packet = setup_packet;
+	trans->buffer = data_buffer;
+	trans->size = data_buffer_len;
+
+	rc = usb_iface->control_write(fun, target,
+	    setup_packet, setup_packet_len,
+	    data_buffer, data_buffer_len,
+	    callback_out, trans);
+
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
+}
+
+
+void remote_usbhc_control_read(ddf_fun_t *fun, void *iface,
+ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	if (!usb_iface->control_read) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_target_t target = {
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
+	};
+
+	int rc;
+
+	void *setup_packet = NULL;
+	size_t setup_packet_len = 0;
+	size_t data_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(callid, EPARTY);
+		free(setup_packet);
+		return;
+	}
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		free(setup_packet);
+		return;
+	}
+	trans->data_caller = data_callid;
+	trans->setup_packet = setup_packet;
+	trans->size = data_len;
+	trans->buffer = malloc(data_len);
+	if (trans->buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		async_transaction_destroy(trans);
+		return;
+	}
+
+	rc = usb_iface->control_read(fun, target,
+	    setup_packet, setup_packet_len,
+	    trans->buffer, trans->size,
+	    callback_in, trans);
+
+	if (rc != EOK) {
+		async_answer_0(data_callid, rc);
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
+}
+
+
+void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->register_endpoint) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+#define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
+	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
+#define _INIT_FROM_LOW_DATA2(type, var, arg_no) \
+	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16)
+#define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \
+	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
+#define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \
+	type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8)
+#define _INIT_FROM_LOW_DATA3(type, var, arg_no) \
+	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
+
+	_INIT_FROM_HIGH_DATA2(usb_address_t, address, 1);
+	_INIT_FROM_LOW_DATA2(usb_endpoint_t, endpoint, 1);
+
+	_INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
+	_INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2);
+	_INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2);
+
+	_INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);
+	_INIT_FROM_LOW_DATA2(unsigned int, interval, 3);
+
+#undef _INIT_FROM_HIGH_DATA2
+#undef _INIT_FROM_LOW_DATA2
+#undef _INIT_FROM_HIGH_DATA3
+#undef _INIT_FROM_MIDDLE_DATA3
+#undef _INIT_FROM_LOW_DATA3
+
+	int rc = usb_iface->register_endpoint(fun, address, speed, endpoint,
+	    transfer_type, direction, max_packet_size, interval);
+
+	async_answer_0(callid, rc);
+}
+
+
+void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->unregister_endpoint) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
+	usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);
+	usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);
+
+	int rc = usb_iface->unregister_endpoint(fun,
+	    address, endpoint, direction);
+
+	async_answer_0(callid, rc);
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/generic/remote_usbhid.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/generic/remote_usbhid.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2010-2011 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdio.h>
+
+#include "usbhid_iface.h"
+#include "ddf/driver.h"
+
+static void remote_usbhid_get_event_length(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhid_get_event(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhid_get_report_descriptor_length(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhid_get_report_descriptor(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+// static void remote_usbhid_(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+
+/** Remote USB HID interface operations. */
+static remote_iface_func_ptr_t remote_usbhid_iface_ops [] = {
+	remote_usbhid_get_event_length,
+	remote_usbhid_get_event,
+	remote_usbhid_get_report_descriptor_length,
+	remote_usbhid_get_report_descriptor
+};
+
+/** Remote USB HID interface structure.
+ */
+remote_iface_t remote_usbhid_iface = {
+	.method_count = sizeof(remote_usbhid_iface_ops) /
+	    sizeof(remote_usbhid_iface_ops[0]),
+	.methods = remote_usbhid_iface_ops
+};
+
+//usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+
+void remote_usbhid_get_event_length(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	printf("remote_usbhid_get_event_length()\n");
+	
+	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
+
+	if (!hid_iface->get_event_length) {
+		printf("Get event length not set!\n");
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t len = hid_iface->get_event_length(fun);
+//	if (len == 0) {
+//		len = EEMPTY;
+//	}
+	async_answer_1(callid, EOK, len);
+	
+//	if (len < 0) {
+//		async_answer_0(callid, len);
+//	} else {
+//		async_answer_1(callid, EOK, len);
+//	}
+}
+
+void remote_usbhid_get_event(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
+
+	if (!hid_iface->get_event) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	unsigned int flags = DEV_IPC_GET_ARG1(*call);
+
+	size_t len;
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &len)) {
+		async_answer_0(callid, EPARTY);
+		return;
+	}
+//	/* Check that length is even number. Truncate otherwise. */
+//	if ((len % 2) == 1) {
+//		len--;
+//	}
+	if (len == 0) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	int rc;
+
+	uint8_t *data = malloc(len);
+	if (data == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	size_t act_length;
+	int event_nr;
+	rc = hid_iface->get_event(fun, data, len, &act_length, &event_nr, flags);
+	if (rc != EOK) {
+		free(data);
+		async_answer_0(data_callid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+	if (act_length >= len) {
+		/* This shall not happen. */
+		// FIXME: how about an assert here?
+		act_length = len;
+	}
+
+	async_data_read_finalize(data_callid, data, act_length);
+
+	free(data);
+
+	async_answer_1(callid, EOK, event_nr);
+}
+
+void remote_usbhid_get_report_descriptor_length(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
+
+	if (!hid_iface->get_report_descriptor_length) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t len = hid_iface->get_report_descriptor_length(fun);
+	async_answer_1(callid, EOK, (sysarg_t) len);
+}
+
+void remote_usbhid_get_report_descriptor(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
+
+	if (!hid_iface->get_report_descriptor) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t len;
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &len)) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (len == 0) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	uint8_t *descriptor = malloc(len);
+	if (descriptor == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	size_t act_len = 0;
+	int rc = hid_iface->get_report_descriptor(fun, descriptor, len,
+	    &act_len);
+	if (act_len > len) {
+		rc = ELIMIT;
+	}
+	if (rc != EOK) {
+		free(descriptor);
+		async_answer_0(data_callid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	async_data_read_finalize(data_callid, descriptor, act_len);
+	async_answer_0(callid, EOK);
+
+	free(descriptor);
+}
+
+
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/drv/include/ddf/driver.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,7 +37,7 @@
 #define DDF_DRIVER_H_
 
+#include <async.h>
 #include <ipc/devman.h>
 #include <ipc/dev_iface.h>
-
 #include "../dev_iface.h"
 
@@ -83,8 +83,8 @@
 	
 	/**
-	 * Phone to the parent device driver (if it is different from this
+	 * Session to the parent device driver (if it is different from this
 	 * driver)
 	 */
-	int parent_phone;
+	async_sess_t *parent_sess;
 	
 	/** Device name */
@@ -118,4 +118,6 @@
 	/** Implementation of operations provided by this function */
 	ddf_dev_ops_t *ops;
+	/** Connection handler or @c NULL to use the DDF default handler. */
+	async_client_conn_t conn_handler;
 	
 	/** Link in the list of functions handled by the driver */
@@ -147,7 +149,8 @@
 extern void ddf_fun_destroy(ddf_fun_t *);
 extern int ddf_fun_bind(ddf_fun_t *);
+extern int ddf_fun_unbind(ddf_fun_t *);
 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
 
-extern int ddf_fun_add_to_class(ddf_fun_t *, const char *);
+extern int ddf_fun_add_to_category(ddf_fun_t *, const char *);
 
 #endif
Index: uspace/lib/drv/include/ddf/interrupt.h
===================================================================
--- uspace/lib/drv/include/ddf/interrupt.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/drv/include/ddf/interrupt.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,5 +36,5 @@
 #define DDF_INTERRUPT_H_
 
-#include <kernel/ddi/irq.h>
+#include <abi/ddi/irq.h>
 #include <adt/list.h>
 #include <ddi.h>
@@ -60,5 +60,5 @@
 typedef struct interrupt_context_list {
 	int curr_id;
-	link_t contexts;
+	list_t contexts;
 	fibril_mutex_t mutex;
 } interrupt_context_list_t;
Index: uspace/lib/drv/include/ddf/log.h
===================================================================
--- uspace/lib/drv/include/ddf/log.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/ddf/log.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libdrv
+ * @{
+ */
+
+#ifndef DDF_LOG_H_
+#define DDF_LOG_H_
+
+#include <io/log.h>
+
+extern int ddf_log_init(const char *, log_level_t);
+extern void ddf_msg(log_level_t, const char *, ...);
+
+extern void ddf_dump_buffer(char *, size_t, const void *, size_t, size_t,
+    size_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/drv/include/pci_dev_iface.h
===================================================================
--- uspace/lib/drv/include/pci_dev_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/pci_dev_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,68 @@
+/*
+ * 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 libdrv
+ * @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief PCI device interface definition.
+ */
+
+#ifndef LIBDRV_PCI_DEV_IFACE_H_
+#define LIBDRV_PCI_DEV_IFACE_H_
+
+#include "ddf/driver.h"
+
+typedef enum {
+	IPC_M_CONFIG_SPACE_READ_8,
+	IPC_M_CONFIG_SPACE_READ_16,
+	IPC_M_CONFIG_SPACE_READ_32,
+
+	IPC_M_CONFIG_SPACE_WRITE_8,
+	IPC_M_CONFIG_SPACE_WRITE_16,
+	IPC_M_CONFIG_SPACE_WRITE_32
+} pci_dev_iface_funcs_t;
+
+/** PCI device communication interface. */
+typedef struct {
+	int (*config_space_read_8)(ddf_fun_t *, uint32_t address, uint8_t *data);
+	int (*config_space_read_16)(ddf_fun_t *, uint32_t address, uint16_t *data);
+	int (*config_space_read_32)(ddf_fun_t *, uint32_t address, uint32_t *data);
+
+	int (*config_space_write_8)(ddf_fun_t *, uint32_t address, uint8_t data);
+	int (*config_space_write_16)(ddf_fun_t *, uint32_t address, uint16_t data);
+	int (*config_space_write_32)(ddf_fun_t *, uint32_t address, uint32_t data);
+} pci_dev_iface_t;
+
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/include/remote_pci.h
===================================================================
--- uspace/lib/drv/include/remote_pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/remote_pci.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_PCI_H_
+#define LIBDRV_REMOTE_PCI_H_
+
+extern remote_iface_t remote_pci_iface;
+
+#endif
+
+/**
+ * @}
+ */
+
Index: uspace/lib/drv/include/remote_usb.h
===================================================================
--- uspace/lib/drv/include/remote_usb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/remote_usb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_USB_H_
+#define LIBDRV_REMOTE_USB_H_
+
+extern remote_iface_t remote_usb_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_usbhc.h
===================================================================
--- uspace/lib/drv/include/remote_usbhc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/remote_usbhc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_USBHC_H_
+#define LIBDRV_REMOTE_USBHC_H_
+
+extern remote_iface_t remote_usbhc_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_usbhid.h
===================================================================
--- uspace/lib/drv/include/remote_usbhid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/remote_usbhid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_USBHID_H_
+#define LIBDRV_REMOTE_USBHID_H_
+
+extern remote_iface_t remote_usbhid_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/usb_iface.h
===================================================================
--- uspace/lib/drv/include/usb_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/usb_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,101 @@
+/*
+ * 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 libdrv
+ * @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief USB interface definition.
+ */
+
+#ifndef LIBDRV_USB_IFACE_H_
+#define LIBDRV_USB_IFACE_H_
+
+#include "ddf/driver.h"
+#include <usb/usb.h>
+typedef enum {
+	/** Tell USB address assigned to device.
+	 * Parameters:
+	 * - devman handle id
+	 * Answer:
+	 * - EINVAL - unknown handle or handle not managed by this driver
+	 * - ENOTSUP - operation not supported (shall not happen)
+	 * - arbitrary error code if returned by remote implementation
+	 * - EOK - handle found, first parameter contains the USB address
+	 *
+	 * The handle must be the one used for binding USB address with
+	 * it (IPC_M_USBHC_BIND_ADDRESS), otherwise the host controller
+	 * (that this request would eventually reach) would not be able
+	 * to find it.
+	 * The problem is that this handle is actually assigned to the
+	 * function inside driver of the parent device (usually hub driver).
+	 * To bypass this problem, the initial caller specify handle as
+	 * zero and the first parent assigns the actual value.
+	 * See usb_iface_get_address_hub_child_impl() implementation
+	 * that could be assigned to device ops of a child device of in a
+	 * hub driver.
+	 * For example, the USB multi interface device driver (MID)
+	 * passes this initial zero without any modification because the
+	 * handle must be resolved by its parent.
+	 */
+	IPC_M_USB_GET_ADDRESS,
+
+	/** Tell interface number given device can use.
+	 * Parameters
+	 * - devman handle id of the device
+	 * Answer:
+	 * - ENOTSUP - operation not supported (can also mean any interface)
+	 * - EOK - operation okay, first parameter contains interface number
+	 */
+	IPC_M_USB_GET_INTERFACE,
+
+	/** Tell devman handle of device host controller.
+	 * Parameters:
+	 * - none
+	 * Answer:
+	 * - EOK - request processed without errors
+	 * - ENOTSUP - this indicates invalid USB driver
+	 * Parameters of the answer:
+	 * - devman handle of HC caller is physically connected to
+	 */
+	IPC_M_USB_GET_HOST_CONTROLLER_HANDLE
+} usb_iface_funcs_t;
+
+/** USB device communication interface. */
+typedef struct {
+	int (*get_address)(ddf_fun_t *, devman_handle_t, usb_address_t *);
+	int (*get_interface)(ddf_fun_t *, devman_handle_t, int *);
+	int (*get_hc_handle)(ddf_fun_t *, devman_handle_t *);
+} usb_iface_t;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,244 @@
+/*
+ * 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 libdrv
+ * @addtogroup usb
+ * @{
+ */
+/** @file
+ * @brief USB host controller interface definition.
+ */
+
+#ifndef LIBDRV_USBHC_IFACE_H_
+#define LIBDRV_USBHC_IFACE_H_
+
+#include "ddf/driver.h"
+#include <usb/usb.h>
+#include <bool.h>
+
+
+/** IPC methods for communication with HC through DDF interface.
+ *
+ * Notes for async methods:
+ *
+ * Methods for sending data to device (OUT transactions)
+ * - e.g. IPC_M_USBHC_INTERRUPT_OUT -
+ * always use the same semantics:
+ * - first, IPC call with given method is made
+ *   - argument #1 is target address
+ *   - argument #2 is target endpoint
+ *   - argument #3 is max packet size of the endpoint
+ * - this call is immediately followed by IPC data write (from caller)
+ * - the initial call (and the whole transaction) is answer after the
+ *   transaction is scheduled by the HC and acknowledged by the device
+ *   or immediately after error is detected
+ * - the answer carries only the error code
+ *
+ * Methods for retrieving data from device (IN transactions)
+ * - e.g. IPC_M_USBHC_INTERRUPT_IN -
+ * also use the same semantics:
+ * - first, IPC call with given method is made
+ *   - argument #1 is target address
+ *   - argument #2 is target endpoint
+ * - this call is immediately followed by IPC data read (async version)
+ * - the call is not answered until the device returns some data (or until
+ *   error occurs)
+ *
+ * Some special methods (NO-DATA transactions) do not send any data. These
+ * might behave as both OUT or IN transactions because communication parts
+ * where actual buffers are exchanged are omitted.
+ **
+ * For all these methods, wrap functions exists. Important rule: functions
+ * for IN transactions have (as parameters) buffers where retrieved data
+ * will be stored. These buffers must be already allocated and shall not be
+ * touch until the transaction is completed
+ * (e.g. not before calling usb_wait_for() with appropriate handle).
+ * OUT transactions buffers can be freed immediately after call is dispatched
+ * (i.e. after return from wrapping function).
+ *
+ */
+typedef enum {
+	/** Asks for address assignment by host controller.
+	 * Answer:
+	 * - ELIMIT - host controller run out of address
+	 * - EOK - address assigned
+	 * Answer arguments:
+	 * - assigned address
+	 *
+	 * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS.
+	 */
+	IPC_M_USBHC_REQUEST_ADDRESS,
+
+	/** Bind USB address with devman handle.
+	 * Parameters:
+	 * - USB address
+	 * - devman handle
+	 * Answer:
+	 * - EOK - address binded
+	 * - ENOENT - address is not in use
+	 */
+	IPC_M_USBHC_BIND_ADDRESS,
+
+	/** Get handle binded with given USB address.
+	 * Parameters
+	 * - USB address
+	 * Answer:
+	 * - EOK - address binded, first parameter is the devman handle
+	 * - ENOENT - address is not in use at the moment
+	 */
+	IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
+
+	/** Release address in use.
+	 * Arguments:
+	 * - address to be released
+	 * Answer:
+	 * - ENOENT - address not in use
+	 * - EPERM - trying to release default USB address
+	 */
+	IPC_M_USBHC_RELEASE_ADDRESS,
+
+
+	/** Send interrupt data to device.
+	 * See explanation at usb_iface_funcs_t (OUT transaction).
+	 */
+	IPC_M_USBHC_INTERRUPT_OUT,
+
+	/** Get interrupt data from device.
+	 * See explanation at usb_iface_funcs_t (IN transaction).
+	 */
+	IPC_M_USBHC_INTERRUPT_IN,
+
+	/** Send bulk data to device.
+	 * See explanation at usb_iface_funcs_t (OUT transaction).
+	 */
+	IPC_M_USBHC_BULK_OUT,
+
+	/** Get bulk data from device.
+	 * See explanation at usb_iface_funcs_t (IN transaction).
+	 */
+	IPC_M_USBHC_BULK_IN,
+
+	/** Issue control WRITE transfer.
+	 * See explanation at usb_iface_funcs_t (OUT transaction) for
+	 * call parameters.
+	 * This call is immediately followed by two IPC data writes
+	 * from the caller (setup packet and actual data).
+	 */
+	IPC_M_USBHC_CONTROL_WRITE,
+
+	/** Issue control READ transfer.
+	 * See explanation at usb_iface_funcs_t (IN transaction) for
+	 * call parameters.
+	 * This call is immediately followed by IPC data write from the caller
+	 * (setup packet) and IPC data read (buffer that was read).
+	 */
+	IPC_M_USBHC_CONTROL_READ,
+
+	/** Register endpoint attributes at host controller.
+	 * This is used to reserve portion of USB bandwidth.
+	 * When speed is invalid, speed of the device is used.
+	 * Parameters:
+	 * - USB address + endpoint number
+	 *   - packed as ADDR << 16 + EP
+	 * - speed + transfer type + direction
+	 *   - packed as ( SPEED << 8 + TYPE ) << 8 + DIR
+	 * - maximum packet size + interval (in milliseconds)
+	 *   - packed as MPS << 16 + INT
+	 * Answer:
+	 * - EOK - reservation successful
+	 * - ELIMIT - not enough bandwidth to satisfy the request
+	 */
+	IPC_M_USBHC_REGISTER_ENDPOINT,
+
+	/** Revert endpoint registration.
+	 * Parameters:
+	 * - USB address
+	 * - endpoint number
+	 * - data direction
+	 * Answer:
+	 * - EOK - endpoint unregistered
+	 * - ENOENT - unknown endpoint
+	 */
+	IPC_M_USBHC_UNREGISTER_ENDPOINT
+} usbhc_iface_funcs_t;
+
+/** Callback for outgoing transfer. */
+typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *,
+    int, void *);
+
+/** Callback for incoming transfer. */
+typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *,
+    int, size_t, void *);
+
+
+/** Out transfer processing function prototype. */
+typedef int (*usbhc_iface_transfer_out_t)(ddf_fun_t *, usb_target_t,
+    void *, size_t,
+    usbhc_iface_transfer_out_callback_t, void *);
+
+/** Setup transfer processing function prototype. @deprecated */
+typedef usbhc_iface_transfer_out_t usbhc_iface_transfer_setup_t;
+
+/** In transfer processing function prototype. */
+typedef int (*usbhc_iface_transfer_in_t)(ddf_fun_t *, usb_target_t,
+    void *, size_t,
+    usbhc_iface_transfer_in_callback_t, void *);
+
+/** USB host controller communication interface. */
+typedef struct {
+	int (*request_address)(ddf_fun_t *, usb_speed_t, usb_address_t *);
+	int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t);
+	int (*find_by_address)(ddf_fun_t *, usb_address_t, devman_handle_t *);
+	int (*release_address)(ddf_fun_t *, usb_address_t);
+
+	int (*register_endpoint)(ddf_fun_t *,
+	    usb_address_t, usb_speed_t, usb_endpoint_t,
+	    usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
+	int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
+	    usb_direction_t);
+
+	usbhc_iface_transfer_out_t interrupt_out;
+	usbhc_iface_transfer_in_t interrupt_in;
+
+	usbhc_iface_transfer_out_t bulk_out;
+	usbhc_iface_transfer_in_t bulk_in;
+
+	int (*control_write)(ddf_fun_t *, usb_target_t,
+	    void *, size_t, void *, size_t,
+	    usbhc_iface_transfer_out_callback_t, void *);
+
+	int (*control_read)(ddf_fun_t *, usb_target_t,
+	    void *, size_t, void *, size_t,
+	    usbhc_iface_transfer_in_callback_t, void *);
+} usbhc_iface_t;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/usbhid_iface.h
===================================================================
--- uspace/lib/drv/include/usbhid_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/drv/include/usbhid_iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,136 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ * USB HID interface definition.
+ */
+
+#ifndef LIBDRV_USBHID_IFACE_H_
+#define LIBDRV_USBHID_IFACE_H_
+
+#include "ddf/driver.h"
+#include <usb/usb.h>
+
+/** IPC methods for USB HID device interface. */
+typedef enum {
+	/** Get number of events reported in single burst.
+	 * Parameters: none
+	 * Answer:
+	 * - Size of one report in bytes.
+	 */
+	IPC_M_USBHID_GET_EVENT_LENGTH,
+	/** Get single event from the HID device.
+	 * The word single refers to set of individual events that were
+	 * available at particular point in time.
+	 * Parameters:
+	 * - flags
+	 * The call is followed by data read expecting two concatenated
+	 * arrays.
+	 * Answer:
+	 * - EOK - events returned
+	 * - EAGAIN - no event ready (only in non-blocking mode)
+	 *
+	 * It is okay if the client requests less data. Extra data must
+	 * be truncated by the driver.
+	 *
+	 * @todo Change this comment.
+	 */
+	IPC_M_USBHID_GET_EVENT,
+	
+	/** Get the size of the report descriptor from the HID device.
+	 *
+	 * Parameters:
+	 * - none
+	 * Answer:
+	 * - EOK - method is implemented (expected always)
+	 * Parameters of the answer:
+	 * - Size of the report in bytes.
+	 */
+	IPC_M_USBHID_GET_REPORT_DESCRIPTOR_LENGTH,
+	
+	/** Get the report descriptor from the HID device.
+	 *
+	 * Parameters:
+	 * - none
+	 * The call is followed by data read expecting the descriptor itself.
+	 * Answer:
+	 * - EOK - report descriptor returned.
+	 */
+	IPC_M_USBHID_GET_REPORT_DESCRIPTOR
+} usbhid_iface_funcs_t;
+
+/** USB HID interface flag - return immediately if no data are available. */
+#define USBHID_IFACE_FLAG_NON_BLOCKING (1 << 0)
+
+/** USB HID device communication interface. */
+typedef struct {
+	/** Get size of the event in bytes.
+	 *
+	 * @param[in] fun DDF function answering the request.
+	 * @return Size of the event in bytes.
+	 */
+	size_t (*get_event_length)(ddf_fun_t *fun);
+
+	/** Get single event from the HID device.
+	 *
+	 * @param[in] fun DDF function answering the request.
+	 * @param[out] buffer Buffer with raw data from the device.
+	 * @param[out] act_size Actual number of returned events.
+	 * @param[in] flags Flags (see USBHID_IFACE_FLAG_*).
+	 * @return Error code.
+	 */
+	int (*get_event)(ddf_fun_t *fun, uint8_t *buffer, size_t size,
+	    size_t *act_size, int *event_nr, unsigned int flags);
+	
+	/** Get size of the report descriptor in bytes.
+	 *
+	 * @param[in] fun DDF function answering the request.
+	 * @return Size of the report descriptor in bytes.
+	 */
+	size_t (*get_report_descriptor_length)(ddf_fun_t *fun);
+	
+	/** Get the report descriptor from the HID device.
+	 *
+	 * @param[in] fun DDF function answering the request.
+	 * @param[out] desc Buffer with the report descriptor.
+	 * @param[in] size Size of the allocated @p desc buffer.
+	 * @param[out] act_size Actual size of the report descriptor returned.
+	 * @return Error code.
+	 */
+	int (*get_report_descriptor)(ddf_fun_t *fun, uint8_t *desc, 
+	    size_t size, size_t *act_size);
+} usbhid_iface_t;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/ext2/Makefile
===================================================================
--- uspace/lib/ext2/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# Copyright (c) 2010 Martin Sucha
+# 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 = ../..
+LIBRARY = libext2
+EXTRA_CFLAGS = -I$(LIBBLOCK_PREFIX)
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a
+
+SOURCES = \
+	libext2_filesystem.c \
+	libext2_superblock.c \
+	libext2_block_group.c \
+	libext2_inode.c \
+	libext2_directory.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/ext2/libext2.h
===================================================================
--- uspace/lib/ext2/libext2.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBEXT2_LIBEXT2_H_
+#define LIBEXT2_LIBEXT2_H_
+
+#include "libext2_superblock.h"
+#include "libext2_block_group.h"
+#include "libext2_inode.h"
+#include "libext2_filesystem.h"
+#include "libext2_directory.h"
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_block_group.c
===================================================================
--- uspace/lib/ext2/libext2_block_group.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_block_group.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "libext2.h"
+#include "libext2_block_group.h"
+#include <byteorder.h>
+
+/**
+ * Get block ID corresponding to the block bitmap of this block group
+ * 
+ * @param bg pointer to block group descriptor
+ */
+uint32_t ext2_block_group_get_block_bitmap_block(ext2_block_group_t *bg)
+{
+	return uint32_t_le2host(bg->block_bitmap_block);
+}
+
+/**
+ * Get block ID corresponding to the inode bitmap of this block group
+ * 
+ * @param bg pointer to block group descriptor
+ */
+uint32_t ext2_block_group_get_inode_bitmap_block(ext2_block_group_t *bg)
+{
+	return uint32_t_le2host(bg->inode_bitmap_block);
+}
+
+/**
+ * Get block ID of first block in inode table
+ * 
+ * @param bg pointer to block group descriptor
+ */
+uint32_t ext2_block_group_get_inode_table_first_block(ext2_block_group_t *bg)
+{
+	return uint32_t_le2host(bg->inode_table_first_block);
+}
+
+/**
+ * Get amount of free blocks in this block group
+ * 
+ * @param bg pointer to block group descriptor
+ */
+uint16_t ext2_block_group_get_free_block_count(ext2_block_group_t *bg)
+{
+	return uint16_t_le2host(bg->free_block_count);
+}
+
+/**
+ * Set amount of free blocks in this block group
+ * 
+ * @param bg pointer to block group descriptor
+ * @param val new value
+ */
+void ext2_block_group_set_free_block_count(ext2_block_group_t *bg,
+	uint16_t val)
+{
+	bg->free_block_count = host2uint16_t_le(val);
+}
+
+/**
+ * Get amount of free inodes in this block group
+ * 
+ * @param bg pointer to block group descriptor
+ */
+uint16_t ext2_block_group_get_free_inode_count(ext2_block_group_t *bg)
+{
+	return uint16_t_le2host(bg->free_inode_count);
+}
+
+/**
+ * Get amount of inodes allocated for directories
+ * 
+ * @param bg pointer to block group descriptor
+ */
+uint16_t ext2_block_group_get_directory_inode_count(ext2_block_group_t *bg)
+{
+	return uint16_t_le2host(bg->directory_inode_count);
+}
+
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_block_group.h
===================================================================
--- uspace/lib/ext2/libext2_block_group.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_block_group.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBEXT2_LIBEXT2_BLOCK_GROUP_H_
+#define LIBEXT2_LIBEXT2_BLOCK_GROUP_H_
+
+#include <libblock.h>
+
+typedef struct ext2_block_group {
+	uint32_t block_bitmap_block; // Block ID for block bitmap
+	uint32_t inode_bitmap_block; // Block ID for inode bitmap
+	uint32_t inode_table_first_block; // Block ID of first block of inode table 
+	uint16_t free_block_count; // Count of free blocks
+	uint16_t free_inode_count; // Count of free inodes
+	uint16_t directory_inode_count; // Number of inodes allocated to directories
+} ext2_block_group_t;
+
+typedef struct ext2_block_group_ref {
+	block_t *block; // Reference to a block containing this block group descr
+	ext2_block_group_t *block_group;
+} ext2_block_group_ref_t;
+
+#define EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE 32
+
+extern uint32_t	ext2_block_group_get_block_bitmap_block(ext2_block_group_t *);
+extern uint32_t	ext2_block_group_get_inode_bitmap_block(ext2_block_group_t *);
+extern uint32_t	ext2_block_group_get_inode_table_first_block(ext2_block_group_t *);
+extern uint16_t	ext2_block_group_get_free_block_count(ext2_block_group_t *);
+extern uint16_t	ext2_block_group_get_free_inode_count(ext2_block_group_t *);
+extern uint16_t	ext2_block_group_get_directory_inode_count(ext2_block_group_t *);
+
+extern void	ext2_block_group_set_free_block_count(ext2_block_group_t *, uint16_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_directory.c
===================================================================
--- uspace/lib/ext2/libext2_directory.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_directory.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "libext2.h"
+#include "libext2_directory.h"
+#include <byteorder.h>
+#include <errno.h>
+#include <assert.h>
+
+static int ext2_directory_iterator_set(ext2_directory_iterator_t *it,
+    uint32_t block_size);
+
+/**
+ * Get inode number for the directory entry
+ * 
+ * @param de pointer to linked list directory entry
+ */
+uint32_t ext2_directory_entry_ll_get_inode(ext2_directory_entry_ll_t *de)
+{
+	return uint32_t_le2host(de->inode);
+}
+
+/**
+ * Get length of the directory entry
+ * 
+ * @param de pointer to linked list directory entry
+ */
+uint16_t ext2_directory_entry_ll_get_entry_length(
+    ext2_directory_entry_ll_t *de)
+{
+	return uint16_t_le2host(de->entry_length);
+}
+
+/**
+ * Get length of the name stored in the directory entry
+ * 
+ * @param de pointer to linked list directory entry
+ */
+uint16_t ext2_directory_entry_ll_get_name_length(
+    ext2_superblock_t *sb, ext2_directory_entry_ll_t *de)
+{
+	if (ext2_superblock_get_rev_major(sb) == 0 &&
+	    ext2_superblock_get_rev_minor(sb) < 5) {
+		return ((uint16_t)de->name_length_high) << 8 | 
+		    ((uint16_t)de->name_length);
+	}
+	return de->name_length;
+}
+
+/**
+ * Initialize a directory iterator
+ * 
+ * @param it pointer to iterator to initialize
+ * @param fs pointer to filesystem structure
+ * @param inode pointer to inode reference structure
+ * @param pos position within inode to start at, 0 is the first entry
+ * @return EOK on success or negative error code on failure
+ */
+int ext2_directory_iterator_init(ext2_directory_iterator_t *it,
+    ext2_filesystem_t *fs, ext2_inode_ref_t *inode_ref, aoff64_t pos)
+{	
+	it->inode_ref = inode_ref;
+	it->fs = fs;
+	it->current = NULL;
+	it->current_offset = 0;
+	it->current_block = NULL;
+	
+	return ext2_directory_iterator_seek(it, pos);
+}
+
+/**
+ * Advance the directory iterator to the next entry
+ * 
+ * @param it pointer to iterator to initialize
+ * @return EOK on success or negative error code on failure
+ */
+int ext2_directory_iterator_next(ext2_directory_iterator_t *it)
+{
+	uint16_t skip;
+	
+	assert(it->current != NULL);
+	
+	skip = ext2_directory_entry_ll_get_entry_length(it->current);
+	
+	return ext2_directory_iterator_seek(it, it->current_offset + skip);
+}
+
+/**
+ * Seek the directory iterator to the given byte offset within the inode.
+ * 
+ * @param it pointer to iterator to initialize
+ * @return EOK on success or negative error code on failure
+ */
+int ext2_directory_iterator_seek(ext2_directory_iterator_t *it, aoff64_t pos)
+{
+	int rc;
+	
+	uint64_t size;
+	aoff64_t current_block_idx;
+	aoff64_t next_block_idx;
+	uint32_t next_block_phys_idx;
+	uint32_t block_size;
+	
+	size = ext2_inode_get_size(it->fs->superblock, it->inode_ref->inode);
+	
+	/* The iterator is not valid until we seek to the desired position */
+	it->current = NULL;
+	
+	/* Are we at the end? */
+	if (pos >= size) {		
+		if (it->current_block) {
+			rc = block_put(it->current_block);
+			it->current_block = NULL;
+			if (rc != EOK) {
+				return rc;
+			}
+		}
+		
+		it->current_offset = pos;
+		return EOK;
+	}
+	
+	block_size = ext2_superblock_get_block_size(it->fs->superblock);
+	current_block_idx = it->current_offset / block_size;
+	next_block_idx = pos / block_size;
+	
+	/* If we don't have a block or are moving accross block boundary,
+	 * we need to get another block
+	 */
+	if (it->current_block == NULL || current_block_idx != next_block_idx) {		
+		if (it->current_block) {
+			rc = block_put(it->current_block);
+			it->current_block = NULL;
+			if (rc != EOK) {
+				return rc;
+			}
+		}
+		
+		rc = ext2_filesystem_get_inode_data_block_index(it->fs,
+		    it->inode_ref->inode, next_block_idx, &next_block_phys_idx);
+		if (rc != EOK) {
+			return rc;
+		}
+		
+		rc = block_get(&it->current_block, it->fs->device, next_block_phys_idx,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			it->current_block = NULL;
+			return rc;
+		}
+	}
+	
+	it->current_offset = pos;
+	return ext2_directory_iterator_set(it, block_size);
+}
+
+/** Setup the entry at the current iterator offset.
+ * 
+ * This function checks the validity of the directory entry,
+ * before setting the data pointer.
+ *
+ * @return EOK on success or error code on failure 
+ */
+static int ext2_directory_iterator_set(ext2_directory_iterator_t *it,
+    uint32_t block_size)
+{
+	uint32_t offset_in_block = it->current_offset % block_size;
+	
+	it->current = NULL;
+	
+	/* Ensure proper alignment */
+	if ((offset_in_block % 4) != 0) {
+		return EIO;
+	}
+	
+	/* Ensure that the core of the entry does not overflow the block */
+	if (offset_in_block > block_size - 8) {
+		return EIO;
+	}
+	
+	ext2_directory_entry_ll_t *entry = it->current_block->data + offset_in_block;
+	
+	/* Ensure that the whole entry does not overflow the block */
+	uint16_t length = ext2_directory_entry_ll_get_entry_length(entry);
+	if (offset_in_block + length > block_size) {
+		return EIO;
+	}
+	
+	/* Ensure the name length is not too large */
+	if (ext2_directory_entry_ll_get_name_length(it->fs->superblock, 
+	    entry) > length-8) {
+		return EIO;
+	}
+	
+	it->current = entry;
+	return EOK;
+}
+
+/**
+ * Release all resources asociated with the directory iterator
+ * 
+ * @param it pointer to iterator to initialize
+ * @return EOK on success or negative error code on failure
+ */
+int ext2_directory_iterator_fini(ext2_directory_iterator_t *it)
+{
+	int rc;
+	
+	it->fs = NULL;
+	it->inode_ref = NULL;
+	it->current = NULL;
+	
+	if (it->current_block) {
+		rc = block_put(it->current_block);
+		if (rc != EOK) {
+			return rc;
+		}
+	}
+	
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_directory.h
===================================================================
--- uspace/lib/ext2/libext2_directory.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_directory.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBEXT2_LIBEXT2_DIRECTORY_H_
+#define LIBEXT2_LIBEXT2_DIRECTORY_H_
+
+#include <libblock.h>
+#include "libext2_filesystem.h"
+#include "libext2_inode.h"
+
+/**
+ * Linked list directory entry structure
+ */
+typedef struct ext2_directory_entry_ll {
+	uint32_t inode; // Inode for the entry
+	uint16_t entry_length; // Distance to the next directory entry
+	uint8_t name_length; // Lower 8 bits of name length
+	union {
+		uint8_t name_length_high; // Higher 8 bits of name length
+		uint8_t inode_type; // Type of referenced inode (in rev >= 0.5)
+	} __attribute__ ((packed));
+	uint8_t name; // First byte of name, if present
+} __attribute__ ((packed)) ext2_directory_entry_ll_t;
+
+typedef struct ext2_directory_iterator {
+	ext2_filesystem_t *fs;
+	ext2_inode_ref_t *inode_ref;
+	block_t *current_block;
+	aoff64_t current_offset;
+	ext2_directory_entry_ll_t *current;
+} ext2_directory_iterator_t;
+
+
+extern uint32_t	ext2_directory_entry_ll_get_inode(ext2_directory_entry_ll_t *);
+extern uint16_t	ext2_directory_entry_ll_get_entry_length(
+    ext2_directory_entry_ll_t *);
+extern uint16_t	ext2_directory_entry_ll_get_name_length(
+    ext2_superblock_t *, ext2_directory_entry_ll_t *);
+
+extern int ext2_directory_iterator_init(ext2_directory_iterator_t *,
+    ext2_filesystem_t *, ext2_inode_ref_t *, aoff64_t);
+extern int ext2_directory_iterator_next(ext2_directory_iterator_t *);
+extern int ext2_directory_iterator_seek(ext2_directory_iterator_t *, aoff64_t pos);
+extern int ext2_directory_iterator_fini(ext2_directory_iterator_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_filesystem.c
===================================================================
--- uspace/lib/ext2/libext2_filesystem.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_filesystem.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "libext2_filesystem.h"
+#include "libext2_superblock.h"
+#include "libext2_block_group.h"
+#include "libext2_inode.h"
+#include <errno.h>
+#include <libblock.h>
+#include <malloc.h>
+#include <assert.h>
+#include <byteorder.h>
+
+/**
+ * Initialize an instance of filesystem on the device.
+ * This function reads superblock from the device and
+ * initializes libblock cache with appropriate logical block size.
+ * 
+ * @param fs			Pointer to ext2_filesystem_t to initialize
+ * @param service_id	Service ID of the block device
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_init(ext2_filesystem_t *fs, service_id_t service_id)
+{
+	int rc;
+	ext2_superblock_t *temp_superblock;
+	size_t block_size;
+	
+	fs->device = service_id;
+	
+	rc = block_init(EXCHANGE_SERIALIZE, fs->device, 2048);
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	rc = ext2_superblock_read_direct(fs->device, &temp_superblock);
+	if (rc != EOK) {
+		block_fini(fs->device);
+		return rc;
+	}
+	
+	block_size = ext2_superblock_get_block_size(temp_superblock);
+	
+	if (block_size > EXT2_MAX_BLOCK_SIZE) {
+		block_fini(fs->device);
+		return ENOTSUP;
+	}
+	
+	rc = block_cache_init(service_id, block_size, 0, CACHE_MODE_WT);
+	if (rc != EOK) {
+		block_fini(fs->device);
+		return rc;
+	}
+	
+	fs->superblock = temp_superblock;
+	
+	return EOK; 
+}
+
+/**
+ * Check filesystem for sanity
+ * 
+ * @param fs			Pointer to ext2_filesystem_t to check
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_check_sanity(ext2_filesystem_t *fs)
+{
+	int rc;
+	
+	rc = ext2_superblock_check_sanity(fs->superblock);
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/**
+ * Check feature flags
+ * 
+ * @param fs Pointer to ext2_filesystem_t to check
+ * @param read_only bool to set to true if the fs needs to be read-only
+ * @return EOK on success or negative error code on failure
+ */
+int ext2_filesystem_check_flags(ext2_filesystem_t *fs, bool *o_read_only)
+{
+	/* feature flags are present in rev 1 and later */
+	if (ext2_superblock_get_rev_major(fs->superblock) == 0) {
+		*o_read_only = false;
+		return EOK;
+	}
+	
+	uint32_t incompatible;
+	uint32_t read_only;
+	
+	incompatible = ext2_superblock_get_features_incompatible(fs->superblock);
+	read_only = ext2_superblock_get_features_read_only(fs->superblock);
+	
+	/* check whether we support all features
+	 * first unset any supported feature flags
+	 * and see whether any unspported feature remains */
+	incompatible &= ~EXT2_SUPPORTED_INCOMPATIBLE_FEATURES;
+	read_only &= ~EXT2_SUPPORTED_READ_ONLY_FEATURES;
+	
+	if (incompatible > 0) {
+		*o_read_only = true;
+		return ENOTSUP;
+	}
+	
+	if (read_only > 0) {
+		*o_read_only = true;
+	}
+	
+	return EOK;
+}
+
+/**
+ * Get a reference to block descriptor
+ * 
+ * @param fs Pointer to filesystem information
+ * @param bgid Index of block group to find
+ * @param ref Pointer where to store pointer to block group reference
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_get_block_group_ref(ext2_filesystem_t *fs, uint32_t bgid,
+    ext2_block_group_ref_t **ref)
+{
+	int rc;
+	aoff64_t block_id;
+	uint32_t descriptors_per_block;
+	size_t offset;
+	ext2_block_group_ref_t *newref;
+	
+	newref = malloc(sizeof(ext2_block_group_ref_t));
+	if (newref == NULL) {
+		return ENOMEM;
+	}
+	
+	descriptors_per_block = ext2_superblock_get_block_size(fs->superblock)
+	    / EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE;
+	
+	/* Block group descriptor table starts at the next block after superblock */
+	block_id = ext2_superblock_get_first_block(fs->superblock) + 1;
+	
+	/* Find the block containing the descriptor we are looking for */
+	block_id += bgid / descriptors_per_block;
+	offset = (bgid % descriptors_per_block) * EXT2_BLOCK_GROUP_DESCRIPTOR_SIZE;
+	
+	rc = block_get(&newref->block, fs->device, block_id, 0);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+	
+	newref->block_group = newref->block->data + offset;
+	
+	*ref = newref;
+	
+	return EOK;
+}
+
+/**
+ * Free a reference to block group
+ * 
+ * @param ref Pointer to block group reference to free
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_put_block_group_ref(ext2_block_group_ref_t *ref)
+{
+	int rc;
+	
+	rc = block_put(ref->block);
+	free(ref);
+	
+	return rc;
+}
+
+/**
+ * Get a reference to inode
+ * 
+ * @param fs Pointer to filesystem information
+ * @param index The index number of the inode
+ * @param ref Pointer where to store pointer to inode reference
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_get_inode_ref(ext2_filesystem_t *fs, uint32_t index,
+    ext2_inode_ref_t **ref)
+{
+	int rc;
+	aoff64_t block_id;
+	uint32_t block_group;
+	uint32_t offset_in_group;
+	uint32_t byte_offset_in_group;
+	size_t offset_in_block;
+	uint32_t inodes_per_group;
+	uint32_t inode_table_start;
+	uint16_t inode_size;
+	uint32_t block_size;
+	ext2_block_group_ref_t *bg_ref;
+	ext2_inode_ref_t *newref;
+	
+	newref = malloc(sizeof(ext2_inode_ref_t));
+	if (newref == NULL) {
+		return ENOMEM;
+	}
+	
+	inodes_per_group = ext2_superblock_get_inodes_per_group(fs->superblock);
+	
+	/* inode numbers are 1-based, but it is simpler to work with 0-based
+	 * when computing indices
+	 */
+	index -= 1;
+	block_group = index / inodes_per_group;
+	offset_in_group = index % inodes_per_group;
+	
+	rc = ext2_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+	
+	inode_table_start = ext2_block_group_get_inode_table_first_block(
+	    bg_ref->block_group);
+	
+	inode_size = ext2_superblock_get_inode_size(fs->superblock);
+	block_size = ext2_superblock_get_block_size(fs->superblock);
+	
+	byte_offset_in_group = offset_in_group * inode_size;
+	
+	block_id = inode_table_start + (byte_offset_in_group / block_size);
+	offset_in_block = byte_offset_in_group % block_size;
+	
+	rc = block_get(&newref->block, fs->device, block_id, 0);
+	if (rc != EOK) {
+		free(newref);
+		return rc;
+	}
+	
+	newref->inode = newref->block->data + offset_in_block;
+	/* we decremented index above, but need to store the original value
+	 * in the reference
+	 */
+	newref->index = index+1;
+	
+	*ref = newref;
+	
+	return EOK;
+}
+
+/**
+ * Free a reference to inode
+ * 
+ * @param ref Pointer to inode reference to free
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_put_inode_ref(ext2_inode_ref_t *ref)
+{
+	int rc;
+	
+	rc = block_put(ref->block);
+	free(ref);
+	
+	return rc;
+}
+
+/**
+ * Find a filesystem block number where iblock-th data block
+ * of the given inode is located.
+ * 
+ * @param fblock the number of filesystem block, or 0 if no such block is allocated yet
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *fs, ext2_inode_t* inode,
+    aoff64_t iblock, uint32_t* fblock)
+{
+	int rc;
+	aoff64_t limits[4];
+	uint32_t block_ids_per_block;
+	aoff64_t blocks_per_level[4];
+	uint32_t offset_in_block;
+	uint32_t current_block;
+	aoff64_t block_offset_in_level;
+	int i;
+	int level;
+	block_t *block;
+	
+	/* Handle simple case when we are dealing with direct reference */ 
+	if (iblock < EXT2_INODE_DIRECT_BLOCKS) {
+		current_block = ext2_inode_get_direct_block(inode, (uint32_t)iblock);
+		*fblock = current_block;
+		return EOK;
+	}
+	
+	/* Compute limits for indirect block levels
+	 * TODO: compute this once when loading filesystem and store in ext2_filesystem_t
+	 */
+	block_ids_per_block = ext2_superblock_get_block_size(fs->superblock) / sizeof(uint32_t);
+	limits[0] = EXT2_INODE_DIRECT_BLOCKS;
+	blocks_per_level[0] = 1;
+	for (i = 1; i < 4; i++) {
+		blocks_per_level[i]  = blocks_per_level[i-1] *
+		    block_ids_per_block;
+		limits[i] = limits[i-1] + blocks_per_level[i];
+	}
+	
+	/* Determine the indirection level needed to get the desired block */
+	level = -1;
+	for (i = 1; i < 4; i++) {
+		if (iblock < limits[i]) {
+			level = i;
+			break;
+		}
+	}
+	
+	if (level == -1) {
+		return EIO;
+	}
+	
+	/* Compute offsets for the topmost level */
+	block_offset_in_level = iblock - limits[level-1];
+	current_block = ext2_inode_get_indirect_block(inode, level-1);
+	offset_in_block = block_offset_in_level / blocks_per_level[level-1];
+	
+	/* Navigate through other levels, until we find the block number
+	 * or find null reference meaning we are dealing with sparse file
+	 */
+	while (level > 0) {
+		rc = block_get(&block, fs->device, current_block, 0);
+		if (rc != EOK) {
+			return rc;
+		}
+		
+		assert(offset_in_block < block_ids_per_block);
+		current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]);
+		
+		rc = block_put(block);
+		if (rc != EOK) {
+			return rc;
+		}
+		
+		if (current_block == 0) {
+			/* This is a sparse file */
+			*fblock = 0;
+			return EOK;
+		}
+		
+		level -= 1;
+		
+		/* If we are on the last level, break here as
+		 * there is no next level to visit
+		 */
+		if (level == 0) {
+			break;
+		}
+		
+		/* Visit the next level */
+		block_offset_in_level %= blocks_per_level[level];
+		offset_in_block = block_offset_in_level / blocks_per_level[level-1];
+	}
+	
+	*fblock = current_block;
+	
+	return EOK;
+}
+
+/**
+ * Allocate a given number of blocks and store their ids in blocks
+ * 
+ * @todo TODO: This function is not finished and really has never been
+ *             used (and tested) yet
+ * 
+ * @param fs pointer to filesystem
+ * @param blocks array of count uint32_t values where store block ids
+ * @param count number of blocks to allocate and elements in blocks array
+ * @param preferred_bg preferred block group number
+ * 
+ * @return 		EOK on success or negative error code on failure
+ */
+int ext2_filesystem_allocate_blocks(ext2_filesystem_t *fs, uint32_t *blocks,
+    size_t count, uint32_t preferred_bg)
+{
+	uint32_t bg_count = ext2_superblock_get_block_group_count(fs->superblock);
+	uint32_t bpg = ext2_superblock_get_blocks_per_group(fs->superblock);
+	uint32_t block_size = ext2_superblock_get_block_size(fs->superblock);
+	uint32_t block_group = preferred_bg;
+	uint32_t free_blocks_sb;
+	uint32_t block_groups_left;
+	size_t idx;
+	ext2_block_group_ref_t *bg;
+	int rc;
+	uint32_t bb_block;
+	block_t *block;
+	size_t bb_idx;
+	size_t bb_bit;
+	
+	free_blocks_sb = ext2_superblock_get_free_block_count(fs->superblock);
+	
+	if (count > free_blocks_sb) {
+		return EIO;
+	}
+	
+	block_groups_left = bg_count;
+	
+	idx = 0;
+	
+	/* Read the block group descriptor */
+	rc = ext2_filesystem_get_block_group_ref(fs, block_group, &bg);
+	if (rc != EOK) {
+		goto failed;
+	}
+	
+	while (idx < count && block_groups_left > 0) {
+		uint16_t fb = ext2_block_group_get_free_block_count(bg->block_group);
+		if (fb == 0) {
+			block_group = (block_group + 1) % bg_count;
+			block_groups_left -= 1;
+			
+			rc = ext2_filesystem_put_block_group_ref(bg);
+			if (rc != EOK) {
+				goto failed;
+			}
+			
+			rc = ext2_filesystem_get_block_group_ref(fs, block_group, &bg);
+			if (rc != EOK) {
+				goto failed;
+			}
+			continue;
+		}
+		
+		/* We found a block group with free block, let's look at the block bitmap */
+		bb_block = ext2_block_group_get_block_bitmap_block(bg->block_group);
+		
+		rc = block_get(&block, fs->device, bb_block, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			goto failed;
+		}
+		
+		/* Use all blocks from this block group */
+		for (bb_idx = 0; bb_idx < block_size && idx < count; bb_idx++) {
+			uint8_t *data = (uint8_t *) block->data;
+			if (data[bb_idx] == 0xff) {
+				continue;
+			}
+			/* find an empty bit */
+			uint8_t mask;
+			for (mask = 1, bb_bit = 0;
+				 bb_bit < 8 && idx < count; 
+				 bb_bit++, mask = mask << 1) {
+				if ((data[bb_idx] & mask) == 0) {
+					// free block found
+					blocks[idx] = block_group * bpg + bb_idx*8 + bb_bit;
+					data[bb_idx] |= mask;
+					idx += 1;
+					fb -= 1;
+					ext2_block_group_set_free_block_count(bg->block_group, fb);
+				}
+			}
+		}
+	}
+	
+	rc = ext2_filesystem_put_block_group_ref(bg);
+	if (rc != EOK) {
+		goto failed;
+	}
+	
+	// TODO update superblock
+	
+	return EOK;
+failed:
+	// TODO deallocate already allocated blocks, if possible
+	
+	return rc;
+}
+
+/**
+ * Finalize an instance of filesystem
+ * 
+ * @param fs Pointer to ext2_filesystem_t to finalize
+ */
+void ext2_filesystem_fini(ext2_filesystem_t *fs)
+{
+	free(fs->superblock);
+	block_fini(fs->device);
+}
+
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_filesystem.h
===================================================================
--- uspace/lib/ext2/libext2_filesystem.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_filesystem.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBEXT2_LIBEXT2_FILESYSTEM_H_
+#define LIBEXT2_LIBEXT2_FILESYSTEM_H_
+
+#include <libblock.h>
+#include "libext2_superblock.h"
+#include "libext2_block_group.h"
+#include "libext2_inode.h"
+
+typedef struct ext2_filesystem {
+	service_id_t		device;
+	ext2_superblock_t *	superblock;
+} ext2_filesystem_t;
+
+// allow maximum this block size
+#define EXT2_MAX_BLOCK_SIZE			8096
+#define EXT2_REV0_FIRST_INODE		11
+#define EXT2_REV0_INODE_SIZE		128
+
+#define EXT2_FEATURE_RO_SPARSE_SUPERBLOCK	1
+#define EXT2_FEATURE_RO_LARGE_FILE			2
+#define EXT2_FEATURE_I_TYPE_IN_DIR			2
+
+#define EXT2_SUPPORTED_INCOMPATIBLE_FEATURES EXT2_FEATURE_I_TYPE_IN_DIR
+#define EXT2_SUPPORTED_READ_ONLY_FEATURES 0
+
+extern int ext2_filesystem_init(ext2_filesystem_t *, service_id_t);
+extern int ext2_filesystem_check_sanity(ext2_filesystem_t *);
+extern int ext2_filesystem_check_flags(ext2_filesystem_t *, bool *);
+extern int ext2_filesystem_get_block_group_ref(ext2_filesystem_t *, uint32_t, 
+    ext2_block_group_ref_t **);
+extern int ext2_filesystem_put_block_group_ref(ext2_block_group_ref_t *);
+extern int ext2_filesystem_get_inode_ref(ext2_filesystem_t *, uint32_t,
+    ext2_inode_ref_t **);
+extern int ext2_filesystem_put_inode_ref(ext2_inode_ref_t *);
+extern int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *, ext2_inode_t*,
+    aoff64_t, uint32_t*);
+extern int ext2_filesystem_allocate_blocks(ext2_filesystem_t *, uint32_t *, size_t, uint32_t);
+extern void ext2_filesystem_fini(ext2_filesystem_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_inode.c
===================================================================
--- uspace/lib/ext2/libext2_inode.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_inode.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "libext2.h"
+#include "libext2_inode.h"
+#include "libext2_superblock.h"
+#include <byteorder.h>
+#include <assert.h>
+
+/**
+ * Get mode stored in the inode
+ * 
+ * @param inode pointer to inode
+ */
+uint32_t ext2_inode_get_mode(ext2_superblock_t *sb, ext2_inode_t *inode)
+{
+	if (ext2_superblock_get_os(sb) == EXT2_SUPERBLOCK_OS_HURD) {
+		return ((uint32_t)uint16_t_le2host(inode->mode_high)) << 16 |
+		    ((uint32_t)uint16_t_le2host(inode->mode));
+	}
+	return uint16_t_le2host(inode->mode);
+}
+
+/**
+ * Check whether inode is of given type
+ * 
+ * @param sb pointer to superblock structure
+ * @param inode pointer to inode
+ * @param type EXT2_INODE_MODE_TYPE_* constant to check
+ */
+bool ext2_inode_is_type(ext2_superblock_t *sb, ext2_inode_t *inode, uint32_t type)
+{
+	uint32_t mode = ext2_inode_get_mode(sb, inode);
+	return (mode & EXT2_INODE_MODE_TYPE_MASK) == type;
+}
+
+/**
+ * Get uid this inode is belonging to
+ * 
+ * @param inode pointer to inode
+ */
+uint32_t ext2_inode_get_user_id(ext2_superblock_t *sb, ext2_inode_t *inode)
+{
+	uint32_t os = ext2_superblock_get_os(sb);
+	if (os == EXT2_SUPERBLOCK_OS_LINUX || os == EXT2_SUPERBLOCK_OS_HURD) {
+		return ((uint32_t)uint16_t_le2host(inode->user_id_high)) << 16 |
+		    ((uint32_t)uint16_t_le2host(inode->user_id));
+	}
+	return uint16_t_le2host(inode->user_id);
+}
+
+/**
+ * Get size of file
+ * 
+ * For regular files in revision 1 and later, the high 32 bits of
+ * file size are stored in inode->size_high and are 0 otherwise
+ * 
+ * @param inode pointer to inode
+ */
+uint64_t ext2_inode_get_size(ext2_superblock_t *sb, ext2_inode_t *inode)
+{
+	uint32_t major_rev = ext2_superblock_get_rev_major(sb);
+	
+	if (major_rev > 0 && ext2_inode_is_type(sb, inode, EXT2_INODE_MODE_FILE)) {
+		return ((uint64_t)uint32_t_le2host(inode->size_high)) << 32 |
+		    ((uint64_t)uint32_t_le2host(inode->size));
+	}
+	return uint32_t_le2host(inode->size);
+}
+
+/**
+ * Get gid this inode belongs to
+ * 
+ * For Linux and Hurd, the high 16 bits are stored in OS dependent part
+ * of inode structure
+ * 
+ * @param inode pointer to inode
+ */
+uint32_t ext2_inode_get_group_id(ext2_superblock_t *sb, ext2_inode_t *inode)
+{
+	uint32_t os = ext2_superblock_get_os(sb);
+	if (os == EXT2_SUPERBLOCK_OS_LINUX || os == EXT2_SUPERBLOCK_OS_HURD) {
+		return ((uint32_t)uint16_t_le2host(inode->group_id_high)) << 16 |
+		    ((uint32_t)uint16_t_le2host(inode->group_id));
+	}
+	return uint16_t_le2host(inode->group_id);
+}
+
+/**
+ * Get usage count (i.e. hard link count)
+ * A value of 1 is common, while 0 means that the inode should be freed
+ * 
+ * @param inode pointer to inode
+ */
+uint16_t ext2_inode_get_usage_count(ext2_inode_t *inode)
+{
+	return uint16_t_le2host(inode->usage_count);
+}
+
+/**
+ * Get number of 512-byte data blocks allocated for contents of the file
+ * represented by this inode.
+ * This should be multiple of block size unless fragments are used.
+ * 
+ * @param inode pointer to inode
+ */
+uint32_t ext2_inode_get_reserved_512_blocks(ext2_inode_t *inode)
+{
+	return uint32_t_le2host(inode->reserved_512_blocks);
+}
+
+/**
+ * Get number of blocks allocated for contents of the file
+ * represented by this inode.
+ * 
+ * @param inode pointer to inode
+ */
+uint32_t ext2_inode_get_reserved_blocks(ext2_superblock_t *sb,
+    ext2_inode_t *inode)
+{
+	return ext2_inode_get_reserved_512_blocks(inode) /
+	    (ext2_superblock_get_block_size(sb) / 512);
+}
+
+/**
+ * Get inode flags
+ * 
+ * @param inode pointer to inode
+ */
+uint32_t ext2_inode_get_flags(ext2_inode_t *inode) {
+	return uint32_t_le2host(inode->flags);
+}
+
+/**
+ * Get direct block ID
+ * 
+ * @param inode pointer to inode
+ * @param idx Index to block. Valid values are 0 <= idx < 12
+ */
+uint32_t ext2_inode_get_direct_block(ext2_inode_t *inode, uint8_t idx)
+{
+	assert(idx < EXT2_INODE_DIRECT_BLOCKS);
+	return uint32_t_le2host(inode->direct_blocks[idx]);
+}
+
+/**
+ * Get indirect block ID
+ * 
+ * @param inode pointer to inode
+ * @param idx Indirection level. Valid values are 0 <= idx < 3, where 0 is
+ *            singly-indirect block and 2 is triply-indirect-block
+ */
+uint32_t ext2_inode_get_indirect_block(ext2_inode_t *inode, uint8_t idx)
+{
+	assert(idx < 3);
+	return uint32_t_le2host(inode->indirect_blocks[idx]);
+}
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_inode.h
===================================================================
--- uspace/lib/ext2/libext2_inode.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_inode.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBEXT2_LIBEXT2_INODE_H_
+#define LIBEXT2_LIBEXT2_INODE_H_
+
+#include <libblock.h>
+#include "libext2_superblock.h"
+
+typedef struct ext2_inode {
+	uint16_t mode;
+	uint16_t user_id;
+	uint32_t size;
+	uint8_t unused[16];
+	uint16_t group_id;
+	uint16_t usage_count; // Hard link count, when 0 the inode is to be freed
+	uint32_t reserved_512_blocks; // Size of this inode in 512-byte blocks
+	uint32_t flags;
+	uint8_t unused2[4];
+	uint32_t direct_blocks[12]; // Direct block ids stored in this inode
+	uint32_t indirect_blocks[3];
+	uint32_t version;
+	uint32_t file_acl;
+	union {
+		uint32_t dir_acl;
+		uint32_t size_high; // For regular files in version >= 1
+	} __attribute__ ((packed));
+	uint8_t unused3[6];
+	uint16_t mode_high; // Hurd only
+	uint16_t user_id_high; // Linux/Hurd only
+	uint16_t group_id_high; // Linux/Hurd only
+} __attribute__ ((packed)) ext2_inode_t;
+
+#define EXT2_INODE_MODE_FIFO		0x1000
+#define EXT2_INODE_MODE_CHARDEV		0x2000
+#define EXT2_INODE_MODE_DIRECTORY	0x4000
+#define EXT2_INODE_MODE_BLOCKDEV	0x6000
+#define EXT2_INODE_MODE_FILE		0x8000
+#define EXT2_INODE_MODE_SOFTLINK	0xA000
+#define EXT2_INODE_MODE_SOCKET		0xC000
+#define EXT2_INODE_MODE_ACCESS_MASK	0x0FFF
+#define EXT2_INODE_MODE_TYPE_MASK	0xF000
+#define EXT2_INODE_DIRECT_BLOCKS	12
+
+#define EXT2_INODE_ROOT_INDEX		2
+
+typedef struct ext2_inode_ref {
+	block_t *block; // Reference to a block containing this inode
+	ext2_inode_t *inode;
+	uint32_t index; // Index number of this inode
+} ext2_inode_ref_t;
+
+extern uint32_t ext2_inode_get_mode(ext2_superblock_t *, ext2_inode_t *);
+extern bool ext2_inode_is_type(ext2_superblock_t *, ext2_inode_t *, uint32_t);
+extern uint32_t ext2_inode_get_user_id(ext2_superblock_t *, ext2_inode_t *);
+extern uint64_t ext2_inode_get_size(ext2_superblock_t *, ext2_inode_t *);
+extern uint32_t ext2_inode_get_group_id(ext2_superblock_t *, ext2_inode_t *);
+extern uint16_t ext2_inode_get_usage_count(ext2_inode_t *);
+extern uint32_t ext2_inode_get_reserved_512_blocks(ext2_inode_t *);
+extern uint32_t ext2_inode_get_reserved_blocks(ext2_superblock_t *, 
+    ext2_inode_t *);
+extern uint32_t ext2_inode_get_flags(ext2_inode_t *);
+extern uint32_t ext2_inode_get_direct_block(ext2_inode_t *, uint8_t);
+extern uint32_t ext2_inode_get_indirect_block(ext2_inode_t *, uint8_t level);
+
+
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_superblock.c
===================================================================
--- uspace/lib/ext2/libext2_superblock.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_superblock.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include "libext2.h"
+#include <errno.h>
+#include <malloc.h>
+#include <libblock.h>
+#include <byteorder.h>
+
+/**
+ * Return a magic number from ext2 superblock, this should be equal to
+ * EXT_SUPERBLOCK_MAGIC for valid ext2 superblock
+ * 
+ * @param sb pointer to superblock
+ */
+uint16_t ext2_superblock_get_magic(ext2_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->magic);
+}
+
+/**
+ * Get the position of first ext2 data block (i.e. the block number
+ * containing main superblock)
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_first_block(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->first_block);
+}
+
+/**
+ * Get the number of bits to shift a value of 1024 to the left necessary
+ * to get the size of a block
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_block_size_log2(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->block_size_log2);
+}
+
+/**
+ * Get the size of a block, in bytes 
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_block_size(ext2_superblock_t *sb)
+{
+	return 1024 << ext2_superblock_get_block_size_log2(sb);
+}
+
+/**
+ * Get the number of bits to shift a value of 1024 to the left necessary
+ * to get the size of a fragment (note that this is a signed integer and
+ * if negative, the value should be shifted to the right instead)
+ * 
+ * @param sb pointer to superblock
+ */
+int32_t ext2_superblock_get_fragment_size_log2(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->fragment_size_log2);
+}
+
+/**
+ * Get the size of a fragment, in bytes 
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_fragment_size(ext2_superblock_t *sb)
+{
+	int32_t log = ext2_superblock_get_fragment_size_log2(sb);
+	if (log >= 0) {
+		return 1024 << log;
+	}
+	else {
+		return 1024 >> -log;
+	}
+}
+
+/**
+ * Get number of blocks per block group
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_blocks_per_group(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->blocks_per_group);
+}
+
+/**
+ * Get number of fragments per block group
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_fragments_per_group(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->fragments_per_group);
+}
+
+/**
+ * Get filesystem state
+ * 
+ * @param sb pointer to superblock
+ */
+uint16_t ext2_superblock_get_state(ext2_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->state);
+}
+
+/**
+ * Get minor revision number
+ * 
+ * @param sb pointer to superblock
+ */
+uint16_t ext2_superblock_get_rev_minor(ext2_superblock_t *sb)
+{
+	return uint16_t_le2host(sb->rev_minor);
+}
+
+/**
+ * Get major revision number
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_rev_major(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->rev_major);
+}
+
+/**
+ * Get index of first regular inode
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_first_inode(ext2_superblock_t *sb)
+{
+	if (ext2_superblock_get_rev_major(sb) == 0) {
+		return EXT2_REV0_FIRST_INODE;
+	}
+	return uint32_t_le2host(sb->first_inode);
+}
+
+/**
+ * Get size of inode
+ * 
+ * @param sb pointer to superblock
+ */
+uint16_t ext2_superblock_get_inode_size(ext2_superblock_t *sb)
+{
+	if (ext2_superblock_get_rev_major(sb) == 0) {
+		return EXT2_REV0_INODE_SIZE;
+	}
+	return uint16_t_le2host(sb->inode_size);
+}
+
+/**
+ * Get total inode count
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_total_inode_count(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->total_inode_count);
+}
+
+/**
+ * Get total block count
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_total_block_count(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->total_block_count);
+}
+
+/**
+ * Get amount of blocks reserved for the superuser
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_reserved_block_count(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->reserved_block_count);
+}
+
+/**
+ * Get amount of free blocks
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_free_block_count(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->free_block_count);
+}
+
+/**
+ * Get amount of free inodes
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_free_inode_count(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->free_inode_count);
+}
+
+/**
+ * Get id of operating system that created the filesystem
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_os(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->os);
+}
+
+/**
+ * Get count of inodes per block group
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_inodes_per_group(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->inodes_per_group);
+}
+
+/**
+ * Get compatible features flags
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_features_compatible(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->features_compatible);
+}
+
+/**
+ * Get incompatible features flags
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_features_incompatible(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->features_incompatible);
+}
+
+/**
+ * Get read-only compatible features flags
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_features_read_only(ext2_superblock_t *sb)
+{
+	return uint32_t_le2host(sb->features_read_only);
+}
+
+/**
+ * Compute count of block groups present in the filesystem
+ * 
+ * Note: This function works only for correct filesystem,
+ *       i.e. it assumes that total block count > 0 and
+ *       blocks per group > 0
+ * 
+ * Example:
+ *   If there are 3 blocks per group, the result should be as follows:
+ *   Total blocks	Result
+ *   1				1
+ *   2				1
+ *   3				1
+ *   4				2
+ * 
+ * 
+ * @param sb pointer to superblock
+ */
+uint32_t ext2_superblock_get_block_group_count(ext2_superblock_t *sb)
+{
+	/* We add one to the result because e.g. 2/3 = 0, while to store
+	 *  2 blocks in 3-block group we need one (1) block group
+	 * 
+	 * We subtract one first because of special case that to store e.g.
+	 *  3 blocks in a 3-block group we need only one group
+	 *  (and 3/3 yields one - this is one more that we want as we
+	 *   already add one at the end)
+	 */ 
+	return ((ext2_superblock_get_total_block_count(sb)-1) / 
+	    ext2_superblock_get_blocks_per_group(sb))+1;
+}
+
+/** Read a superblock directly from device (i.e. no libblock cache)
+ * 
+ * @param service_id	Service ID of the block device.
+ * @param superblock	Pointer where to store pointer to new superblock
+ * 
+ * @return		EOK on success or negative error code on failure.
+ */
+int ext2_superblock_read_direct(service_id_t service_id,
+    ext2_superblock_t **superblock)
+{
+	void *data;
+	int rc;
+	
+	data = malloc(EXT2_SUPERBLOCK_SIZE);
+	if (data == NULL) {
+		return ENOMEM;
+	}
+	
+	rc = block_read_bytes_direct(service_id, EXT2_SUPERBLOCK_OFFSET,
+	    EXT2_SUPERBLOCK_SIZE, data);
+	if (rc != EOK) {
+		free(data);
+		return rc;
+	}
+	
+	(*superblock) = data;
+	return EOK;
+}
+
+/** Check a superblock for sanity
+ * 
+ * @param sb	Pointer to superblock
+ * 
+ * @return		EOK on success or negative error code on failure.
+ */
+int ext2_superblock_check_sanity(ext2_superblock_t *sb)
+{
+	if (ext2_superblock_get_magic(sb) != EXT2_SUPERBLOCK_MAGIC) {
+		return ENOTSUP;
+	}
+	
+	if (ext2_superblock_get_rev_major(sb) > 1) {
+		return ENOTSUP;
+	}
+	
+	if (ext2_superblock_get_total_inode_count(sb) == 0) {
+		return ENOTSUP;
+	}
+	
+	if (ext2_superblock_get_total_block_count(sb) == 0) {
+		return ENOTSUP;
+	}
+	
+	if (ext2_superblock_get_blocks_per_group(sb) == 0) {
+		return ENOTSUP;
+	}
+	
+	if (ext2_superblock_get_fragments_per_group(sb) == 0) {
+		return ENOTSUP;
+	}
+	
+	/* We don't support fragments smaller than block */
+	if (ext2_superblock_get_block_size(sb) != 
+		    ext2_superblock_get_fragment_size(sb)) {
+		return ENOTSUP;
+	}
+	if (ext2_superblock_get_blocks_per_group(sb) !=
+		    ext2_superblock_get_fragments_per_group(sb)) {
+		return ENOTSUP;
+	}
+	
+	if (ext2_superblock_get_inodes_per_group(sb) == 0) {
+		return ENOTSUP;
+	}
+	
+	if (ext2_superblock_get_inode_size(sb) < 128) {
+		return ENOTSUP;
+	}
+	
+	if (ext2_superblock_get_first_inode(sb) < 11) {
+		return ENOTSUP;
+	}
+	
+	return EOK;
+}
+
+
+/** @}
+ */
Index: uspace/lib/ext2/libext2_superblock.h
===================================================================
--- uspace/lib/ext2/libext2_superblock.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/ext2/libext2_superblock.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 libext2
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef LIBEXT2_LIBEXT2_SUPERBLOCK_H_
+#define LIBEXT2_LIBEXT2_SUPERBLOCK_H_
+
+#include <libblock.h>
+
+typedef struct ext2_superblock {
+	uint32_t	total_inode_count; // Total number of inodes
+	uint32_t	total_block_count; // Total number of blocks
+	uint32_t	reserved_block_count; // Total number of reserved blocks
+	uint32_t	free_block_count; // Total number of free blocks
+	uint32_t	free_inode_count; // Total number of free inodes
+	uint32_t	first_block; // Block containing the superblock (either 0 or 1)
+	uint32_t	block_size_log2; // log_2(block_size)
+	int32_t		fragment_size_log2; // log_2(fragment size)
+	uint32_t	blocks_per_group; // Number of blocks in one block group
+	uint32_t	fragments_per_group; // Number of fragments per block group
+	uint32_t	inodes_per_group; // Number of inodes per block group
+	uint8_t		unused2[12];
+	uint16_t	magic; // Magic value
+	uint16_t	state; // State (mounted/unmounted)
+	uint16_t	error_behavior; // What to do when errors are encountered
+	uint16_t	rev_minor; // Minor revision level
+	uint8_t		unused3[8];
+	uint32_t	os; // OS that created the filesystem
+	uint32_t	rev_major; // Major revision level
+	uint8_t		unused4[4];
+	
+	// Following is for ext2 revision 1 only
+	uint32_t	first_inode;
+	uint16_t	inode_size;
+	uint16_t	unused5;
+	uint32_t	features_compatible;
+	uint32_t	features_incompatible;
+	uint32_t	features_read_only;
+	uint8_t		uuid[16]; // UUID TODO: Create a library for UUIDs
+	uint8_t		volume_name[16];
+
+// TODO: add __attribute__((aligned(...)) for better performance?
+//       (it is necessary to ensure the superblock is correctly aligned then
+//        though)
+} __attribute__ ((packed)) ext2_superblock_t;
+
+#define EXT2_SUPERBLOCK_MAGIC		0xEF53
+#define EXT2_SUPERBLOCK_SIZE		1024
+#define EXT2_SUPERBLOCK_OFFSET		1024
+#define EXT2_SUPERBLOCK_LAST_BYTE	(EXT2_SUPERBLOCK_OFFSET + \
+									 EXT2_SUPERBLOCK_SIZE -1)
+#define EXT2_SUPERBLOCK_OS_LINUX	0
+#define EXT2_SUPERBLOCK_OS_HURD		1
+
+
+extern uint16_t	ext2_superblock_get_magic(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_first_block(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_block_size_log2(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_block_size(ext2_superblock_t *);
+extern int32_t	ext2_superblock_get_fragment_size_log2(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_fragment_size(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_blocks_per_group(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_fragments_per_group(ext2_superblock_t *);
+extern uint16_t	ext2_superblock_get_state(ext2_superblock_t *);
+extern uint16_t	ext2_superblock_get_rev_minor(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_rev_major(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_os(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_first_inode(ext2_superblock_t *);
+extern uint16_t	ext2_superblock_get_inode_size(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_total_inode_count(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_total_block_count(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_reserved_block_count(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_free_block_count(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_free_inode_count(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_block_group_count(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_inodes_per_group(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_features_compatible(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_features_incompatible(ext2_superblock_t *);
+extern uint32_t	ext2_superblock_get_features_read_only(ext2_superblock_t *);
+
+extern int ext2_superblock_read_direct(service_id_t, ext2_superblock_t **);
+extern int ext2_superblock_check_sanity(ext2_superblock_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/fs/libfs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,4 +45,5 @@
 #include <mem.h>
 #include <sys/stat.h>
+#include <stdlib.h>
 
 #define on_error(rc, action) \
@@ -61,4 +62,226 @@
 	} while (0)
 
+static fs_reg_t reg;
+
+static vfs_out_ops_t *vfs_out_ops = NULL;
+static libfs_ops_t *libfs_ops = NULL;
+
+static void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
+static void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
+static void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t,
+    ipc_call_t *);
+static void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
+static void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
+    ipc_call_t *);
+
+static void vfs_out_mounted(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	char *opts;
+	int rc;
+	
+	/* Accept the mount options. */
+	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(rid, rc);
+		return;
+	}
+
+	fs_index_t index;
+	aoff64_t size;
+	unsigned lnkcnt;
+	rc = vfs_out_ops->mounted(service_id, opts, &index, &size, &lnkcnt);
+
+	if (rc == EOK)
+		async_answer_4(rid, EOK, index, LOWER32(size), UPPER32(size),
+		    lnkcnt);
+	else
+		async_answer_0(rid, rc);
+
+	free(opts);
+}
+
+static void vfs_out_mount(ipc_callid_t rid, ipc_call_t *req)
+{
+	libfs_mount(libfs_ops, reg.fs_handle, rid, req);
+}
+
+static void vfs_out_unmounted(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	int rc; 
+
+	rc = vfs_out_ops->unmounted(service_id);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_out_unmount(ipc_callid_t rid, ipc_call_t *req)
+{
+		
+	libfs_unmount(libfs_ops, rid, req);
+}
+
+static void vfs_out_lookup(ipc_callid_t rid, ipc_call_t *req)
+{
+	libfs_lookup(libfs_ops, reg.fs_handle, rid, req);
+}
+
+static void vfs_out_read(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
+	    IPC_GET_ARG4(*req));
+	size_t rbytes;
+	int rc;
+
+	rc = vfs_out_ops->read(service_id, index, pos, &rbytes);
+
+	if (rc == EOK)
+		async_answer_1(rid, EOK, rbytes);
+	else
+		async_answer_0(rid, rc);
+}
+
+static void vfs_out_write(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
+	    IPC_GET_ARG4(*req));
+	size_t wbytes;
+	aoff64_t nsize;
+	int rc;
+
+	rc = vfs_out_ops->write(service_id, index, pos, &wbytes, &nsize);
+
+	if (rc == EOK)
+		async_answer_3(rid, EOK, wbytes, LOWER32(nsize), UPPER32(nsize));
+	else
+		async_answer_0(rid, rc);
+}
+
+static void vfs_out_truncate(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*req),
+	    IPC_GET_ARG4(*req));
+	int rc;
+
+	rc = vfs_out_ops->truncate(service_id, index, size);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_out_close(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	int rc;
+
+	rc = vfs_out_ops->close(service_id, index);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_out_destroy(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	int rc;
+
+	rc = vfs_out_ops->destroy(service_id, index);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_out_open_node(ipc_callid_t rid, ipc_call_t *req)
+{
+	libfs_open_node(libfs_ops, reg.fs_handle, rid, req);
+}
+
+static void vfs_out_stat(ipc_callid_t rid, ipc_call_t *req)
+{
+	libfs_stat(libfs_ops, reg.fs_handle, rid, req);
+}
+
+static void vfs_out_sync(ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*req);
+	int rc;
+
+	rc = vfs_out_ops->sync(service_id, index);
+
+	async_answer_0(rid, rc);
+}
+
+static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	if (iid) {
+		/*
+		 * This only happens for connections opened by
+		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
+		 * created by IPC_M_CONNECT_TO_ME.
+		 */
+		async_answer_0(iid, EOK);
+	}
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			return;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case VFS_OUT_MOUNTED:
+			vfs_out_mounted(callid, &call);
+			break;
+		case VFS_OUT_MOUNT:
+			vfs_out_mount(callid, &call);
+			break;
+		case VFS_OUT_UNMOUNTED:
+			vfs_out_unmounted(callid, &call);
+			break;
+		case VFS_OUT_UNMOUNT:
+			vfs_out_unmount(callid, &call);
+			break;
+		case VFS_OUT_LOOKUP:
+			vfs_out_lookup(callid, &call);
+			break;
+		case VFS_OUT_READ:
+			vfs_out_read(callid, &call);
+			break;
+		case VFS_OUT_WRITE:
+			vfs_out_write(callid, &call);
+			break;
+		case VFS_OUT_TRUNCATE:
+			vfs_out_truncate(callid, &call);
+			break;
+		case VFS_OUT_CLOSE:
+			vfs_out_close(callid, &call);
+			break;
+		case VFS_OUT_DESTROY:
+			vfs_out_destroy(callid, &call);
+			break;
+		case VFS_OUT_OPEN_NODE:
+			vfs_out_open_node(callid, &call);
+			break;
+		case VFS_OUT_STAT:
+			vfs_out_stat(callid, &call);
+			break;
+		case VFS_OUT_SYNC:
+			vfs_out_sync(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+}
+
 /** Register file system server.
  *
@@ -67,17 +290,15 @@
  * code.
  *
- * @param vfs_phone Open phone for communication with VFS.
- * @param reg       File system registration structure. It will be
- *                  initialized by this function.
- * @param info      VFS info structure supplied by the file system
- *                  implementation.
- * @param conn      Connection fibril for handling all calls originating in
- *                  VFS.
+ * @param sess Session for communication with VFS.
+ * @param info VFS info structure supplied by the file system
+ *             implementation.
+ * @param vops Address of the vfs_out_ops_t structure.
+ * @param lops Address of the libfs_ops_t structure.
  *
  * @return EOK on success or a non-zero error code on errror.
  *
  */
-int fs_register(int vfs_phone, fs_reg_t *reg, vfs_info_t *info,
-    async_client_conn_t conn)
+int fs_register(async_sess_t *sess, vfs_info_t *info, vfs_out_ops_t *vops,
+    libfs_ops_t *lops)
 {
 	/*
@@ -86,12 +307,17 @@
 	 * out-of-order, when it knows that the operation succeeded or failed.
 	 */
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
 	ipc_call_t answer;
-	aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer);
+	aid_t req = async_send_0(exch, VFS_IN_REGISTER, &answer);
 	
 	/*
 	 * Send our VFS info structure to VFS.
 	 */
-	int rc = async_data_write_start(vfs_phone, info, sizeof(*info)); 
+	int rc = async_data_write_start(exch, info, sizeof(*info));
+	
 	if (rc != EOK) {
+		async_exchange_end(exch);
 		async_wait_for(req, NULL);
 		return rc;
@@ -99,13 +325,20 @@
 	
 	/*
+	 * Set VFS_OUT and libfs operations.
+	 */
+	vfs_out_ops = vops;
+	libfs_ops = lops;
+
+	/*
 	 * Ask VFS for callback connection.
 	 */
-	async_connect_to_me(vfs_phone, 0, 0, 0, conn);
+	async_connect_to_me(exch, 0, 0, 0, vfs_connection, NULL);
 	
 	/*
 	 * Allocate piece of address space for PLB.
 	 */
-	reg->plb_ro = as_get_mappable_page(PLB_SIZE);
-	if (!reg->plb_ro) {
+	reg.plb_ro = as_get_mappable_page(PLB_SIZE);
+	if (!reg.plb_ro) {
+		async_exchange_end(exch);
 		async_wait_for(req, NULL);
 		return ENOMEM;
@@ -115,5 +348,8 @@
 	 * Request sharing the Path Lookup Buffer with VFS.
 	 */
-	rc = async_share_in_start_0_0(vfs_phone, reg->plb_ro, PLB_SIZE);
+	rc = async_share_in_start_0_0(exch, reg.plb_ro, PLB_SIZE);
+	
+	async_exchange_end(exch);
+	
 	if (rc) {
 		async_wait_for(req, NULL);
@@ -125,5 +361,5 @@
 	 */
 	async_wait_for(req, NULL);
-	reg->fs_handle = (int) IPC_GET_ARG1(answer);
+	reg.fs_handle = (int) IPC_GET_ARG1(answer);
 	
 	/*
@@ -131,5 +367,5 @@
 	 * the same connection fibril as well.
 	 */
-	async_set_client_connection(conn);
+	async_set_client_connection(vfs_connection);
 	
 	return IPC_GET_RETVAL(answer);
@@ -142,33 +378,21 @@
 
 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
-    ipc_call_t *request)
-{
-	devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
-	fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
-	devmap_handle_t mr_devmap_handle = (devmap_handle_t) IPC_GET_ARG4(*request);
-	int res;
-	sysarg_t rc;
-	
-	ipc_call_t call;
-	ipc_callid_t callid;
-	
-	/* Accept the phone */
-	callid = async_get_call(&call);
-	int mountee_phone = (int) IPC_GET_ARG1(call);
-	if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) ||
-	    (mountee_phone < 0)) {
-		async_answer_0(callid, EINVAL);
+    ipc_call_t *req)
+{
+	service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
+	fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*req);
+	service_id_t mr_service_id = (service_id_t) IPC_GET_ARG4(*req);
+	
+	async_sess_t *mountee_sess = async_clone_receive(EXCHANGE_PARALLEL);
+	if (mountee_sess == NULL) {
 		async_answer_0(rid, EINVAL);
 		return;
 	}
 	
-	/* Acknowledge the mountee_phone */
-	async_answer_0(callid, EOK);
-	
 	fs_node_t *fn;
-	res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
+	int res = ops->node_get(&fn, mp_service_id, mp_fs_index);
 	if ((res != EOK) || (!fn)) {
-		async_hangup(mountee_phone);
+		async_hangup(mountee_sess);
 		async_data_write_void(combine_rc(res, ENOENT));
 		async_answer_0(rid, combine_rc(res, ENOENT));
@@ -177,5 +401,5 @@
 	
 	if (fn->mp_data.mp_active) {
-		async_hangup(mountee_phone);
+		async_hangup(mountee_sess);
 		(void) ops->node_put(fn);
 		async_data_write_void(EBUSY);
@@ -184,22 +408,26 @@
 	}
 	
-	rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME);
-	if (rc != EOK) {
-		async_hangup(mountee_phone);
+	async_exch_t *exch = async_exchange_begin(mountee_sess);
+	async_sess_t *sess = async_connect_me(EXCHANGE_PARALLEL, exch);
+	
+	if (!sess) {
+		async_exchange_end(exch);
+		async_hangup(mountee_sess);
 		(void) ops->node_put(fn);
-		async_data_write_void(rc);
-		async_answer_0(rid, rc);
+		async_data_write_void(errno);
+		async_answer_0(rid, errno);
 		return;
 	}
 	
 	ipc_call_t answer;
-	rc = async_data_write_forward_1_1(mountee_phone, VFS_OUT_MOUNTED,
-	    mr_devmap_handle, &answer);
+	int rc = async_data_write_forward_1_1(exch, VFS_OUT_MOUNTED,
+	    mr_service_id, &answer);
+	async_exchange_end(exch);
 	
 	if (rc == EOK) {
 		fn->mp_data.mp_active = true;
 		fn->mp_data.fs_handle = mr_fs_handle;
-		fn->mp_data.devmap_handle = mr_devmap_handle;
-		fn->mp_data.phone = mountee_phone;
+		fn->mp_data.service_id = mr_service_id;
+		fn->mp_data.sess = mountee_sess;
 	}
 	
@@ -207,16 +435,16 @@
 	 * Do not release the FS node so that it stays in memory.
 	 */
-	async_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
-	    IPC_GET_ARG3(answer));
-}
-
-void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t mp_devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request);
+	async_answer_4(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
+	    IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
+}
+
+void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *req)
+{
+	service_id_t mp_service_id = (service_id_t) IPC_GET_ARG1(*req);
+	fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*req);
 	fs_node_t *fn;
 	int res;
 
-	res = ops->node_get(&fn, mp_devmap_handle, mp_fs_index);
+	res = ops->node_get(&fn, mp_service_id, mp_fs_index);
 	if ((res != EOK) || (!fn)) {
 		async_answer_0(rid, combine_rc(res, ENOENT));
@@ -236,6 +464,7 @@
 	 * Tell the mounted file system to unmount.
 	 */
-	res = async_req_1_0(fn->mp_data.phone, VFS_OUT_UNMOUNTED,
-	    fn->mp_data.devmap_handle);
+	async_exch_t *exch = async_exchange_begin(fn->mp_data.sess);
+	res = async_req_1_0(exch, VFS_OUT_UNMOUNTED, fn->mp_data.service_id);
+	async_exchange_end(exch);
 
 	/*
@@ -243,9 +472,10 @@
 	 */
 	if (res == EOK) {
-		async_hangup(fn->mp_data.phone);
+		async_hangup(fn->mp_data.sess);
 		fn->mp_data.mp_active = false;
 		fn->mp_data.fs_handle = 0;
-		fn->mp_data.devmap_handle = 0;
-		fn->mp_data.phone = 0;
+		fn->mp_data.service_id = 0;
+		fn->mp_data.sess = NULL;
+		
 		/* Drop the reference created in libfs_mount(). */
 		(void) ops->node_put(fn);
@@ -254,4 +484,9 @@
 	(void) ops->node_put(fn);
 	async_answer_0(rid, res);
+}
+
+static char plb_get_char(unsigned pos)
+{
+	return reg.plb_ro[pos % PLB_SIZE];
 }
 
@@ -270,12 +505,12 @@
  */
 void libfs_lookup(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
-    ipc_call_t *request)
-{
-	unsigned int first = IPC_GET_ARG1(*request);
-	unsigned int last = IPC_GET_ARG2(*request);
+    ipc_call_t *req)
+{
+	unsigned int first = IPC_GET_ARG1(*req);
+	unsigned int last = IPC_GET_ARG2(*req);
 	unsigned int next = first;
-	devmap_handle_t devmap_handle = IPC_GET_ARG3(*request);
-	int lflag = IPC_GET_ARG4(*request);
-	fs_index_t index = IPC_GET_ARG5(*request);
+	service_id_t service_id = IPC_GET_ARG3(*req);
+	int lflag = IPC_GET_ARG4(*req);
+	fs_index_t index = IPC_GET_ARG5(*req);
 	char component[NAME_MAX + 1];
 	int len;
@@ -289,11 +524,14 @@
 	fs_node_t *tmp = NULL;
 	
-	rc = ops->root_get(&cur, devmap_handle);
+	rc = ops->root_get(&cur, service_id);
 	on_error(rc, goto out_with_answer);
 	
 	if (cur->mp_data.mp_active) {
-		async_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP,
-		    next, last, cur->mp_data.devmap_handle, lflag, index,
+		async_exch_t *exch = async_exchange_begin(cur->mp_data.sess);
+		async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next, last,
+		    cur->mp_data.service_id, lflag, index,
 		    IPC_FF_ROUTE_FROM_ME);
+		async_exchange_end(exch);
+		
 		(void) ops->node_put(cur);
 		return;
@@ -301,5 +539,5 @@
 	
 	/* Eat slash */
-	if (ops->plb_get_char(next) == '/')
+	if (plb_get_char(next) == '/')
 		next++;
 	
@@ -314,5 +552,5 @@
 		/* Collect the component */
 		len = 0;
-		while ((next <= last) && (ops->plb_get_char(next) != '/')) {
+		while ((next <= last) && (plb_get_char(next) != '/')) {
 			if (len + 1 == NAME_MAX) {
 				/* Component length overflow */
@@ -320,5 +558,5 @@
 				goto out;
 			}
-			component[len++] = ops->plb_get_char(next);
+			component[len++] = plb_get_char(next);
 			/* Process next character */
 			next++;
@@ -351,7 +589,10 @@
 				next--;
 			
-			async_forward_slow(rid, tmp->mp_data.phone,
-			    VFS_OUT_LOOKUP, next, last, tmp->mp_data.devmap_handle,
-			    lflag, index, IPC_FF_ROUTE_FROM_ME);
+			async_exch_t *exch = async_exchange_begin(tmp->mp_data.sess);
+			async_forward_slow(rid, exch, VFS_OUT_LOOKUP, next,
+			    last, tmp->mp_data.service_id, lflag, index,
+			    IPC_FF_ROUTE_FROM_ME);
+			async_exchange_end(exch);
+			
 			(void) ops->node_put(cur);
 			(void) ops->node_put(tmp);
@@ -379,8 +620,8 @@
 				fs_node_t *fn;
 				if (lflag & L_CREATE)
-					rc = ops->create(&fn, devmap_handle,
+					rc = ops->create(&fn, service_id,
 					    lflag);
 				else
-					rc = ops->node_get(&fn, devmap_handle,
+					rc = ops->node_get(&fn, service_id,
 					    index);
 				on_error(rc, goto out_with_answer);
@@ -391,9 +632,11 @@
 						if (lflag & L_CREATE)
 							(void) ops->destroy(fn);
+						else
+							(void) ops->node_put(fn);
 						async_answer_0(rid, rc);
 					} else {
 						aoff64_t size = ops->size_get(fn);
 						async_answer_5(rid, fs_handle,
-						    devmap_handle,
+						    service_id,
 						    ops->index_get(fn),
 						    LOWER32(size),
@@ -441,5 +684,5 @@
 			len = 0;
 			while (next <= last) {
-				if (ops->plb_get_char(next) == '/') {
+				if (plb_get_char(next) == '/') {
 					/* More than one component */
 					async_answer_0(rid, ENOENT);
@@ -453,5 +696,5 @@
 				}
 				
-				component[len++] = ops->plb_get_char(next);
+				component[len++] = plb_get_char(next);
 				/* Process next character */
 				next++;
@@ -463,7 +706,7 @@
 			fs_node_t *fn;
 			if (lflag & L_CREATE)
-				rc = ops->create(&fn, devmap_handle, lflag);
+				rc = ops->create(&fn, service_id, lflag);
 			else
-				rc = ops->node_get(&fn, devmap_handle, index);
+				rc = ops->node_get(&fn, service_id, index);
 			on_error(rc, goto out_with_answer);
 			
@@ -473,9 +716,11 @@
 					if (lflag & L_CREATE)
 						(void) ops->destroy(fn);
+					else
+						(void) ops->node_put(fn);
 					async_answer_0(rid, rc);
 				} else {
 					aoff64_t size = ops->size_get(fn);
 					async_answer_5(rid, fs_handle,
-					    devmap_handle,
+					    service_id,
 					    ops->index_get(fn),
 					    LOWER32(size),
@@ -503,5 +748,5 @@
 		if (rc == EOK) {
 			aoff64_t size = ops->size_get(cur);
-			async_answer_5(rid, fs_handle, devmap_handle,
+			async_answer_5(rid, fs_handle, service_id,
 			    ops->index_get(cur), LOWER32(size), UPPER32(size),
 			    old_lnkcnt);
@@ -541,5 +786,5 @@
 		if (rc == EOK) {
 			aoff64_t size = ops->size_get(cur);
-			async_answer_5(rid, fs_handle, devmap_handle,
+			async_answer_5(rid, fs_handle, service_id,
 			    ops->index_get(cur), LOWER32(size), UPPER32(size),
 			    ops->lnkcnt_get(cur));
@@ -565,9 +810,9 @@
     ipc_call_t *request)
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
 	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
 	
 	fs_node_t *fn;
-	int rc = ops->node_get(&fn, devmap_handle, index);
+	int rc = ops->node_get(&fn, service_id, index);
 	on_error(rc, answer_and_return(rid, rc));
 	
@@ -586,5 +831,5 @@
 	
 	stat.fs_handle = fs_handle;
-	stat.devmap_handle = devmap_handle;
+	stat.service_id = service_id;
 	stat.index = index;
 	stat.lnkcnt = ops->lnkcnt_get(fn);
@@ -592,5 +837,5 @@
 	stat.is_directory = ops->is_directory(fn);
 	stat.size = ops->size_get(fn);
-	stat.device = ops->device_get(fn);
+	stat.service = ops->device_get(fn);
 	
 	ops->node_put(fn);
@@ -611,9 +856,9 @@
     ipc_call_t *request)
 {
-	devmap_handle_t devmap_handle = IPC_GET_ARG1(*request);
+	service_id_t service_id = IPC_GET_ARG1(*request);
 	fs_index_t index = IPC_GET_ARG2(*request);
 	
 	fs_node_t *fn;
-	int rc = ops->node_get(&fn, devmap_handle, index);
+	int rc = ops->node_get(&fn, service_id, index);
 	on_error(rc, answer_and_return(rid, rc));
 	
@@ -625,5 +870,6 @@
 	rc = ops->node_open(fn);
 	aoff64_t size = ops->size_get(fn);
-	async_answer_4(rid, rc, LOWER32(size), UPPER32(size), ops->lnkcnt_get(fn),
+	async_answer_4(rid, rc, LOWER32(size), UPPER32(size),
+	    ops->lnkcnt_get(fn),
 	    (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0));
 	
Index: uspace/lib/fs/libfs.h
===================================================================
--- uspace/lib/fs/libfs.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/fs/libfs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,11 +40,24 @@
 #include <stdint.h>
 #include <async.h>
-#include <devmap.h>
+#include <loc.h>
+
+typedef struct {
+	int (* mounted)(service_id_t, const char *, fs_index_t *, aoff64_t *,
+	    unsigned *);
+	int (* unmounted)(service_id_t);
+	int (* read)(service_id_t, fs_index_t, aoff64_t, size_t *);
+	int (* write)(service_id_t, fs_index_t, aoff64_t, size_t *,
+	    aoff64_t *);
+	int (* truncate)(service_id_t, fs_index_t, aoff64_t);
+	int (* close)(service_id_t, fs_index_t);
+	int (* destroy)(service_id_t, fs_index_t);
+	int (* sync)(service_id_t, fs_index_t);
+} vfs_out_ops_t;
 
 typedef struct {
 	bool mp_active;
-	int phone;
+	async_sess_t *sess;
 	fs_handle_t fs_handle;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 } mp_data_t;
 
@@ -60,10 +73,10 @@
 	 * argument holds the output argument.
 	 */
-	int (* root_get)(fs_node_t **, devmap_handle_t);
+	int (* root_get)(fs_node_t **, service_id_t);
 	int (* match)(fs_node_t **, fs_node_t *, const char *);
-	int (* node_get)(fs_node_t **, devmap_handle_t, fs_index_t);
+	int (* node_get)(fs_node_t **, service_id_t, fs_index_t);
 	int (* node_open)(fs_node_t *);
 	int (* node_put)(fs_node_t *);
-	int (* create)(fs_node_t **, devmap_handle_t, int);
+	int (* create)(fs_node_t **, service_id_t, int);
 	int (* destroy)(fs_node_t *);
 	int (* link)(fs_node_t *, fs_node_t *, const char *);
@@ -71,14 +84,13 @@
 	int (* has_children)(bool *, fs_node_t *);
 	/*
-	 * The second set of methods are usually mere getters that do not return
-	 * an integer error code.
+	 * The second set of methods are usually mere getters that do not
+	 * return an integer error code.
 	 */
 	fs_index_t (* index_get)(fs_node_t *);
 	aoff64_t (* size_get)(fs_node_t *);
 	unsigned int (* lnkcnt_get)(fs_node_t *);
-	char (* plb_get_char)(unsigned pos);
 	bool (* is_directory)(fs_node_t *);
 	bool (* is_file)(fs_node_t *);
-	devmap_handle_t (* device_get)(fs_node_t *);
+	service_id_t (* device_get)(fs_node_t *);
 } libfs_ops_t;
 
@@ -88,14 +100,8 @@
 } fs_reg_t;
 
-extern int fs_register(int, fs_reg_t *, vfs_info_t *, async_client_conn_t);
+extern int fs_register(async_sess_t *, vfs_info_t *, vfs_out_ops_t *,
+    libfs_ops_t *);
 
 extern void fs_node_initialize(fs_node_t *);
-
-extern void libfs_mount(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
-extern void libfs_unmount(libfs_ops_t *, ipc_callid_t, ipc_call_t *);
-extern void libfs_lookup(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
-extern void libfs_stat(libfs_ops_t *, fs_handle_t, ipc_callid_t, ipc_call_t *);
-extern void libfs_open_node(libfs_ops_t *, fs_handle_t, ipc_callid_t,
-    ipc_call_t *);
 
 #endif
Index: uspace/lib/imgmap/Makefile
===================================================================
--- uspace/lib/imgmap/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/imgmap/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+LIBRARY = libimgmap
+
+SOURCES = \
+	imgmap.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/imgmap/imgmap.c
===================================================================
--- uspace/lib/imgmap/imgmap.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/imgmap/imgmap.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup imgmap
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <stdlib.h>
+#include <byteorder.h>
+#include <align.h>
+#include <bool.h>
+#include <mem.h>
+#include "imgmap.h"
+
+typedef struct {
+	uint8_t id_length;
+	uint8_t cmap_type;
+	uint8_t img_type;
+	
+	uint16_t cmap_first_entry;
+	uint16_t cmap_entries;
+	uint8_t cmap_bpp;
+	
+	uint16_t startx;
+	uint16_t starty;
+	uint16_t width;
+	uint16_t height;
+	uint8_t img_bpp;
+	uint8_t img_descr;
+} __attribute__((packed)) tga_header_t;
+
+typedef enum {
+	CMAP_NOT_PRESENT = 0,
+	CMAP_PRESENT = 1,
+	CMAP_RESERVED_START = 2,
+	CMAP_PRIVATE_START = 128
+} cmap_type_t;
+
+typedef enum {
+	IMG_EMTPY = 0,
+	IMG_CMAP = 1,
+	IMG_BGRA = 2,
+	IMG_GRAY = 3,
+	IMG_CMAP_RLE = 9,
+	IMG_BGRA_RLE = 10,
+	IMG_GRAY_RLE = 11
+} img_type_t;
+
+typedef struct {
+	cmap_type_t cmap_type;
+	img_type_t img_type;
+	
+	uint16_t cmap_first_entry;
+	uint16_t cmap_entries;
+	uint8_t cmap_bpp;
+	
+	uint16_t startx;
+	uint16_t starty;
+	uint16_t width;
+	uint16_t height;
+	uint8_t img_bpp;
+	uint8_t img_alpha_bpp;
+	uint8_t img_alpha_dir;
+	
+	void *id_data;
+	size_t id_length;
+	
+	void *cmap_data;
+	size_t cmap_length;
+	
+	void *img_data;
+	size_t img_length;
+} tga_t;
+
+/** Decode Truevision TGA header
+ *
+ * @param[in]  data Memory representation of TGA.
+ * @param[in]  size Size of the representation (in bytes).
+ * @param[out] tga  Decoded TGA.
+ *
+ * @return True on succesful decoding.
+ * @return False on failure.
+ *
+ */
+static bool decode_tga_header(void *data, size_t size, tga_t *tga)
+{
+	/* Header sanity check */
+	if (size < sizeof(tga_header_t))
+		return false;
+	
+	tga_header_t *head = (tga_header_t *) data;
+	
+	/* Image ID field */
+	tga->id_data = data + sizeof(tga_header_t);
+	tga->id_length = head->id_length;
+	
+	if (size < sizeof(tga_header_t) + tga->id_length)
+		return false;
+	
+	/* Color map type */
+	tga->cmap_type = head->cmap_type;
+	
+	/* Image type */
+	tga->img_type = head->img_type;
+	
+	/* Color map specification */
+	tga->cmap_first_entry = uint16_t_le2host(head->cmap_first_entry);
+	tga->cmap_entries = uint16_t_le2host(head->cmap_entries);
+	tga->cmap_bpp = head->cmap_bpp;
+	tga->cmap_data = tga->id_data + tga->id_length;
+	tga->cmap_length = ALIGN_UP(tga->cmap_entries * tga->cmap_bpp, 8) >> 3;
+	
+	if (size < sizeof(tga_header_t) + tga->id_length +
+	    tga->cmap_length)
+		return false;
+	
+	/* Image specification */
+	tga->startx = uint16_t_le2host(head->startx);
+	tga->starty = uint16_t_le2host(head->starty);
+	tga->width = uint16_t_le2host(head->width);
+	tga->height = uint16_t_le2host(head->height);
+	tga->img_bpp = head->img_bpp;
+	tga->img_alpha_bpp = head->img_descr & 0x0f;
+	tga->img_alpha_dir = (head->img_descr & 0xf0) >> 4;
+	tga->img_data = tga->cmap_data + tga->cmap_length;
+	tga->img_length = ALIGN_UP(tga->width * tga->height * tga->img_bpp, 8) >> 3;
+	
+	if (size < sizeof(tga_header_t) + tga->id_length +
+	    tga->cmap_length + tga->img_length)
+		return false;
+	
+	return true;
+}
+
+/** Decode Truevision TGA format
+ *
+ * Decode Truevision TGA format and create an image map
+ * from it. The supported variants of TGA are currently
+ * limited to uncompressed 24 bit true-color images without
+ * alpha channel.
+ *
+ * @param[in] data Memory representation of TGA.
+ * @param[in] size Size of the representation (in bytes).
+ *
+ * @return Newly allocated image map.
+ * @return NULL on error or unsupported format.
+ *
+ */
+imgmap_t *imgmap_decode_tga(void *data, size_t size)
+{
+	tga_t tga;
+	if (!decode_tga_header(data, size, &tga))
+		return NULL;
+	
+	/*
+	 * Check for unsupported features.
+	 */
+	
+	switch (tga.cmap_type) {
+	case CMAP_NOT_PRESENT:
+		break;
+	default:
+		/* Unsupported */
+		return NULL;
+	}
+	
+	switch (tga.img_type) {
+	case IMG_BGRA:
+		if (tga.img_bpp != 24)
+			return NULL;
+		break;
+	case IMG_GRAY:
+		if (tga.img_bpp != 8)
+			return NULL;
+		break;
+	default:
+		/* Unsupported */
+		return NULL;
+	}
+	
+	if (tga.img_alpha_bpp != 0)
+		return NULL;
+	
+	sysarg_t twidth = tga.startx + tga.width;
+	sysarg_t theight = tga.starty + tga.height;
+	size_t bsize = twidth * theight * 3;
+	
+	imgmap_t *imgmap = (imgmap_t *) malloc(sizeof(imgmap_t) + bsize);
+	if (imgmap == NULL)
+		return NULL;
+	
+	imgmap->size = sizeof(imgmap_t) + bsize;
+	imgmap->width = twidth;
+	imgmap->height = theight;
+	imgmap->visual = VISUAL_BGR_8_8_8;
+	
+	memset(imgmap->data, 0, bsize);
+	
+	/*
+	 * TGA is encoded in a bottom-up manner.
+	 */
+	
+	switch (tga.img_type) {
+	case IMG_BGRA:
+		for (sysarg_t y = tga.starty; y < theight; y++) {
+			size_t src_offset = (y - tga.starty) * tga.width * 3;
+			size_t dst_offset = ((theight - y - 1) * twidth + tga.startx) * 3;
+			
+			memcpy(imgmap->data + dst_offset, tga.img_data + src_offset,
+			    tga.width * 3);
+		}
+		break;
+	case IMG_GRAY:
+		for (sysarg_t y = tga.starty; y < theight; y++) {
+			for (sysarg_t x = tga.startx; x < twidth; x++) {
+				uint8_t val =
+				    ((uint8_t *) tga.img_data)[(y - tga.starty) * tga.width + (x - tga.startx)];
+				size_t dst_offset = ((theight - y - 1) * twidth + x) * 3;
+				memset(imgmap->data + dst_offset, val, 3);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+	
+	return imgmap;
+}
+
+/** @}
+ */
Index: uspace/lib/imgmap/imgmap.h
===================================================================
--- uspace/lib/imgmap/imgmap.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/imgmap/imgmap.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup imgmap
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef IMGMAP_IMGMAP_H_
+#define IMGMAP_IMGMAP_H_
+
+#include <sys/types.h>
+#include <abi/fb/visuals.h>
+
+typedef struct {
+	size_t size;
+	sysarg_t width;
+	sysarg_t height;
+	visual_t visual;
+	uint8_t data[];
+} imgmap_t;
+
+extern imgmap_t *imgmap_decode_tga(void *, size_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/net/adt/module_map.c
===================================================================
--- uspace/lib/net/adt/module_map.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/adt/module_map.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,9 +39,5 @@
 #include <unistd.h>
 #include <errno.h>
-
-#include <ipc/services.h>
-
 #include <net/modules.h>
-
 #include <adt/generic_char_map.h>
 #include <adt/module_map.h>
@@ -49,19 +45,20 @@
 GENERIC_CHAR_MAP_IMPLEMENT(modules, module_t)
 
-/** Adds module to the module map.
+/** Add module to the module map.
  *
- * @param[out] module	The module structure added.
- * @param[in] modules	The module map.
- * @param[in] name	The module name.
- * @param[in] filename	The full path filename.
- * @param[in] service	The module service.
- * @param[in] task_id	The module current task identifier. Zero means not
- *			running.
- * @param[in] connect_module The module connecting function.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
+ * @param[out] module         Module structure added.
+ * @param[in]  modules        Module map.
+ * @param[in]  name           Module name.
+ * @param[in]  filename       Full path filename.
+ * @param[in]  service        Module service.
+ * @param[in]  task_id        Module current task identifier.
+ *                            Zero means not running.
+ * @param[in]  connect_module Module connecting function.
+ *
+ * @return EOK on success.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
-int
-add_module(module_t **module, modules_t *modules, const uint8_t *name,
+int add_module(module_t **module, modules_t *modules, const uint8_t *name,
     const uint8_t *filename, services_t service, task_id_t task_id,
     connect_module_t connect_module)
@@ -69,11 +66,11 @@
 	module_t *tmp_module;
 	int rc;
-
+	
 	tmp_module = (module_t *) malloc(sizeof(module_t));
 	if (!tmp_module)
 		return ENOMEM;
-
+	
 	tmp_module->task_id = task_id;
-	tmp_module->phone = 0;
+	tmp_module->sess = NULL;
 	tmp_module->usage = 0;
 	tmp_module->name = name;
@@ -81,5 +78,5 @@
 	tmp_module->service = service;
 	tmp_module->connect_module = connect_module;
-
+	
 	rc = modules_add(modules, tmp_module->name, 0, tmp_module);
 	if (rc != EOK) {
@@ -87,29 +84,30 @@
 		return rc;
 	}
+	
 	if (module)
 		*module = tmp_module;
-
+	
 	return EOK;
 }
 
-/** Searches and returns the specified module.
+/** Search and return the specified module.
  *
  * If the module is not running, the module filaname is spawned.
  * If the module is not connected, the connect_function is called.
  *
- * @param[in] modules	The module map.
- * @param[in] name	The module name.
- * @return		The running module found. It does not have to be
- *			connected.
- * @return		NULL if there is no such module.
+ * @param[in] modules Module map.
+ * @param[in] name    Module name.
+ *
+ * @return The running module found. It does not have to be
+ *         connected.
+ * @return NULL if there is no such module.
+ *
  */
 module_t *get_running_module(modules_t *modules, uint8_t *name)
 {
-	module_t *module;
-
-	module = modules_find(modules, name, 0);
+	module_t *module = modules_find(modules, name, 0);
 	if (!module)
 		return NULL;
-
+	
 	if (!module->task_id) {
 		module->task_id = net_spawn(module->filename);
@@ -117,7 +115,8 @@
 			return NULL;
 	}
-	if (!module->phone)
-		module->phone = module->connect_module(module->service);
-
+	
+	if (!module->sess)
+		module->sess = module->connect_module(module->service);
+	
 	return module;
 }
Index: uspace/lib/net/generic/generic.c
===================================================================
--- uspace/lib/net/generic/generic.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/generic/generic.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,18 +44,19 @@
 /** Notify the module about the device state change.
  *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[in] state	The new device state.
- * @param[in] target	The target module service.
- * @return		EOK on success.
- *
- */
-int
-generic_device_state_msg_remote(int phone, int message, device_id_t device_id,
-    int state, services_t target)
-{
-	async_msg_3(phone, (sysarg_t) message, (sysarg_t) device_id,
-	    (sysarg_t) state, target);
+ * @param[in] sess      Service module session.
+ * @param[in] message   Service specific message.
+ * @param[in] device_id Device identifier.
+ * @param[in] state     New device state.
+ * @param[in] target    Target module service.
+ *
+ * @return EOK on success.
+ *
+ */
+int generic_device_state_msg_remote(async_sess_t *sess, sysarg_t message,
+    device_id_t device_id, sysarg_t state, services_t target)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	async_msg_3(exch, message, (sysarg_t) device_id, state, target);
+	async_exchange_end(exch);
 	
 	return EOK;
@@ -64,55 +65,60 @@
 /** Notify a module about the device.
  *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[in] arg2	The second argument of the message.
- * @param[in] service	The device module service.
- * @return		EOK on success.
- * @return		Other error codes as defined for the specific service
- *			 message.
- *
- */
-int
-generic_device_req_remote(int phone, int message, device_id_t device_id,
-    int arg2, services_t service)
-{
-	return (int) async_req_3_0(phone, (sysarg_t) message,
-	    (sysarg_t) device_id, (sysarg_t) arg2, (sysarg_t) service);
+ * @param[in] sess      Service module session.
+ * @param[in] message   Service specific message.
+ * @param[in] device_id Device identifier.
+ * @param[in] arg2      Second argument of the message.
+ * @param[in] service   Device module service.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the specific service
+ *         message.
+ *
+ */
+int generic_device_req_remote(async_sess_t *sess, sysarg_t message,
+    device_id_t device_id, sysarg_t arg2, services_t service)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_0(exch, message, (sysarg_t) device_id,
+	    arg2, (sysarg_t) service);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
 /** Returns the address.
  *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[out] address	The desired address.
- * @param[out] data	The address data container.
- * @return		EOK on success.
- * @return		EBADMEM if the address parameter and/or the data
- *			parameter is NULL.
- * @return		Other error codes as defined for the specific service
- *			message.
- */
-int
-generic_get_addr_req(int phone, int message, device_id_t device_id,
-    measured_string_t **address, uint8_t **data)
-{
-	aid_t message_id;
+ * @param[in] sess      Service module session.
+ * @param[in] message   Service specific message.
+ * @param[in] device_id Device identifier.
+ * @param[out] address  Desired address.
+ * @param[out] data     Address data container.
+ *
+ * @return EOK on success.
+ * @return EBADMEM if the address parameter and/or the data
+ *         parameter is NULL.
+ * @return Other error codes as defined for the specific service
+ *         message.
+ *
+ */
+int generic_get_addr_req(async_sess_t *sess, sysarg_t message,
+    device_id_t device_id, measured_string_t **address, uint8_t **data)
+{
+	if ((!address) || (!data))
+		return EBADMEM;
+	
+	/* Request the address */
+	async_exch_t *exch = async_exchange_begin(sess);
+	aid_t message_id = async_send_1(exch, message, (sysarg_t) device_id,
+	    NULL);
+	int rc = measured_strings_return(exch, address, data, 1);
+	async_exchange_end(exch);
+	
 	sysarg_t result;
-	int string;
-
-	if (!address || !data)
-		return EBADMEM;
-
-	// request the address
-	message_id = async_send_1(phone, (sysarg_t) message,
-	    (sysarg_t) device_id, NULL);
-	string = measured_strings_return(phone, address, data, 1);
 	async_wait_for(message_id, &result);
-
-	// if not successful
-	if ((string == EOK) && (result != EOK)) {
-		// clear the data
+	
+	/* If not successful */
+	if ((rc == EOK) && (result != EOK)) {
+		/* Clear the data */
 		free(*address);
 		free(*data);
@@ -124,16 +130,17 @@
 /** Return the device packet dimension for sending.
  *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[out] packet_dimension The packet dimension.
- * @return		EOK on success.
- * @return		EBADMEM if the packet_dimension parameter is NULL.
- * @return		Other error codes as defined for the specific service
- *			message.
- */
-int
-generic_packet_size_req_remote(int phone, int message, device_id_t device_id,
-    packet_dimension_t *packet_dimension)
+ * @param[in] sess              Service module session.
+ * @param[in] message           Service specific message.
+ * @param[in] device_id         Device identifier.
+ * @param[out] packet_dimension Packet dimension.
+ *
+ * @return EOK on success.
+ * @return EBADMEM if the packet_dimension parameter is NULL.
+ * @return Other error codes as defined for the specific service
+ *         message.
+ *
+ */
+int generic_packet_size_req_remote(async_sess_t *sess, sysarg_t message,
+    device_id_t device_id, packet_dimension_t *packet_dimension)
 {
 	if (!packet_dimension)
@@ -145,6 +152,8 @@
 	sysarg_t suffix;
 	
-	sysarg_t result = async_req_1_4(phone, (sysarg_t) message,
-	    (sysarg_t) device_id, &addr_len, &prefix, &content, &suffix);
+	async_exch_t *exch = async_exchange_begin(sess);
+	sysarg_t result = async_req_1_4(exch, message, (sysarg_t) device_id,
+	    &addr_len, &prefix, &content, &suffix);
+	async_exchange_end(exch);
 	
 	packet_dimension->prefix = (size_t) prefix;
@@ -158,25 +167,31 @@
 /** Pass the packet queue to the module.
  *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[in] packet_id	The received packet or the received packet queue
- *			identifier.
- * @param[in] target	The target module service.
- * @param[in] error	The error module service.
- * @return		EOK on success.
- */
-int
-generic_received_msg_remote(int phone, int message, device_id_t device_id,
-    packet_id_t packet_id, services_t target, services_t error)
-{
+ * @param[in] sess      Service module session.
+ * @param[in] message   Service specific message.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet_id Received packet or the received packet queue
+ *                      identifier.
+ * @param[in] target    Target module service.
+ * @param[in] error     Error module service.
+ *
+ * @return EOK on success.
+ *
+ */
+int generic_received_msg_remote(async_sess_t *sess, sysarg_t message,
+    device_id_t device_id, packet_id_t packet_id, services_t target,
+    services_t error)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	
 	if (error) {
-		async_msg_4(phone, (sysarg_t) message, (sysarg_t) device_id,
+		async_msg_4(exch, message, (sysarg_t) device_id,
 		    (sysarg_t) packet_id, (sysarg_t) target, (sysarg_t) error);
 	} else {
-		async_msg_3(phone, (sysarg_t) message, (sysarg_t) device_id,
+		async_msg_3(exch, message, (sysarg_t) device_id,
 		    (sysarg_t) packet_id, (sysarg_t) target);
 	}
 	
+	async_exchange_end(exch);
+	
 	return EOK;
 }
@@ -184,25 +199,30 @@
 /** Send the packet queue.
  *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[in] packet_id	The packet or the packet queue identifier.
- * @param[in] sender	The sending module service.
- * @param[in] error	The error module service.
- * @return		EOK on success.
- *
- */
-int
-generic_send_msg_remote(int phone, int message, device_id_t device_id,
-    packet_id_t packet_id, services_t sender, services_t error)
-{
+ * @param[in] sess      Service module session.
+ * @param[in] message   Service specific message.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet_id Packet or the packet queue identifier.
+ * @param[in] sender    Sending module service.
+ * @param[in] error     Error module service.
+ *
+ * @return EOK on success.
+ *
+ */
+int generic_send_msg_remote(async_sess_t *sess, sysarg_t message,
+    device_id_t device_id, packet_id_t packet_id, services_t sender,
+    services_t error)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	
 	if (error) {
-		async_msg_4(phone, (sysarg_t) message, (sysarg_t) device_id,
+		async_msg_4(exch, message, (sysarg_t) device_id,
 		    (sysarg_t) packet_id, (sysarg_t) sender, (sysarg_t) error);
 	} else {
-		async_msg_3(phone, (sysarg_t) message, (sysarg_t) device_id,
+		async_msg_3(exch, message, (sysarg_t) device_id,
 		    (sysarg_t) packet_id, (sysarg_t) sender);
 	}
 	
+	async_exchange_end(exch);
+	
 	return EOK;
 }
@@ -212,48 +232,51 @@
  * Allocates and returns the needed memory block as the data parameter.
  *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[in] service	The module service.
- * @param[in] configuration The key strings.
- * @param[in] count	The number of configuration keys.
- * @param[out] translation The translated values.
- * @param[out] data	The translation data container.
- * @return		EOK on success.
- * @return		EINVAL if the configuration parameter is NULL.
- * @return		EINVAL if the count parameter is zero.
- * @return		EBADMEM if the translation or the data parameters are
- *			NULL.
- * @return		Other error codes as defined for the specific service
- *			message.
- */
-int
-generic_translate_req(int phone, int message, device_id_t device_id,
-    services_t service, measured_string_t *configuration, size_t count,
+ * @param[in] sess          Service module session.
+ * @param[in] message       Service specific message.
+ * @param[in] device_id     Device identifier.
+ * @param[in] service       Module service.
+ * @param[in] configuration Key strings.
+ * @param[in] count         Number of configuration keys.
+ * @param[out] translation  Translated values.
+ * @param[out] data         Translation data container.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the configuration parameter is NULL.
+ * @return EINVAL if the count parameter is zero.
+ * @return EBADMEM if the translation or the data parameters are
+ *         NULL.
+ * @return Other error codes as defined for the specific service
+ *         message.
+ *
+ */
+int generic_translate_req(async_sess_t *sess, sysarg_t message,
+    device_id_t device_id, services_t service,
+    measured_string_t *configuration, size_t count,
     measured_string_t **translation, uint8_t **data)
 {
-	aid_t message_id;
+	if ((!configuration) || (count == 0))
+		return EINVAL;
+	
+	if ((!translation) || (!data))
+		return EBADMEM;
+	
+	/* Request the translation */
+	async_exch_t *exch = async_exchange_begin(sess);
+	aid_t message_id = async_send_3(exch, message, (sysarg_t) device_id,
+	    (sysarg_t) count, (sysarg_t) service, NULL);
+	measured_strings_send(exch, configuration, count);
+	int rc = measured_strings_return(exch, translation, data, count);
+	async_exchange_end(exch);
+	
 	sysarg_t result;
-	int string;
-
-	if (!configuration || (count == 0))
-		return EINVAL;
-	if (!translation || !data)
-		return EBADMEM;
-
-	// request the translation
-	message_id = async_send_3(phone, (sysarg_t) message,
-	    (sysarg_t) device_id, (sysarg_t) count, (sysarg_t) service, NULL);
-	measured_strings_send(phone, configuration, count);
-	string = measured_strings_return(phone, translation, data, count);
 	async_wait_for(message_id, &result);
-
-	// if not successful
-	if ((string == EOK) && (result != EOK)) {
-		// clear the data
+	
+	/* If not successful */
+	if ((rc == EOK) && (result != EOK)) {
+		/* Clear the data */
 		free(*translation);
 		free(*data);
 	}
-
+	
 	return (int) result;
 }
Index: uspace/lib/net/generic/net_checksum.c
===================================================================
--- uspace/lib/net/generic/net_checksum.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/generic/net_checksum.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,5 +52,5 @@
 uint16_t compact_checksum(uint32_t sum)
 {
-	// shorten to the 16 bits
+	/* Shorten to the 16 bits */
 	while (sum >> 16)
 		sum = (sum & 0xffff) + (sum >> 16);
@@ -72,9 +72,9 @@
 	size_t index;
 
-	// sum all the 16 bit fields
+	/* Sum all the 16 bit fields */
 	for (index = 0; index + 1 < length; index += 2)
 		seed += (data[index] << 8) + data[index + 1];
 
-	// last odd byte with zero padding
+	/* Last odd byte with zero padding */
 	if (index + 1 == length)
 		seed += data[index] << 8;
@@ -94,39 +94,39 @@
 	size_t index;
 
-	// process full bytes
+	/* Process full bytes */
 	while (length >= 8) {
-		// add the data
+		/* Add the data */
 		seed ^= (*data) << 24;
 		
-		// for each added bit
+		/* For each added bit */
 		for (index = 0; index < 8; ++index) {
-			// if the first bit is set
+			/* If the first bit is set */
 			if (seed & 0x80000000) {
-				// shift and divide the checksum
+				/* Shift and divide the checksum */
 				seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
 			} else {
-				// shift otherwise
+				/* Shift otherwise */
 				seed <<= 1;
 			}
 		}
 		
-		// move to the next byte
+		/* Move to the next byte */
 		++data;
 		length -= 8;
 	}
 
-	// process the odd bits
+	/* Process the odd bits */
 	if (length > 0) {
-		// add the data with zero padding
+		/* Add the data with zero padding */
 		seed ^= ((*data) & (0xff << (8 - length))) << 24;
 		
-		// for each added bit
+		/* For each added bit */
 		for (index = 0; index < length; ++index) {
-			// if the first bit is set
+			/* If the first bit is set */
 			if (seed & 0x80000000) {
-				// shift and divide the checksum
+				/* Shift and divide the checksum */
 				seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
 			} else {
-				// shift otherwise
+				/* Shift otherwise */
 				seed <<= 1;
 			}
@@ -148,38 +148,38 @@
 	size_t index;
 
-	// process full bytes
+	/* Process full bytes */
 	while (length >= 8) {
-		// add the data
+		/* Add the data */
 		seed ^= (*data);
 		
-		// for each added bit
+		/* For each added bit */
 		for (index = 0; index < 8; ++index) {
-			// if the last bit is set
+			/* If the last bit is set */
 			if (seed & 1) {
-				// shift and divide the checksum
+				/* Shift and divide the checksum */
 				seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
 			} else {
-				// shift otherwise
+				/* Shift otherwise */
 				seed >>= 1;
 			}
 		}
 		
-		// move to the next byte
+		/* Move to the next byte */
 		++data;
 		length -= 8;
 	}
 
-	// process the odd bits
+	/* Process the odd bits */
 	if (length > 0) {
-		// add the data with zero padding
+		/* Add the data with zero padding */
 		seed ^= (*data) >> (8 - length);
 		
 		for (index = 0; index < length; ++index) {
-			// if the last bit is set
+			/* If the last bit is set */
 			if (seed & 1) {
-				// shift and divide the checksum
+				/* Shift and divide the checksum */
 				seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
 			} else {
-				// shift otherwise
+				/* Shift otherwise */
 				seed >>= 1;
 			}
@@ -198,5 +198,5 @@
 uint16_t flip_checksum(uint16_t checksum)
 {
-	// flip, zero is returned as 0xFFFF (not flipped)
+	/* Flip, zero is returned as 0xFFFF (not flipped) */
 	checksum = ~checksum;
 	return checksum ? checksum : IP_CHECKSUM_ZERO;
@@ -216,5 +216,5 @@
 uint16_t ip_checksum(uint8_t *data, size_t length)
 {
-	// compute, compact and flip the data checksum
+	/* Compute, compact and flip the data checksum */
 	return flip_checksum(compact_checksum(compute_checksum(0, data,
 	    length)));
Index: uspace/lib/net/generic/net_remote.c
===================================================================
--- uspace/lib/net/generic/net_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/generic/net_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -47,19 +47,22 @@
 #include <adt/measured_strings.h>
 
-/** Connects to the networking module.
+/** Connect to the networking module.
  *
- * @return		The networking module phone on success.
+ * @return Networking module session on success.
+ *
  */
-int net_connect_module(void)
+async_sess_t *net_connect_module(void)
 {
 	return connect_to_service(SERVICE_NETWORKING);
 }
 
-/** Frees the received settings.
+/** Free the received settings.
  *
- * @param[in] settings	The received settings.
- * @param[in] data	The received settings data.
- * @see	net_get_device_conf_req()
+ * @param[in] settings Received settings.
+ * @param[in] data     Received settings data.
+ *
+ * @see net_get_device_conf_req()
  * @see net_get_conf_req()
+ *
  */
 void net_free_settings(measured_string_t *settings, uint8_t *data)
@@ -71,5 +74,5 @@
 }
 
-/** Returns the global configuration.
+/** Return the global configuration.
  *
  * The configuration names are read and the appropriate settings are set
@@ -77,48 +80,52 @@
  * configuration.
  *
- * @param[in] net_phone	The networking module phone.
- * @param[in,out] configuration The requested configuration. The names are read
- * and the appropriate settings are set instead.
+ * @param[in]     sess          Networking module session.
+ * @param[in,out] configuration Requested configuration. The names are
+ *                              read and the appropriate settings are set
+ *                              instead.
  *
- * @param[in] count	The configuration entries count.
- * @param[in,out] data	The configuration and settings data.
- * @return		EOK on success.
- * @return		EINVAL if the configuration is NULL.
- * @return		EINVAL if the count is zero.
- * @return		Other error codes as defined for the
- *			generic_translate_req() function.
+ * @param[in]     count         Configuration entries count.
+ * @param[in,out] data          Configuration and settings data.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the configuration is NULL.
+ * @return EINVAL if the count is zero.
+ * @return Other error codes as defined for the
+ *         generic_translate_req() function.
+ *
  */
-int
-net_get_conf_req(int net_phone, measured_string_t **configuration,
+int net_get_conf_req(async_sess_t *sess, measured_string_t **configuration,
     size_t count, uint8_t **data)
 {
-	return generic_translate_req(net_phone, NET_NET_GET_DEVICE_CONF, 0, 0,
+	return generic_translate_req(sess, NET_NET_GET_DEVICE_CONF, 0, 0,
 	    *configuration, count, configuration, data);
 }
 
-/** Returns the device specific configuration.
+/** Return the device specific configuration.
  *
- * Returns the global configuration if the device specific is not found.
+ * Return the global configuration if the device specific is not found.
  * The configuration names are read and the appropriate settings are set
  * instead. Call net_free_settings() function to release the returned
  * configuration.
  *
- * @param[in] net_phone	The networking module phone.
- * @param[in] device_id	The device identifier.
- * @param[in,out] configuration The requested device configuration. The names
- *			are read and the appropriate settings are set instead.
- * @param[in] count	The configuration entries count.
- * @param[in,out] data	The configuration and settings data.
- * @return		EOK on success.
- * @return		EINVAL if the configuration is NULL.
- * @return		EINVAL if the count is zero.
- * @return		Other error codes as defined for the
- *			generic_translate_req() function.
+ * @param[in]     sess          The networking module session.
+ * @param[in]     device_id     Device identifier.
+ * @param[in,out] configuration Requested device configuration. The names
+ *                              are read and the appropriate settings are
+ *                              set instead.
+ * @param[in]     count         Configuration entries count.
+ * @param[in,out] data          Configuration and settings data.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the configuration is NULL.
+ * @return EINVAL if the count is zero.
+ * @return Other error codes as defined for the
+ *         generic_translate_req() function.
+ *
  */
-int
-net_get_device_conf_req(int net_phone, device_id_t device_id,
+int net_get_device_conf_req(async_sess_t *sess, device_id_t device_id,
     measured_string_t **configuration, size_t count, uint8_t **data)
 {
-	return generic_translate_req(net_phone, NET_NET_GET_DEVICE_CONF,
+	return generic_translate_req(sess, NET_NET_GET_DEVICE_CONF,
 	    device_id, 0, *configuration, count, configuration, data);
 }
Index: uspace/lib/net/generic/packet_client.c
===================================================================
--- uspace/lib/net/generic/packet_client.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/generic/packet_client.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -247,37 +247,38 @@
 }
 
-/** Returns the packet copy.
- *
- * Copies the addresses, data, order and metric values.
- * Does not copy the queue placement.
- *
- * @param[in] phone	The packet server module phone.
- * @param[in] packet	The original packet.
- * @return		The packet copy.
- * @return		NULL on error.
- */
-packet_t *packet_get_copy(int phone, packet_t *packet)
-{
-	packet_t *copy;
-	uint8_t * src = NULL;
-	uint8_t * dest = NULL;
-	size_t addrlen;
-
-	if (!packet_is_valid(packet))
-		return NULL;
-
-	// get a new packet
-	copy = packet_get_4_remote(phone, PACKET_DATA_LENGTH(packet),
+/** Return the packet copy.
+ *
+ * Copy the addresses, data, order and metric values.
+ * Queue placement is not copied.
+ *
+ * @param[in] sess   Packet server module session.
+ * @param[in] packet Original packet.
+ *
+ * @return Packet copy.
+ * @return NULL on error.
+ *
+ */
+packet_t *packet_get_copy(async_sess_t *sess, packet_t *packet)
+{
+	if (!packet_is_valid(packet))
+		return NULL;
+	
+	/* Get a new packet */
+	packet_t *copy = packet_get_4_remote(sess, PACKET_DATA_LENGTH(packet),
 	    PACKET_MAX_ADDRESS_LENGTH(packet), packet->max_prefix,
 	    PACKET_MIN_SUFFIX(packet));
+	
 	if (!copy)
 		return NULL;
-
-	// get addresses
-	addrlen = packet_get_addr(packet, &src, &dest);
-	// copy data
+	
+	/* Get addresses */
+	uint8_t *src = NULL;
+	uint8_t *dest = NULL;
+	size_t addrlen = packet_get_addr(packet, &src, &dest);
+	
+	/* Copy data */
 	if ((packet_copy_data(copy, packet_get_data(packet),
 	    PACKET_DATA_LENGTH(packet)) == EOK) &&
-	    // copy addresses if present
+	    /* Copy addresses if present */
 	    ((addrlen <= 0) ||
 	    (packet_set_addr(copy, src, dest, addrlen) == EOK))) {
@@ -286,5 +287,5 @@
 		return copy;
 	} else {
-		pq_release_remote(phone, copy->packet_id);
+		pq_release_remote(sess, copy->packet_id);
 		return NULL;
 	}
Index: uspace/lib/net/generic/packet_remote.c
===================================================================
--- uspace/lib/net/generic/packet_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/generic/packet_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -51,63 +51,64 @@
  * Create the local packet mapping as well.
  *
- * @param[in]  phone     The packet server module phone.
- * @param[out] packet    The packet reference pointer to store the received
+ * @param[in]  sess      Packet server module session.
+ * @param[out] packet    Packet reference pointer to store the received
  *                       packet reference.
- * @param[in]  packet_id The packet identifier.
- * @param[in]  size      The packet total size in bytes.
+ * @param[in]  packet_id Packet identifier.
+ * @param[in]  size      Packet total size in bytes.
  *
  * @return EOK on success.
  * @return Other error codes as defined for the pm_add() function.
- * @return Other error codes as defined for the async_share_in_start() function.
- *
- */
-static int
-packet_return(int phone, packet_t **packet, packet_id_t packet_id, size_t size)
-{
+ * @return Other error codes as defined for the async_share_in_start()
+ *         function.
+ *
+ */
+static int packet_return(async_sess_t *sess, packet_t **packet,
+    packet_id_t packet_id, size_t size)
+{
+	*packet = (packet_t *) as_get_mappable_page(size);
+	
+	async_exch_t *exch = async_exchange_begin(sess);
 	ipc_call_t answer;
-	aid_t message;
-	int rc;
-	
-	message = async_send_1(phone, NET_PACKET_GET, packet_id, &answer);
-
-	*packet = (packet_t *) as_get_mappable_page(size);
-	rc = async_share_in_start_0_0(phone, *packet, size);
+	aid_t message = async_send_1(exch, NET_PACKET_GET, packet_id, &answer);
+	int rc = async_share_in_start_0_0(exch, *packet, size);
+	async_exchange_end(exch);
+	
+	sysarg_t result;
+	async_wait_for(message, &result);
+	
 	if (rc != EOK) {
 		munmap(*packet, size);
-		async_wait_for(message, NULL);
 		return rc;
 	}
+	
 	rc = pm_add(*packet);
 	if (rc != EOK) {
 		munmap(*packet, size);
-		async_wait_for(message, NULL);
 		return rc;
 	}
 	
-	sysarg_t result;
-	async_wait_for(message, &result);
-	
 	return result;
 }
 
-/** Translates the packet identifier to the packet reference.
- *
- * Tries to find mapping first.
- * Contacts the packet server to share the packet if the mapping is not present.
- *
- * @param[in] phone	The packet server module phone.
- * @param[out] packet	The packet reference.
- * @param[in] packet_id	The packet identifier.
- * @return		EOK on success.
- * @return		EINVAL if the packet parameter is NULL.
- * @return		Other error codes as defined for the NET_PACKET_GET_SIZE
- *			message.
- * @return		Other error codes as defined for the packet_return()
- *			function.
- */
-int packet_translate_remote(int phone, packet_t **packet, packet_id_t packet_id)
-{
-	int rc;
-	
+/** Translate the packet identifier to the packet reference.
+ *
+ * Try to find mapping first. The packet server is asked to share
+ * the packet if the mapping is not present.
+ *
+ * @param[in]  sess      Packet server module session.
+ * @param[out] packet    Packet reference.
+ * @param[in]  packet_id Packet identifier.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the packet parameter is NULL.
+ * @return Other error codes as defined for the NET_PACKET_GET_SIZE
+ *         message.
+ * @return Other error codes as defined for the packet_return()
+ *         function.
+ *
+ */
+int packet_translate_remote(async_sess_t *sess, packet_t **packet,
+    packet_id_t packet_id)
+{
 	if (!packet)
 		return EINVAL;
@@ -115,18 +116,21 @@
 	*packet = pm_find(packet_id);
 	if (!*packet) {
+		async_exch_t *exch = async_exchange_begin(sess);
 		sysarg_t size;
+		int rc = async_req_1_1(exch, NET_PACKET_GET_SIZE, packet_id,
+		    &size);
+		async_exchange_end(exch);
 		
-		rc = async_req_1_1(phone, NET_PACKET_GET_SIZE, packet_id,
-		    &size);
 		if (rc != EOK)
 			return rc;
-		rc = packet_return(phone, packet, packet_id, size);
+		
+		rc = packet_return(sess, packet, packet_id, size);
 		if (rc != EOK)
 			return rc;
 	}
+	
 	if ((*packet)->next) {
 		packet_t *next;
-		
-		return packet_translate_remote(phone, &next, (*packet)->next);
+		return packet_translate_remote(sess, &next, (*packet)->next);
 	}
 	
@@ -134,33 +138,35 @@
 }
 
-/** Obtains the packet of the given dimensions.
- *
- * Contacts the packet server to return the appropriate packet.
- *
- * @param[in] phone	The packet server module phone.
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- * @return		The packet reference.
- * @return		NULL on error.
- */
-packet_t *packet_get_4_remote(int phone, size_t max_content, size_t addr_len,
-    size_t max_prefix, size_t max_suffix)
-{
+/** Obtain the packet of given dimensions.
+ *
+ * Contact the packet server to return the appropriate packet.
+ *
+ * @param[in] sess        Packet server module session.
+ * @param[in] addr_len    Source and destination addresses maximal length
+ *                        in bytes.
+ * @param[in] max_prefix  Maximal prefix length in bytes.
+ * @param[in] max_content Maximal content length in bytes.
+ * @param[in] max_suffix  Maximal suffix length in bytes.
+ *
+ * @return The packet reference.
+ * @return NULL on error.
+ *
+ */
+packet_t *packet_get_4_remote(async_sess_t *sess, size_t max_content,
+    size_t addr_len, size_t max_prefix, size_t max_suffix)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
 	sysarg_t packet_id;
 	sysarg_t size;
-	int rc;
-	
-	rc = async_req_4_2(phone, NET_PACKET_CREATE_4, max_content, addr_len,
+	int rc = async_req_4_2(exch, NET_PACKET_CREATE_4, max_content, addr_len,
 	    max_prefix, max_suffix, &packet_id, &size);
+	async_exchange_end(exch);
+	
 	if (rc != EOK)
 		return NULL;
 	
-	
 	packet_t *packet = pm_find(packet_id);
 	if (!packet) {
-		rc = packet_return(phone, &packet, packet_id, size);
+		rc = packet_return(sess, &packet, packet_id, size);
 		if (rc != EOK)
 			return NULL;
@@ -170,21 +176,24 @@
 }
 
-/** Obtains the packet of the given content size.
- *
- * Contacts the packet server to return the appropriate packet.
- *
- * @param[in] phone	The packet server module phone.
- * @param[in] content	The maximal content length in bytes.
- * @return		The packet reference.
- * @return		NULL on error.
- */
-packet_t *packet_get_1_remote(int phone, size_t content)
-{
+/** Obtain the packet of given content size.
+ *
+ * Contact the packet server to return the appropriate packet.
+ *
+ * @param[in] sess    Packet server module session.
+ * @param[in] content Maximal content length in bytes.
+ *
+ * @return The packet reference.
+ * @return NULL on error.
+ *
+ */
+packet_t *packet_get_1_remote(async_sess_t *sess, size_t content)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
 	sysarg_t packet_id;
 	sysarg_t size;
-	int rc;
-	
-	rc = async_req_1_2(phone, NET_PACKET_CREATE_1, content, &packet_id,
+	int rc = async_req_1_2(exch, NET_PACKET_CREATE_1, content, &packet_id,
 	    &size);
+	async_exchange_end(exch);
+	
 	if (rc != EOK)
 		return NULL;
@@ -192,5 +201,5 @@
 	packet_t *packet = pm_find(packet_id);
 	if (!packet) {
-		rc = packet_return(phone, &packet, packet_id, size);
+		rc = packet_return(sess, &packet, packet_id, size);
 		if (rc != EOK)
 			return NULL;
@@ -200,5 +209,5 @@
 }
 
-/** Releases the packet queue.
+/** Release the packet queue.
  *
  * All packets in the queue are marked as free for use.
@@ -207,10 +216,13 @@
  * received or obtained again.
  *
- * @param[in] phone	The packet server module phone.
- * @param[in] packet_id	The packet identifier.
- */
-void pq_release_remote(int phone, packet_id_t packet_id)
-{
-	async_msg_1(phone, NET_PACKET_RELEASE, packet_id);
+ * @param[in] sess      Packet server module session.
+ * @param[in] packet_id Packet identifier.
+ *
+ */
+void pq_release_remote(async_sess_t *sess, packet_id_t packet_id)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	async_msg_1(exch, NET_PACKET_RELEASE, packet_id);
+	async_exchange_end(exch);
 }
 
Index: uspace/lib/net/il/arp_remote.c
===================================================================
--- uspace/lib/net/il/arp_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/il/arp_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,24 +38,20 @@
 #include <arp_interface.h>
 #include <generic.h>
-
-#include <async.h>
-#include <errno.h>
 #include <ipc/services.h>
 #include <ipc/arp.h>
-
 #include <net/modules.h>
 #include <net/device.h>
 #include <adt/measured_strings.h>
+#include <async.h>
+#include <errno.h>
 
-/** Connects to the ARP module.
+/** Connect to the ARP module.
  *
- * @param service	The ARP module service. Ignored parameter.
- * @return		The ARP module phone on success.
+ * @return ARP module session on success.
+ *
  */
-int arp_connect_module(services_t service)
+async_sess_t *arp_connect_module(services_t service)
 {
-	if (service != SERVICE_ARP)
-		return EINVAL;
-
+	// FIXME: Get rid of the useless argument
 	return connect_to_service(SERVICE_ARP);
 }
@@ -63,31 +59,98 @@
 /** Cleans the cache.
  *
- * @param[in] arp_phone	The ARP module phone used for (semi)remote calls.
- * @return		EOK on success.
+ * @param[in] sess ARP module session.
+ *
+ * @return EOK on success.
+ *
  */
-int arp_clean_cache_req(int arp_phone)
+int arp_clean_cache_req(async_sess_t *sess)
 {
-	return (int) async_req_0_0(arp_phone, NET_ARP_CLEAN_CACHE);
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_0_0(exch, NET_ARP_CLEAN_CACHE);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
-/** Clears the given protocol address from the cache.
+/** Clear the given protocol address from the cache.
  *
- * @param[in] arp_phone	The ARP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[in] protocol	The requesting protocol service.
- * @param[in] address	The protocol address to be cleared.
- * @return		EOK on success.
- * @return		ENOENT if the mapping is not found.
+ * @param[in] sess      ARP module session.
+ * @param[in] device_id Device identifier.
+ * @param[in] protocol  Requesting protocol service.
+ * @param[in] address   Protocol address to be cleared.
+ *
+ * @return EOK on success.
+ * @return ENOENT if the mapping is not found.
+ *
  */
-int
-arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol,
-    measured_string_t *address)
+int arp_clear_address_req(async_sess_t *sess, device_id_t device_id,
+    services_t protocol, measured_string_t *address)
 {
-	aid_t message_id;
+	async_exch_t *exch = async_exchange_begin(sess);
+	aid_t message_id = async_send_2(exch, NET_ARP_CLEAR_ADDRESS,
+	    (sysarg_t) device_id, protocol, NULL);
+	measured_strings_send(exch, address, 1);
+	async_exchange_end(exch);
+	
 	sysarg_t result;
+	async_wait_for(message_id, &result);
+	
+	return (int) result;
+}
 
-	message_id = async_send_2(arp_phone, NET_ARP_CLEAR_ADDRESS,
-	    (sysarg_t) device_id, protocol, NULL);
-	measured_strings_send(arp_phone, address, 1);
+/** Clear the device cache.
+ *
+ * @param[in] sess      ARP module session.
+ * @param[in] device_id Device identifier.
+ *
+ * @return EOK on success.
+ * @return ENOENT if the device is not found.
+ *
+ */
+int arp_clear_device_req(async_sess_t *sess, device_id_t device_id)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_1_0(exch, NET_ARP_CLEAR_DEVICE,
+	    (sysarg_t) device_id);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Register new device and the requesting protocol service.
+ *
+ * Connect to the network interface layer service.
+ * Determine the device broadcast address, its address lengths and packet size.
+ *
+ * @param[in] sess      ARP module session.
+ * @param[in] device_id New device identifier.
+ * @param[in] protocol  Requesting protocol service.
+ * @param[in] netif     Underlying device network interface layer service.
+ * @param[in] address   Local requesting protocol address of the device.
+ *
+ * @return EOK on success.
+ * @return EEXIST if the device is already used.
+ * @return ENOMEM if there is not enough memory left.
+ * @return ENOENT if the network interface service is not known.
+ * @return EREFUSED if the network interface service is not
+ *         responding.
+ * @return Other error codes as defined for the
+ *         nil_packet_get_size() function.
+ * @return Other error codes as defined for the nil_get_addr()
+ *         function.
+ * @return Other error codes as defined for the
+ *         nil_get_broadcast_addr() function.
+ *
+ */
+int arp_device_req(async_sess_t *sess, device_id_t device_id,
+    services_t protocol, services_t netif, measured_string_t *address)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	aid_t message_id = async_send_3(exch, NET_ARP_DEVICE,
+	    (sysarg_t) device_id, protocol, netif, NULL);
+	measured_strings_send(exch, address, 1);
+	async_exchange_end(exch);
+	
+	sysarg_t result;
 	async_wait_for(message_id, &result);
 
@@ -95,76 +158,28 @@
 }
 
-/** Clears the device cache.
+/** Translate the given protocol address to the network interface address.
  *
- * @param[in] arp_phone	The ARP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @return		EOK on success.
- * @return		ENOENT if the device is not found.
+ * Broadcast the ARP request if the mapping is not found.
+ * Allocate and returns the needed memory block as the data parameter.
+ *
+ * @param[in]  sess        ARP module session.
+ * @param[in]  device_id   Device identifier.
+ * @param[in]  protocol    Requesting protocol service.
+ * @param[in]  address     Local requesting protocol address.
+ * @param[out] translation Translation of the local protocol address.
+ * @param[out] data        Allocated raw translation data container.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the address parameter is NULL.
+ * @return EBADMEM if the translation or the data parameters are
+ *         NULL.
+ * @return ENOENT if the mapping is not found.
+ *
  */
-int arp_clear_device_req(int arp_phone, device_id_t device_id)
+int arp_translate_req(async_sess_t *sess, device_id_t device_id,
+    services_t protocol, measured_string_t *address,
+    measured_string_t **translation, uint8_t **data)
 {
-	return (int) async_req_1_0(arp_phone, NET_ARP_CLEAR_DEVICE,
-	    (sysarg_t) device_id);
-}
-
-/** Registers the new device and the requesting protocol service.
- *
- * Connects to the network interface layer service.
- * Determines the device broadcast address, its address lengths and packet size.
- *
- * @param[in] arp_phone	The ARP module phone used for (semi)remote calls.
- * @param[in] device_id	The new device identifier.
- * @param[in] protocol	The requesting protocol service.
- * @param[in] netif	The underlying device network interface layer service.
- * @param[in] address	The local requesting protocol address of the device.
- * @return		EOK on success.
- * @return		EEXIST if the device is already used.
- * @return		ENOMEM if there is not enough memory left.
- * @return		ENOENT if the network interface service is not known.
- * @return		EREFUSED if the network interface service is not
- *			responding.
- * @return		Other error codes as defined for the
- *			nil_packet_get_size() function.
- * @return		Other error codes as defined for the nil_get_addr()
- *			function.
- * @return		Other error codes as defined for the
- *			nil_get_broadcast_addr() function.
- */
-int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol,
-    services_t netif, measured_string_t *address)
-{
-	aid_t message_id;
-	sysarg_t result;
-
-	message_id = async_send_3(arp_phone, NET_ARP_DEVICE,
-	    (sysarg_t) device_id, protocol, netif, NULL);
-	measured_strings_send(arp_phone, address, 1);
-	async_wait_for(message_id, &result);
-
-	return (int) result;
-}
-
-/** Translates the given protocol address to the network interface address.
- *
- * Broadcasts the ARP request if the mapping is not found.
- * Allocates and returns the needed memory block as the data parameter.
- *
- * @param[in] arp_phone	The ARP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[in] protocol	The requesting protocol service.
- * @param[in] address	The local requesting protocol address.
- * @param[out] translation The translation of the local protocol address.
- * @param[out] data	The allocated raw translation data container.
- * @return		EOK on success.
- * @return		EINVAL if the address parameter is NULL.
- * @return		EBADMEM if the translation or the data parameters are
- *			NULL.
- * @return		ENOENT if the mapping is not found.
- */
-int
-arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol,
-    measured_string_t *address, measured_string_t **translation, uint8_t **data)
-{
-	return generic_translate_req(arp_phone, NET_ARP_TRANSLATE, device_id,
+	return generic_translate_req(sess, NET_ARP_TRANSLATE, device_id,
 	    protocol, address, 1, translation, data);
 }
Index: uspace/lib/net/il/il_remote.c
===================================================================
--- uspace/lib/net/il/il_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/il/il_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,8 +39,6 @@
 #include <generic.h>
 #include <packet_client.h>
-
 #include <ipc/services.h>
 #include <ipc/il.h>
-
 #include <net/device.h>
 #include <net/packet.h>
@@ -48,9 +46,8 @@
 /** Notify the internetwork layer modules about the device state change.
  *
- * @param[in] il_phone  The internetwork layer module phone used for
- *                      (semi)remote calls.
- * @param[in] device_id The device identifier.
- * @param[in] state     The new device state.
- * @param[in] target    The target internetwork module service to be
+ * @param[in] sess      Internetwork layer module session.
+ * @param[in] device_id Device identifier.
+ * @param[in] state     New device state.
+ * @param[in] target    Target internetwork module service to be
  *                      delivered to.
  *
@@ -58,8 +55,8 @@
  *
  */
-int il_device_state_msg(int il_phone, device_id_t device_id,
+int il_device_state_msg(async_sess_t *sess, device_id_t device_id,
     device_state_t state, services_t target)
 {
-	return generic_device_state_msg_remote(il_phone, NET_IL_DEVICE_STATE,
+	return generic_device_state_msg_remote(sess, NET_IL_DEVICE_STATE,
 	    device_id, state, target);
 }
@@ -67,9 +64,8 @@
 /** Notify the internetwork layer modules about the received packet/s.
  *
- * @param[in] il_phone  The internetwork layer module phone used for
- *                      (semi)remote calls.
- * @param[in] device_id The device identifier.
- * @param[in] packet    The received packet or the received packet queue.
- * @param[in] target    The target internetwork module service to be
+ * @param[in] sess      Internetwork layer module session.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
+ * @param[in] target    Target internetwork module service to be
  *                      delivered to.
  *
@@ -77,8 +73,8 @@
  *
  */
-int il_received_msg(int il_phone, device_id_t device_id, packet_t *packet,
+int il_received_msg(async_sess_t *sess, device_id_t device_id, packet_t *packet,
     services_t target)
 {
-	return generic_received_msg_remote(il_phone, NET_IL_RECEIVED, device_id,
+	return generic_received_msg_remote(sess, NET_IL_RECEIVED, device_id,
 	    packet_get_id(packet), target, 0);
 }
@@ -86,9 +82,8 @@
 /** Notify the internetwork layer modules about the mtu change.
  *
- * @param[in] il_phone  The internetwork layer module phone used for
- *                      (semi)remote calls.
- * @param[in] device_id The device identifier.
- * @param[in] mtu       The new mtu value.
- * @param[in] target    The target internetwork module service to be
+ * @param[in] sess      Internetwork layer module session.
+ * @param[in] device_id Device identifier.
+ * @param[in] mtu       New MTU value.
+ * @param[in] target    Target internetwork module service to be
  *                      delivered to.
  *
@@ -96,9 +91,9 @@
  *
  */
-int il_mtu_changed_msg(int il_phone, device_id_t device_id, size_t mtu,
+int il_mtu_changed_msg(async_sess_t *sess, device_id_t device_id, size_t mtu,
     services_t target)
 {
-	return generic_device_state_msg_remote(il_phone, NET_IL_MTU_CHANGED,
-	    device_id, (int) mtu, target);
+	return generic_device_state_msg_remote(sess, NET_IL_MTU_CHANGED,
+	    device_id, mtu, target);
 }
 
Index: uspace/lib/net/il/il_skel.c
===================================================================
--- uspace/lib/net/il/il_skel.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/il/il_skel.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #include <bool.h>
 #include <errno.h>
+#include <ns.h>
 #include <il_skel.h>
 #include <net_interface.h>
@@ -48,5 +49,6 @@
  *
  */
-static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	/*
@@ -75,6 +77,5 @@
 		 * result.
 		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
+		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
 			return;
 		
@@ -96,14 +97,12 @@
  * @return Other error codes as defined for the il_initialize()
  *         function.
- * @return Other error codes as defined for the REGISTER_ME() macro
- *         function.
  *
  */
-int il_module_start(int service)
+int il_module_start(sysarg_t service)
 {
 	async_set_client_connection(il_client_connection);
-	int net_phone = net_connect_module();
-	if (net_phone < 0)
-		return net_phone;
+	async_sess_t *sess = net_connect_module();
+	if (!sess)
+		return ENOENT;
 	
 	int rc = pm_init();
@@ -111,9 +110,9 @@
 		return rc;
 	
-	rc = il_initialize(net_phone);
+	rc = il_initialize(sess);
 	if (rc != EOK)
 		goto out;
 	
-	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
+	rc = service_register(service);
 	if (rc != EOK)
 		goto out;
Index: uspace/lib/net/il/ip_client.c
===================================================================
--- uspace/lib/net/il/ip_client.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/il/ip_client.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -124,5 +124,6 @@
 
 	// TODO IPv6
-/*	case AF_INET6:
+#if 0
+	case AF_INET6:
 		if (addrlen != sizeof(struct sockaddr_in6))
 			return EINVAL;
@@ -130,5 +131,5 @@
 		address_in6 = (struct sockaddr_in6 *) addr;
 		return EOK;
-*/
+#endif
 
 	default:
@@ -159,6 +160,8 @@
 	size_t padding;
 
-	// compute the padding if IP options are set
-	// multiple of 4 bytes
+	/*
+	 * Compute the padding if IP options are set
+	 * multiple of 4 bytes
+	 */
 	padding =  ipopt_length % 4;
 	if (padding) {
@@ -167,17 +170,17 @@
 	}
 
-	// prefix the header
+	/* Prefix the header */
 	data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding);
 	if (!data)
 		return ENOMEM;
 
-	// add the padding
+	/* Add the padding */
 	while (padding--)
 		data[sizeof(ip_header_t) + padding] = IPOPT_NOOP;
 
-	// set the header
+	/* Set the header */
 	header = (ip_header_t *) data;
-	header->header_length = IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) +
-	    ipopt_length);
+	SET_IP_HEADER_LENGTH(header,
+	    (IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) + ipopt_length)));
 	header->ttl = (ttl ? ttl : IPDEFTTL);
 	header->tos = tos;
@@ -185,5 +188,5 @@
 
 	if (dont_fragment)
-		header->flags = IPFLAG_DONT_FRAGMENT;
+		SET_IP_HEADER_FLAGS(header, IPFLAG_DONT_FRAGMENT);
 
 	return EOK;
@@ -224,5 +227,5 @@
 		*tos = header->tos;
 	if (dont_fragment)
-		*dont_fragment = header->flags & IPFLAG_DONT_FRAGMENT;
+		*dont_fragment = GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT;
 	if (ipopt_length) {
 		*ipopt_length = IP_HEADER_LENGTH(header) - sizeof(ip_header_t);
Index: uspace/lib/net/il/ip_remote.c
===================================================================
--- uspace/lib/net/il/ip_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/il/ip_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,9 +44,7 @@
 #include <packet_client.h>
 #include <generic.h>
-
 #include <ipc/services.h>
 #include <ipc/il.h>
 #include <ipc/ip.h>
-
 #include <net/modules.h>
 #include <net/device.h>
@@ -57,44 +55,50 @@
  * The target network is routed using this device.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[in] address	The target network address.
- * @param[in] netmask	The target network mask.
- * @param[in] gateway	The target network gateway. Not used if zero.
- */
-int ip_add_route_req_remote(int ip_phone, device_id_t device_id,
+ * @param[in] sess      IP module sessions.
+ * @param[in] device_id Device identifier.
+ * @param[in] address   Target network address.
+ * @param[in] netmask   Target network mask.
+ * @param[in] gateway   Target network gateway. Not used if zero.
+ *
+ */
+int ip_add_route_req_remote(async_sess_t *sess, device_id_t device_id,
     in_addr_t address, in_addr_t netmask, in_addr_t gateway)
 {
-	return (int) async_req_4_0(ip_phone, NET_IP_ADD_ROUTE,
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_4_0(exch, NET_IP_ADD_ROUTE,
 	    (sysarg_t) device_id, (sysarg_t) gateway.s_addr,
 	    (sysarg_t) address.s_addr, (sysarg_t) netmask.s_addr);
-}
-
-/** Creates bidirectional connection with the ip module service and registers
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Create bidirectional connection with the ip module service and register
  * the message receiver.
  *
- * @param[in] service	The IP module service.
- * @param[in] protocol	The transport layer protocol.
- * @param[in] me	The requesting module service.
- * @param[in] receiver	The message receiver. Used for remote connection.
- * @return		The phone of the needed service.
- * @return		EOK on success.
- * @return		Other error codes as defined for the bind_service()
- *			function.
- */
-int ip_bind_service(services_t service, int protocol, services_t me,
+ * @param[in] service  IP module service.
+ * @param[in] protocol Transport layer protocol.
+ * @param[in] me       Rquesting module service.
+ * @param[in] receiver Message receiver. Used for remote connection.
+ *
+ * @return Session to the needed service.
+ * @return NULL on failure.
+ *
+ */
+async_sess_t *ip_bind_service(services_t service, int protocol, services_t me,
     async_client_conn_t receiver)
 {
-	return (int) bind_service(service, (sysarg_t) protocol, me, service,
+	return bind_service(service, (sysarg_t) protocol, me, service,
 	    receiver);
 }
 
-/** Connects to the IP module.
- *
- * @param service	The IP module service. Ignored parameter.
- * @return		The IP module phone on success.
- */
-int ip_connect_module(services_t service)
-{
+/** Connect to the IP module.
+ *
+ * @return The IP module session.
+ *
+ */
+async_sess_t *ip_connect_module(services_t service)
+{
+	// FIXME: Get rid of the useless argument
 	return connect_to_service(SERVICE_IP);
 }
@@ -105,21 +109,22 @@
  * If the device uses ARP registers also the new ARP device.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] device_id	The new device identifier.
- * @param[in] netif	The underlying device network interface layer service.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EINVAL if the device configuration is invalid.
- * @return		ENOTSUP if the device uses IPv6.
- * @return		ENOTSUP if the device uses DHCP.
- * @return		Other error codes as defined for the
- *			net_get_device_conf_req() function.
- * @return		Other error codes as defined for the arp_device_req()
- *			function.
- */
-int ip_device_req_remote(int ip_phone, device_id_t device_id,
+ * @param[in] sess      IP module session.
+ * @param[in] device_id New device identifier.
+ *
+ * @return EOK on success.
+ * @return ENOMEM if there is not enough memory left.
+ * @return EINVAL if the device configuration is invalid.
+ * @return ENOTSUP if the device uses IPv6.
+ * @return ENOTSUP if the device uses DHCP.
+ * @return Other error codes as defined for the
+ *         net_get_device_conf_req() function.
+ * @return Other error codes as defined for the arp_device_req()
+ *         function.
+ *
+ */
+int ip_device_req_remote(async_sess_t *sess, device_id_t device_id,
     services_t service)
 {
-	return generic_device_req_remote(ip_phone, NET_IP_DEVICE, device_id, 0,
+	return generic_device_req_remote(sess, NET_IP_DEVICE, device_id, 0,
 	    service);
 }
@@ -128,35 +133,37 @@
  * destination address.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] protocol	The transport protocol.
- * @param[in] destination The destination address.
- * @param[in] addrlen	The destination address length.
- * @param[out] device_id The device identifier.
- * @param[out] header	The constructed IP pseudo header.
- * @param[out] headerlen The IP pseudo header length.
- *
- */
-int ip_get_route_req_remote(int ip_phone, ip_protocol_t protocol,
+ * @param[in] sess        IP module session.
+ * @param[in] protocol    Transport protocol.
+ * @param[in] destination Destination address.
+ * @param[in] addrlen     Destination address length.
+ * @param[out] device_id  Device identifier.
+ * @param[out] header     Constructed IP pseudo header.
+ * @param[out] headerlen  IP pseudo header length.
+ *
+ */
+int ip_get_route_req_remote(async_sess_t *sess, ip_protocol_t protocol,
     const struct sockaddr *destination, socklen_t addrlen,
     device_id_t *device_id, void **header, size_t *headerlen)
 {
-	if (!destination || (addrlen == 0))
+	if ((!destination) || (addrlen == 0))
 		return EINVAL;
 	
-	if (!device_id || !header || !headerlen)
+	if ((!device_id) || (!header) || (!headerlen))
 		return EBADMEM;
 	
 	*header = NULL;
 	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
 	ipc_call_t answer;
-	aid_t message_id = async_send_1(ip_phone, NET_IP_GET_ROUTE,
+	aid_t message_id = async_send_1(exch, NET_IP_GET_ROUTE,
 	    (sysarg_t) protocol, &answer);
 	
-	if ((async_data_write_start(ip_phone, destination, addrlen) == EOK) &&
-	    (async_data_read_start(ip_phone, headerlen,
-	    sizeof(*headerlen)) == EOK) && (*headerlen > 0)) {
+	if ((async_data_write_start(exch, destination, addrlen) == EOK) &&
+	    (async_data_read_start(exch, headerlen, sizeof(*headerlen)) == EOK) &&
+	    (*headerlen > 0)) {
 		*header = malloc(*headerlen);
 		if (*header) {
-			if (async_data_read_start(ip_phone, *header,
+			if (async_data_read_start(exch, *header,
 			    *headerlen) != EOK)
 				free(*header);
@@ -164,4 +171,6 @@
 	}
 	
+	async_exchange_end(exch);
+	
 	sysarg_t result;
 	async_wait_for(message_id, &result);
@@ -177,16 +186,18 @@
 /** Return the device packet dimension for sending.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[out] packet_dimension The packet dimension.
- * @return		EOK on success.
- * @return		ENOENT if there is no such device.
- * @return		Other error codes as defined for the
- *			generic_packet_size_req_remote() function.
- */
-int ip_packet_size_req_remote(int ip_phone, device_id_t device_id,
+ * @param[in] sess              IP module session.
+ * @param[in] device_id         Device identifier.
+ * @param[out] packet_dimension Packet dimension.
+ *
+ * @return EOK on success.
+ * @return ENOENT if there is no such device.
+ * @return Other error codes as defined for the
+ *         generic_packet_size_req_remote() function.
+ *
+ */
+int ip_packet_size_req_remote(async_sess_t *sess, device_id_t device_id,
     packet_dimension_t *packet_dimension)
 {
-	return generic_packet_size_req_remote(ip_phone, NET_IP_PACKET_SPACE,
+	return generic_packet_size_req_remote(sess, NET_IP_PACKET_SPACE,
 	    device_id, packet_dimension);
 }
@@ -194,17 +205,19 @@
 /** Notify the IP module about the received error notification packet.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The received packet or the received packet queue.
- * @param[in] target	The target internetwork module service to be
- *			delivered to.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- */
-int ip_received_error_msg_remote(int ip_phone, device_id_t device_id,
+ * @param[in] sess      IP module session.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
+ * @param[in] target    Target internetwork module service to be
+ *                      delivered to.
+ * @param[in] error     Packet error reporting service. Prefixes the
+ *                      received packet.
+ *
+ * @return EOK on success.
+ *
+ */
+int ip_received_error_msg_remote(async_sess_t *sess, device_id_t device_id,
     packet_t *packet, services_t target, services_t error)
 {
-	return generic_received_msg_remote(ip_phone, NET_IP_RECEIVED_ERROR,
+	return generic_received_msg_remote(sess, NET_IP_RECEIVED_ERROR,
 	    device_id, packet_get_id(packet), target, error);
 }
@@ -214,19 +227,21 @@
  * The packets may get fragmented if needed.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The packet fragments as a packet queue. All the
- *			packets have to have the same destination address.
- * @param[in] sender	The sending module service.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- * @return		Other error codes as defined for the generic_send_msg()
- *			function.
- */
-int ip_send_msg_remote(int ip_phone, device_id_t device_id, packet_t *packet,
-    services_t sender, services_t error)
-{
-	return generic_send_msg_remote(ip_phone, NET_IP_SEND, device_id,
+ * @param[in] sess      IP module session.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Packet fragments as a packet queue. All the
+ *                      packets have to have the same destination address.
+ * @param[in] sender    Sending module service.
+ * @param[in] error     Packet error reporting service. Prefixes the
+ *                      received packet.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for the generic_send_msg()
+ *         function.
+ *
+ */
+int ip_send_msg_remote(async_sess_t *sess, device_id_t device_id,
+    packet_t *packet, services_t sender, services_t error)
+{
+	return generic_send_msg_remote(sess, NET_IP_SEND, device_id,
 	    packet_get_id(packet), sender, error);
 }
@@ -236,13 +251,18 @@
  * This gateway is used if no other route is found.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[in] gateway	The default gateway.
- */
-int ip_set_gateway_req_remote(int ip_phone, device_id_t device_id,
+ * @param[in] sess      IP module session.
+ * @param[in] device_id Device identifier.
+ * @param[in] gateway   Default gateway.
+ *
+ */
+int ip_set_gateway_req_remote(async_sess_t *sess, device_id_t device_id,
     in_addr_t gateway)
 {
-	return (int) async_req_2_0(ip_phone, NET_IP_SET_GATEWAY,
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_2_0(exch, NET_IP_SET_GATEWAY,
 	    (sysarg_t) device_id, (sysarg_t) gateway.s_addr);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
Index: uspace/lib/net/include/adt/module_map.h
===================================================================
--- uspace/lib/net/include/adt/module_map.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/adt/module_map.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,5 @@
 
 #include <task.h>
-#include <ipc/services.h>
+#include <async.h>
 #include <net/modules.h>
 #include <adt/generic_char_map.h>
@@ -60,6 +60,6 @@
 	/** Module service identifier. */
 	services_t service;
-	/** Module phone if running and connected. */
-	int phone;
+	/** Module session if running and connected. */
+	async_sess_t *sess;
 	/** Usage counter. */
 	int usage;
Index: uspace/lib/net/include/arp_interface.h
===================================================================
--- uspace/lib/net/include/arp_interface.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/arp_interface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,9 +36,8 @@
 #include <adt/measured_strings.h>
 #include <task.h>
-
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <net/socket.h>
+#include <async.h>
 
 /** @name ARP module interface
@@ -47,13 +46,13 @@
 /*@{*/
 
-extern int arp_device_req(int, device_id_t, services_t, services_t,
+extern int arp_device_req(async_sess_t *, device_id_t, services_t, services_t,
     measured_string_t *);
-extern int arp_translate_req(int, device_id_t, services_t, measured_string_t *,
-    measured_string_t **, uint8_t **);
-extern int arp_clear_device_req(int, device_id_t);
-extern int arp_clear_address_req(int, device_id_t, services_t,
+extern int arp_translate_req(async_sess_t *, device_id_t, services_t,
+    measured_string_t *, measured_string_t **, uint8_t **);
+extern int arp_clear_device_req(async_sess_t *, device_id_t);
+extern int arp_clear_address_req(async_sess_t *, device_id_t, services_t,
     measured_string_t *);
-extern int arp_clean_cache_req(int);
-extern int arp_connect_module(services_t);
+extern int arp_clean_cache_req(async_sess_t *);
+extern async_sess_t *arp_connect_module(services_t);
 
 /*@}*/
Index: uspace/lib/net/include/generic.h
===================================================================
--- uspace/lib/net/include/generic.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/generic.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,24 +38,24 @@
 #define LIBNET_GENERIC_H_
 
-#include <async.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <adt/measured_strings.h>
 #include <net/packet.h>
+#include <async.h>
 
-extern int generic_device_state_msg_remote(int, int, device_id_t, int,
-    services_t);
-extern int generic_device_req_remote(int, int, device_id_t, int, services_t);
-extern int generic_get_addr_req(int, int, device_id_t, measured_string_t **,
-    uint8_t **);
-extern int generic_packet_size_req_remote(int, int, device_id_t,
+extern int generic_device_state_msg_remote(async_sess_t *, sysarg_t,
+    device_id_t, sysarg_t, services_t);
+extern int generic_device_req_remote(async_sess_t *, sysarg_t, device_id_t,
+    sysarg_t, services_t);
+extern int generic_get_addr_req(async_sess_t *, sysarg_t, device_id_t,
+    measured_string_t **, uint8_t **);
+extern int generic_packet_size_req_remote(async_sess_t *, sysarg_t, device_id_t,
     packet_dimension_t *);
-extern int generic_received_msg_remote(int, int, device_id_t, packet_id_t,
-    services_t, services_t);
-extern int generic_send_msg_remote(int, int, device_id_t, packet_id_t,
-    services_t, services_t);
-extern int generic_translate_req(int, int, device_id_t, services_t,
-    measured_string_t *, size_t, measured_string_t **, uint8_t **);
+extern int generic_received_msg_remote(async_sess_t *, sysarg_t, device_id_t,
+    packet_id_t, services_t, services_t);
+extern int generic_send_msg_remote(async_sess_t *, sysarg_t, device_id_t,
+    packet_id_t, services_t, services_t);
+extern int generic_translate_req(async_sess_t *, sysarg_t, device_id_t,
+    services_t, measured_string_t *, size_t, measured_string_t **, uint8_t **);
 
 #endif
Index: uspace/lib/net/include/icmp_remote.h
===================================================================
--- uspace/lib/net/include/icmp_remote.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/icmp_remote.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,5 +36,4 @@
 #include <net/socket_codes.h>
 #include <sys/types.h>
-
 #include <net/device.h>
 #include <adt/measured_strings.h>
@@ -44,4 +43,5 @@
 #include <net/icmp_codes.h>
 #include <net/icmp_common.h>
+#include <async.h>
 
 /** @name ICMP module interface
@@ -50,9 +50,9 @@
 /*@{*/
 
-extern int icmp_destination_unreachable_msg(int, icmp_code_t, icmp_param_t,
-    packet_t *);
-extern int icmp_source_quench_msg(int, packet_t *);
-extern int icmp_time_exceeded_msg(int, icmp_code_t, packet_t *);
-extern int icmp_parameter_problem_msg(int, icmp_code_t, icmp_param_t,
+extern int icmp_destination_unreachable_msg(async_sess_t *, icmp_code_t,
+    icmp_param_t, packet_t *);
+extern int icmp_source_quench_msg(async_sess_t *, packet_t *);
+extern int icmp_time_exceeded_msg(async_sess_t *, icmp_code_t, packet_t *);
+extern int icmp_parameter_problem_msg(async_sess_t *, icmp_code_t, icmp_param_t,
     packet_t *);
 
Index: uspace/lib/net/include/il_remote.h
===================================================================
--- uspace/lib/net/include/il_remote.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/il_remote.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -41,7 +41,7 @@
 #include <ipc/services.h>
 #include <sys/types.h>
-
 #include <net/device.h>
 #include <net/packet.h>
+#include <async.h>
 
 /** @name Internetwork layer module interface
@@ -50,7 +50,8 @@
 /*@{*/
 
-extern int il_device_state_msg(int, device_id_t, device_state_t, services_t);
-extern int il_received_msg(int, device_id_t, packet_t *, services_t);
-extern int il_mtu_changed_msg(int, device_id_t, size_t, services_t);
+extern int il_device_state_msg(async_sess_t *, device_id_t, device_state_t,
+    services_t);
+extern int il_received_msg(async_sess_t *, device_id_t, packet_t *, services_t);
+extern int il_mtu_changed_msg(async_sess_t *, device_id_t, size_t, services_t);
 
 /*@}*/
Index: uspace/lib/net/include/il_skel.h
===================================================================
--- uspace/lib/net/include/il_skel.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/il_skel.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,11 +39,9 @@
  */
 
-#include <async.h>
-#include <fibril_synch.h>
 #include <ipc/services.h>
-
 #include <adt/measured_strings.h>
 #include <net/device.h>
 #include <net/packet.h>
+#include <async.h>
 
 /** Module initialization.
@@ -51,5 +49,5 @@
  * This has to be implemented in user code.
  *
- * @param[in] net_phone Networking module phone.
+ * @param[in] sess Networking module session.
  *
  * @return EOK on success.
@@ -58,5 +56,5 @@
  *
  */
-extern int il_initialize(int net_phone);
+extern int il_initialize(async_sess_t *sess);
 
 /** Process the internetwork layer module message.
@@ -76,5 +74,5 @@
     ipc_call_t *answer, size_t *answer_count);
 
-extern int il_module_start(int);
+extern int il_module_start(sysarg_t);
 
 #endif
Index: uspace/lib/net/include/ip_header.h
===================================================================
--- uspace/lib/net/include/ip_header.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/ip_header.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -64,5 +64,5 @@
  */
 #define IP_FRAGMENT_OFFSET(header) \
-	((((header)->fragment_offset_high << 8) + \
+	(((GET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header) << 8) + \
 	    (header)->fragment_offset_low) * 8U)
 
@@ -83,5 +83,5 @@
  */
 #define IP_HEADER_LENGTH(header) \
-	((header)->header_length * 4U)
+	(GET_IP_HEADER_LENGTH(header) * 4U)
 
 /** Returns the actual IP packet total length.
@@ -143,11 +143,17 @@
  */
 struct ip_header {
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t version : 4;
-	uint8_t header_length : 4;
-#else
-	uint8_t header_length : 4;
-	uint8_t version : 4;
-#endif
+	uint8_t vhl; /* version, header_length */
+
+#define GET_IP_HEADER_VERSION(header) \
+	(((header)->vhl & 0xf0) >> 4)
+#define SET_IP_HEADER_VERSION(header, version) \
+	((header)->vhl = \
+	 ((version & 0x0f) << 4) | ((header)->vhl & 0x0f))
+
+#define GET_IP_HEADER_LENGTH(header) \
+	((header)->vhl & 0x0f)
+#define SET_IP_HEADER_LENGTH(header, length) \
+	((header)->vhl = \
+	 (length & 0x0f) | ((header)->vhl & 0xf0))
 
 	uint8_t tos;
@@ -155,11 +161,17 @@
 	uint16_t identification;
 
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t flags : 3;
-	uint8_t fragment_offset_high : 5;
-#else
-	uint8_t fragment_offset_high : 5;
-	uint8_t flags : 3;
-#endif
+	uint8_t ffoh; /* flags, fragment_offset_high */
+
+#define GET_IP_HEADER_FLAGS(header) \
+	(((header)->ffoh & 0xe0) >> 5)
+#define SET_IP_HEADER_FLAGS(header, flags) \
+	((header)->ffoh = \
+	 ((flags & 0x07) << 5) | ((header)->ffoh & 0x1f))
+
+#define GET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header) \
+	((header)->ffoh & 0x1f)
+#define SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, fragment_offset_high) \
+	((header)->ffoh = \
+	 (fragment_offset_high & 0x1f) | ((header)->ffoh & 0xe0))
 
 	uint8_t fragment_offset_low;
@@ -181,11 +193,18 @@
 	uint8_t pointer;
 
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t overflow : 4;
-	uint8_t flags : 4;
-#else
-	uint8_t flags : 4;
-	uint8_t overflow : 4;
-#endif
+	uint8_t of; /* overflow, flags */
+
+#define GET_IP_OPTION_OVERFLOW(option) \
+	(((option)->of & 0xf0) >> 4)
+#define SET_IP_OPTION_OVERFLOW(option, overflow) \
+	((option)->of = \
+	 ((overflow & 0x0f) << 4) | ((option)->of & 0x0f))
+
+#define GET_IP_OPTION_FLAGS(option) \
+	((option)->of & 0x0f)
+#define SET_IP_OPTION_FLAGS(option, flags) \
+	((option)->of = \
+	 (flags & 0x0f) | ((option)->of & 0xf0))
+
 } __attribute__ ((packed));
 
Index: uspace/lib/net/include/ip_interface.h
===================================================================
--- uspace/lib/net/include/ip_interface.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/ip_interface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,14 +35,11 @@
 
 #include <net/socket_codes.h>
-#include <async.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <net/packet.h>
-
 #include <net/in.h>
 #include <net/ip_codes.h>
-
 #include <ip_remote.h>
+#include <async.h>
 
 #define ip_received_error_msg  ip_received_error_msg_remote
@@ -61,18 +58,20 @@
 /** The transport layer notification function type definition.
  *
- * Notifies the transport layer modules about the received packet/s.
+ * Notify the transport layer modules about the received packet/s.
  *
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The received packet or the received packet queue.
- * @param[in] receiver	The receiving module service.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
+ * @param[in] receiver  Receiving module service.
+ * @param[in] error     Packet error reporting service. Prefixes the
+ *                      received packet.
+ *
+ * @return EOK on success.
+ *
  */
 typedef int (*tl_received_msg_t)(device_id_t device_id, packet_t *packet,
     services_t receiver, services_t error);
 
-extern int ip_bind_service(services_t, int, services_t, async_client_conn_t);
-extern int ip_connect_module(services_t);
+extern async_sess_t *ip_bind_service(services_t, int, services_t, async_client_conn_t);
+extern async_sess_t *ip_connect_module(services_t);
 
 /*@}*/
Index: uspace/lib/net/include/ip_remote.h
===================================================================
--- uspace/lib/net/include/ip_remote.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/ip_remote.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,5 +35,4 @@
 
 #include <ipc/services.h>
-
 #include <net/ip_codes.h>
 #include <net/inet.h>
@@ -42,16 +41,18 @@
 #include <net/device.h>
 #include <net/socket.h>
+#include <async.h>
 
-extern int ip_set_gateway_req_remote(int, device_id_t, in_addr_t);
-extern int ip_packet_size_req_remote(int, device_id_t, packet_dimension_t *);
-extern int ip_received_error_msg_remote(int, device_id_t, packet_t *, services_t,
-    services_t);
-extern int ip_device_req_remote(int, device_id_t, services_t);
-extern int ip_add_route_req_remote(int, device_id_t, in_addr_t, in_addr_t,
-    in_addr_t);
-extern int ip_send_msg_remote(int, device_id_t, packet_t *, services_t,
-    services_t);
-extern int ip_get_route_req_remote(int, ip_protocol_t, const struct sockaddr *,
-    socklen_t, device_id_t *, void **, size_t *);
+extern int ip_set_gateway_req_remote(async_sess_t *, device_id_t, in_addr_t);
+extern int ip_packet_size_req_remote(async_sess_t *, device_id_t,
+    packet_dimension_t *);
+extern int ip_received_error_msg_remote(async_sess_t *, device_id_t, packet_t *,
+    services_t, services_t);
+extern int ip_device_req_remote(async_sess_t *, device_id_t, services_t);
+extern int ip_add_route_req_remote(async_sess_t *, device_id_t, in_addr_t,
+    in_addr_t, in_addr_t);
+extern int ip_send_msg_remote(async_sess_t *, device_id_t, packet_t *,
+    services_t, services_t);
+extern int ip_get_route_req_remote(async_sess_t *, ip_protocol_t,
+    const struct sockaddr *, socklen_t, device_id_t *, void **, size_t *);
 
 #endif
Index: uspace/lib/net/include/net_interface.h
===================================================================
--- uspace/lib/net/include/net_interface.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/net_interface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #include <net/device.h>
 #include <adt/measured_strings.h>
+#include <async.h>
 
 /** @name Networking module interface
@@ -44,9 +45,10 @@
 /*@{*/
 
-extern int net_get_device_conf_req(int, device_id_t, measured_string_t **,
-    size_t, uint8_t **);
-extern int net_get_conf_req(int, measured_string_t **, size_t, uint8_t **);
+extern int net_get_device_conf_req(async_sess_t *, device_id_t,
+    measured_string_t **, size_t, uint8_t **);
+extern int net_get_conf_req(async_sess_t *, measured_string_t **, size_t,
+    uint8_t **);
 extern void net_free_settings(measured_string_t *, uint8_t *);
-extern int net_connect_module(void);
+extern async_sess_t *net_connect_module(void);
 
 /*@}*/
Index: uspace/lib/net/include/netif_remote.h
===================================================================
--- uspace/lib/net/include/netif_remote.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/netif_remote.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,19 +34,18 @@
 #define LIBNET_NETIF_REMOTE_H_
 
-#include <async.h>
 #include <ipc/services.h>
 #include <adt/measured_strings.h>
-
 #include <net/device.h>
 #include <net/packet.h>
+#include <async.h>
 
-extern int netif_get_addr_req(int, device_id_t, measured_string_t **,
+extern int netif_get_addr_req(async_sess_t *, device_id_t, measured_string_t **,
     uint8_t **);
-extern int netif_probe_req(int, device_id_t, int, void *);
-extern int netif_send_msg(int, device_id_t, packet_t *, services_t);
-extern int netif_start_req(int, device_id_t);
-extern int netif_stop_req(int, device_id_t);
-extern int netif_stats_req(int, device_id_t, device_stats_t *);
-extern int netif_bind_service(services_t, device_id_t, services_t,
+extern int netif_probe_req(async_sess_t *, device_id_t, int, void *);
+extern int netif_send_msg(async_sess_t *, device_id_t, packet_t *, services_t);
+extern int netif_start_req(async_sess_t *, device_id_t);
+extern int netif_stop_req(async_sess_t *, device_id_t);
+extern int netif_stats_req(async_sess_t *, device_id_t, device_stats_t *);
+extern async_sess_t *netif_bind_service(services_t, device_id_t, services_t,
     async_client_conn_t);
 
Index: uspace/lib/net/include/netif_skel.h
===================================================================
--- uspace/lib/net/include/netif_skel.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/netif_skel.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,18 +39,16 @@
 #define NET_NETIF_SKEL_H_
 
-#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
-
 #include <adt/measured_strings.h>
 #include <net/device.h>
 #include <net/packet.h>
+#include <async.h>
 
 /** Network interface device specific data. */
 typedef struct {
-	device_id_t device_id;  /**< Device identifier. */
-	int nil_phone;          /**< Receiving network interface layer phone. */
-	device_state_t state;   /**< Actual device state. */
-	void *specific;         /**< Driver specific data. */
+	device_id_t device_id;   /**< Device identifier. */
+	device_state_t state;    /**< Actual device state. */
+	void *specific;          /**< Driver specific data. */
 } netif_device_t;
 
@@ -65,5 +63,6 @@
 /** Network interface module skeleton global data. */
 typedef struct {
-	int net_phone;                  /**< Networking module phone. */
+	async_sess_t *sess;             /**< Networking module session. */
+	async_sess_t *nil_sess;         /**< Network interface layer session. */
 	netif_device_map_t device_map;  /**< Device map. */
 	fibril_rwlock_t lock;           /**< Safety lock. */
@@ -127,5 +126,4 @@
  * @return Other error codes as defined for the specific module
  *         message implementation.
- 
  *
  */
Index: uspace/lib/net/include/nil_remote.h
===================================================================
--- uspace/lib/net/include/nil_remote.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/nil_remote.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,29 +38,31 @@
 #include <net/packet.h>
 #include <generic.h>
+#include <async.h>
 
 #define nil_bind_service(service, device_id, me, receiver) \
 	bind_service(service, device_id, me, 0, receiver)
 
-#define nil_packet_size_req(nil_phone, device_id, packet_dimension) \
-	generic_packet_size_req_remote(nil_phone, NET_NIL_PACKET_SPACE, \
+#define nil_packet_size_req(sess, device_id, packet_dimension) \
+	generic_packet_size_req_remote(sess, NET_NIL_PACKET_SPACE, \
 	    device_id, packet_dimension)
 
-#define nil_get_addr_req(nil_phone, device_id, address, data) \
-	generic_get_addr_req(nil_phone, NET_NIL_ADDR, device_id, address, data)
+#define nil_get_addr_req(sess, device_id, address, data) \
+	generic_get_addr_req(sess, NET_NIL_ADDR, device_id, address, data)
 
-#define nil_get_broadcast_addr_req(nil_phone, device_id, address, data) \
-	generic_get_addr_req(nil_phone, NET_NIL_BROADCAST_ADDR, device_id, \
+#define nil_get_broadcast_addr_req(sess, device_id, address, data) \
+	generic_get_addr_req(sess, NET_NIL_BROADCAST_ADDR, device_id, \
 	    address, data)
 
-#define nil_send_msg(nil_phone, device_id, packet, sender) \
-	generic_send_msg_remote(nil_phone, NET_NIL_SEND, device_id, \
+#define nil_send_msg(sess, device_id, packet, sender) \
+	generic_send_msg_remote(sess, NET_NIL_SEND, device_id, \
 	    packet_get_id(packet), sender, 0)
 
-#define nil_device_req(nil_phone, device_id, mtu, netif_service) \
-	generic_device_req_remote(nil_phone, NET_NIL_DEVICE, device_id, mtu, \
+#define nil_device_req(sess, device_id, mtu, netif_service) \
+	generic_device_req_remote(sess, NET_NIL_DEVICE, device_id, mtu, \
 	    netif_service)
 
-extern int nil_device_state_msg(int, device_id_t, int);
-extern int nil_received_msg(int, device_id_t, packet_t *, services_t);
+extern int nil_device_state_msg(async_sess_t *, device_id_t, sysarg_t);
+extern int nil_received_msg(async_sess_t *, device_id_t, packet_t *,
+    services_t);
 
 #endif
Index: uspace/lib/net/include/nil_skel.h
===================================================================
--- uspace/lib/net/include/nil_skel.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/nil_skel.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,11 +39,9 @@
 #define LIBNET_NIL_SKEL_H_
 
-#include <async.h>
-#include <fibril_synch.h>
 #include <ipc/services.h>
-
 #include <adt/measured_strings.h>
 #include <net/device.h>
 #include <net/packet.h>
+#include <async.h>
 
 /** Module initialization.
@@ -51,5 +49,5 @@
  * This has to be implemented in user code.
  *
- * @param[in] net_phone Networking module phone.
+ * @param[in] sess Networking module session.
  *
  * @return EOK on success.
@@ -58,5 +56,5 @@
  *
  */
-extern int nil_initialize(int net_phone);
+extern int nil_initialize(async_sess_t *sess);
 
 /** Notify the network interface layer about the device state change.
@@ -64,5 +62,4 @@
  * This has to be implemented in user code.
  *
- * @param[in] nil_phone Network interface layer phone.
  * @param[in] device_id Device identifier.
  * @param[in] state     New device state.
@@ -73,5 +70,5 @@
  *
  */
-extern int nil_device_state_msg_local(int, device_id_t, int);
+extern int nil_device_state_msg_local(device_id_t device_id, sysarg_t state);
 
 /** Pass the packet queue to the network interface layer.
@@ -82,5 +79,4 @@
  * This has to be implemented in user code.
  *
- * @param[in] nil_phone Network interface layer phone.
  * @param[in] device_id Source device identifier.
  * @param[in] packet    Received packet or the received packet queue.
@@ -92,5 +88,6 @@
  *
  */
-extern int nil_received_msg_local(int, device_id_t, packet_t *, services_t);
+extern int nil_received_msg_local(device_id_t device_id, packet_t *packet,
+    services_t target);
 
 /** Message processing function.
@@ -98,5 +95,4 @@
  * This has to be implemented in user code.
  *
- * @param[in]  name   Module name.
  * @param[in]  callid Message identifier.
  * @param[in]  call   Message parameters.
@@ -112,8 +108,8 @@
  *
  */
-extern int nil_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    size_t *);
+extern int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
+    ipc_call_t *answer, size_t *count);
 
-extern int nil_module_start(int);
+extern int nil_module_start(sysarg_t);
 
 #endif
Index: uspace/lib/net/include/packet_client.h
===================================================================
--- uspace/lib/net/include/packet_client.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/packet_client.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -49,4 +49,5 @@
 
 #include <net/packet.h>
+#include <async.h>
 
 /** @name Packet client interface */
@@ -108,5 +109,5 @@
 extern int packet_get_addr(const packet_t *, uint8_t **, uint8_t **);
 extern int packet_set_addr(packet_t *, const uint8_t *, const uint8_t *, size_t);
-extern packet_t *packet_get_copy(int, packet_t *);
+extern packet_t *packet_get_copy(async_sess_t *, packet_t *);
 
 /*@}*/
Index: uspace/lib/net/include/packet_remote.h
===================================================================
--- uspace/lib/net/include/packet_remote.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/packet_remote.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,9 +36,11 @@
 #include <net/packet.h>
 #include <sys/types.h>
+#include <async.h>
 
-extern int packet_translate_remote(int, packet_t **, packet_id_t);
-extern packet_t *packet_get_4_remote(int, size_t, size_t, size_t, size_t);
-extern packet_t *packet_get_1_remote(int, size_t);
-extern void pq_release_remote(int, packet_id_t);
+extern int packet_translate_remote(async_sess_t *, packet_t **, packet_id_t);
+extern packet_t *packet_get_4_remote(async_sess_t *, size_t, size_t, size_t,
+    size_t);
+extern packet_t *packet_get_1_remote(async_sess_t *, size_t);
+extern void pq_release_remote(async_sess_t *, packet_id_t);
 
 #endif
Index: uspace/lib/net/include/socket_core.h
===================================================================
--- uspace/lib/net/include/socket_core.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/socket_core.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libnet 
+/** @addtogroup libnet
  *  @{
  */
@@ -45,19 +45,20 @@
 #include <net/device.h>
 #include <net/packet.h>
+#include <async.h>
 
 /** Initial size of the received packet queue. */
-#define SOCKET_INITIAL_RECEIVED_SIZE	4
+#define SOCKET_INITIAL_RECEIVED_SIZE  4
 
 /** Maximum size of the received packet queue. */
-#define SOCKET_MAX_RECEIVED_SIZE	0
+#define SOCKET_MAX_RECEIVED_SIZE  0
 
 /** Initial size of the sockets for acceptance queue. */
-#define SOCKET_INITIAL_ACCEPTED_SIZE	1
+#define SOCKET_INITIAL_ACCEPTED_SIZE  1
 
 /** Maximum size of the sockets for acceptance queue. */
-#define SOCKET_MAX_ACCEPTEDED_SIZE	0
+#define SOCKET_MAX_ACCEPTEDED_SIZE  0
 
 /** Listening sockets' port map key. */
-#define SOCKET_MAP_KEY_LISTENING	"L"
+#define SOCKET_MAP_KEY_LISTENING  "L"
 
 /** Type definition of the socket core.
@@ -75,6 +76,6 @@
 	/** Socket identifier. */
 	int socket_id;
-	/** Client application phone. */
-	int phone;
+	/** Client application session. */
+	async_sess_t *sess;
 	/** Bound port. */
 	int port;
@@ -108,13 +109,13 @@
 INT_MAP_DECLARE(socket_ports, socket_port_t);
 
-extern void socket_cores_release(int, socket_cores_t *, socket_ports_t *,
-    void (*)(socket_core_t *));
+extern void socket_cores_release(async_sess_t *, socket_cores_t *,
+    socket_ports_t *, void (*)(socket_core_t *));
 extern int socket_bind(socket_cores_t *, socket_ports_t *, int, void *, size_t,
     int, int, int);
 extern int socket_bind_free_port(socket_ports_t *, socket_core_t *, int, int,
     int);
-extern int socket_create(socket_cores_t *, int, void *, int *);
-extern int socket_destroy(int, int, socket_cores_t *, socket_ports_t *,
-    void (*)(socket_core_t *));
+extern int socket_create(socket_cores_t *, async_sess_t *, void *, int *);
+extern int socket_destroy(async_sess_t *, int, socket_cores_t *,
+    socket_ports_t *, void (*)(socket_core_t *));
 extern int socket_reply_packets(packet_t *, size_t *);
 extern socket_core_t *socket_port_find(socket_ports_t *, int, const uint8_t *,
Index: uspace/lib/net/include/tl_common.h
===================================================================
--- uspace/lib/net/include/tl_common.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/tl_common.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libnet 
+/** @addtogroup libnet
  * @{
  */
@@ -39,9 +39,9 @@
 
 #include <ipc/services.h>
-
 #include <net/socket_codes.h>
 #include <net/packet.h>
 #include <net/device.h>
 #include <net/inet.h>
+#include <async.h>
 
 /** Device packet dimensions.
@@ -51,5 +51,5 @@
 DEVICE_MAP_DECLARE(packet_dimensions, packet_dimension_t);
 
-extern int tl_get_ip_packet_dimension(int, packet_dimensions_t *,
+extern int tl_get_ip_packet_dimension(async_sess_t *, packet_dimensions_t *,
     device_id_t, packet_dimension_t **);
 extern int tl_get_address_port(const struct sockaddr *, int, uint16_t *);
@@ -57,6 +57,7 @@
     size_t);
 extern int tl_set_address_port(struct sockaddr *, int, uint16_t);
-extern int tl_prepare_icmp_packet(int, int, packet_t *, services_t);
-extern int tl_socket_read_packet_data(int, packet_t **, size_t,
+extern int tl_prepare_icmp_packet(async_sess_t *, async_sess_t *, packet_t *,
+    services_t);
+extern int tl_socket_read_packet_data(async_sess_t *, packet_t **, size_t,
     const packet_dimension_t *, const struct sockaddr *, socklen_t);
 
@@ -65,3 +66,2 @@
 /** @}
  */
-
Index: uspace/lib/net/include/tl_remote.h
===================================================================
--- uspace/lib/net/include/tl_remote.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/tl_remote.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,12 +38,11 @@
 #define LIBNET_TL_REMOTE_H_
 
-#include <async.h>
 #include <ipc/services.h>
 #include <ipc/tl.h>
-
 #include <generic.h>
 #include <net/device.h>
 #include <net/packet.h>
 #include <packet_client.h>
+#include <async.h>
 
 /** @name Transport layer module interface
@@ -52,5 +51,5 @@
 /*@{*/
 
-extern int tl_received_msg(int, device_id_t, packet_t *, services_t,
+extern int tl_received_msg(async_sess_t *, device_id_t, packet_t *, services_t,
     services_t);
 
Index: uspace/lib/net/include/tl_skel.h
===================================================================
--- uspace/lib/net/include/tl_skel.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/include/tl_skel.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,11 +39,10 @@
  */
 
-#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
-
 #include <adt/measured_strings.h>
 #include <net/device.h>
 #include <net/packet.h>
+#include <async.h>
 
 /** Module initialization.
@@ -51,5 +50,5 @@
  * This has to be implemented in user code.
  *
- * @param[in] net_phone Networking module phone.
+ * @param[in] sess Networking module session.
  *
  * @return EOK on success.
@@ -58,5 +57,5 @@
  *
  */
-extern int tl_initialize(int net_phone);
+extern int tl_initialize(async_sess_t *sess);
 
 /** Per-connection module initialization.
@@ -83,5 +82,5 @@
     ipc_call_t *, size_t *);
 
-extern int tl_module_start(int);
+extern int tl_module_start(sysarg_t);
 
 #endif
Index: uspace/lib/net/netif/netif_remote.c
===================================================================
--- uspace/lib/net/netif/netif_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/netif/netif_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,8 +38,6 @@
 #include <packet_client.h>
 #include <generic.h>
-
 #include <ipc/services.h>
 #include <ipc/netif.h>
-
 #include <net/modules.h>
 #include <adt/measured_strings.h>
@@ -49,8 +47,8 @@
 /** Return the device local hardware address.
  *
- * @param[in]  netif_phone Network interface phone.
- * @param[in]  device_id   Device identifier.
- * @param[out] address     Device local hardware address.
- * @param[out] data        Address data.
+ * @param[in]  sess      Network interface session.
+ * @param[in]  device_id Device identifier.
+ * @param[out] address   Device local hardware address.
+ * @param[out] data      Address data.
  *
  * @return EOK on success.
@@ -61,8 +59,8 @@
  *
  */
-int netif_get_addr_req(int netif_phone, device_id_t device_id,
+int netif_get_addr_req(async_sess_t *sess, device_id_t device_id,
     measured_string_t **address, uint8_t **data)
 {
-	return generic_get_addr_req(netif_phone, NET_NETIF_GET_ADDR, device_id,
+	return generic_get_addr_req(sess, NET_NETIF_GET_ADDR, device_id,
 	    address, data);
 }
@@ -70,8 +68,8 @@
 /** Probe the existence of the device.
  *
- * @param[in] netif_phone Network interface phone.
- * @param[in] device_id   Device identifier.
- * @param[in] irq         Device interrupt number.
- * @param[in] io          Device input/output address.
+ * @param[in] sess      Network interface session.
+ * @param[in] device_id Device identifier.
+ * @param[in] irq       Device interrupt number.
+ * @param[in] io        Device input/output address.
  *
  * @return EOK on success.
@@ -80,16 +78,20 @@
  *
  */
-int netif_probe_req(int netif_phone, device_id_t device_id, int irq, void *io)
+int netif_probe_req(async_sess_t *sess, device_id_t device_id, int irq, void *io)
 {
-	return async_req_3_0(netif_phone, NET_NETIF_PROBE, device_id, irq,
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_0(exch, NET_NETIF_PROBE, device_id, (sysarg_t) irq,
 	    (sysarg_t) io);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
 /** Send the packet queue.
  *
- * @param[in] netif_phone Network interface phone.
- * @param[in] device_id   Device identifier.
- * @param[in] packet      Packet queue.
- * @param[in] sender      Sending module service.
+ * @param[in] sess      Network interface session.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Packet queue.
+ * @param[in] sender    Sending module service.
  *
  * @return EOK on success.
@@ -98,8 +100,8 @@
  *
  */
-int netif_send_msg(int netif_phone, device_id_t device_id, packet_t *packet,
+int netif_send_msg(async_sess_t *sess, device_id_t device_id, packet_t *packet,
     services_t sender)
 {
-	return generic_send_msg_remote(netif_phone, NET_NETIF_SEND, device_id,
+	return generic_send_msg_remote(sess, NET_NETIF_SEND, device_id,
 	    packet_get_id(packet), sender, 0);
 }
@@ -107,6 +109,6 @@
 /** Start the device.
  *
- * @param[in] netif_phone Network interface phone.
- * @param[in] device_id   Device identifier.
+ * @param[in] sess      Network interface session.
+ * @param[in] device_id Device identifier.
  *
  * @return EOK on success.
@@ -117,13 +119,17 @@
  *
  */
-int netif_start_req(int netif_phone, device_id_t device_id)
+int netif_start_req(async_sess_t *sess, device_id_t device_id)
 {
-	return async_req_1_0(netif_phone, NET_NETIF_START, device_id);
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_1_0(exch, NET_NETIF_START, device_id);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
 /** Stop the device.
  *
- * @param[in] netif_phone Network interface phone.
- * @param[in] device_id   Device identifier.
+ * @param[in] sess      Network interface session.
+ * @param[in] device_id Device identifier.
  *
  * @return EOK on success.
@@ -134,19 +140,23 @@
  *
  */
-int netif_stop_req(int netif_phone, device_id_t device_id)
+int netif_stop_req(async_sess_t *sess, device_id_t device_id)
 {
-	return async_req_1_0(netif_phone, NET_NETIF_STOP, device_id);
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_1_0(exch, NET_NETIF_STOP, device_id);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
 /** Return the device usage statistics.
  *
- * @param[in] netif_phone Network interface phone.
- * @param[in] device_id   Device identifier.
- * @param[out] stats      Device usage statistics.
+ * @param[in]  sess      Network interface session.
+ * @param[in]  device_id Device identifier.
+ * @param[out] stats     Device usage statistics.
  *
  * @return EOK on success.
  *
  */
-int netif_stats_req(int netif_phone, device_id_t device_id,
+int netif_stats_req(async_sess_t *sess, device_id_t device_id,
     device_stats_t *stats)
 {
@@ -154,7 +164,9 @@
 		return EBADMEM;
 	
-	aid_t message_id = async_send_1(netif_phone, NET_NETIF_STATS,
+	async_exch_t *exch = async_exchange_begin(sess);
+	aid_t message_id = async_send_1(exch, NET_NETIF_STATS,
 	    (sysarg_t) device_id, NULL);
-	async_data_read_start(netif_phone, stats, sizeof(*stats));
+	async_data_read_start(exch, stats, sizeof(*stats));
+	async_exchange_end(exch);
 	
 	sysarg_t result;
@@ -169,16 +181,14 @@
  * register the message receiver.
  *
- * @param[in] service   The network interface module service.
- * @param[in] device_id The device identifier.
- * @param[in] me        The requesting module service.
- * @param[in] receiver  The message receiver.
+ * @param[in] service   Network interface module service.
+ * @param[in] device_id Device identifier.
+ * @param[in] me        Requesting module service.
+ * @param[in] receiver  Message receiver.
  *
- * @return The phone of the needed service.
- * @return EOK on success.
- * @return Other error codes as defined for the bind_service()
- *         function.
+ * @return Session to the needed service.
+ * @return NULL on failure.
  *
  */
-int netif_bind_service(services_t service, device_id_t device_id,
+async_sess_t *netif_bind_service(services_t service, device_id_t device_id,
     services_t me, async_client_conn_t receiver)
 {
Index: uspace/lib/net/netif/netif_skel.c
===================================================================
--- uspace/lib/net/netif/netif_skel.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/netif/netif_skel.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -61,5 +61,4 @@
 /** Probe the existence of the device.
  *
- * @param[in] netif_phone Network interface phone.
  * @param[in] device_id   Device identifier.
  * @param[in] irq         Device interrupt number.
@@ -71,6 +70,5 @@
  *
  */
-static int netif_probe_req_local(int netif_phone, device_id_t device_id,
-    int irq, void *io)
+static int netif_probe_req_local(device_id_t device_id, int irq, void *io)
 {
 	fibril_rwlock_write_lock(&netif_globals.lock);
@@ -83,5 +81,4 @@
 /** Send the packet queue.
  *
- * @param[in] netif_phone Network interface phone.
  * @param[in] device_id   Device identifier.
  * @param[in] packet      Packet queue.
@@ -93,6 +90,6 @@
  *
  */
-static int netif_send_msg_local(int netif_phone, device_id_t device_id,
-    packet_t *packet, services_t sender)
+static int netif_send_msg_local(device_id_t device_id, packet_t *packet,
+    services_t sender)
 {
 	fibril_rwlock_write_lock(&netif_globals.lock);
@@ -105,5 +102,4 @@
 /** Start the device.
  *
- * @param[in] netif_phone Network interface phone.
  * @param[in] device_id   Device identifier.
  *
@@ -115,5 +111,5 @@
  *
  */
-static int netif_start_req_local(int netif_phone, device_id_t device_id)
+static int netif_start_req_local(device_id_t device_id)
 {
 	fibril_rwlock_write_lock(&netif_globals.lock);
@@ -128,6 +124,5 @@
 	int result = netif_start_message(device);
 	if (result > NETIF_NULL) {
-		int phone = device->nil_phone;
-		nil_device_state_msg(phone, device_id, result);
+		nil_device_state_msg(netif_globals.nil_sess, device_id, result);
 		fibril_rwlock_write_unlock(&netif_globals.lock);
 		return EOK;
@@ -141,5 +136,4 @@
 /** Stop the device.
  *
- * @param[in] netif_phone Network interface phone.
  * @param[in] device_id   Device identifier.
  *
@@ -151,5 +145,5 @@
  *
  */
-static int netif_stop_req_local(int netif_phone, device_id_t device_id)
+static int netif_stop_req_local(device_id_t device_id)
 {
 	fibril_rwlock_write_lock(&netif_globals.lock);
@@ -164,6 +158,5 @@
 	int result = netif_stop_message(device);
 	if (result > NETIF_NULL) {
-		int phone = device->nil_phone;
-		nil_device_state_msg(phone, device_id, result);
+		nil_device_state_msg(netif_globals.nil_sess, device_id, result);
 		fibril_rwlock_write_unlock(&netif_globals.lock);
 		return EOK;
@@ -219,5 +212,5 @@
 void netif_pq_release(packet_id_t packet_id)
 {
-	pq_release_remote(netif_globals.net_phone, packet_id);
+	pq_release_remote(netif_globals.sess, packet_id);
 }
 
@@ -232,31 +225,29 @@
 packet_t *netif_packet_get_1(size_t content)
 {
-	return packet_get_1_remote(netif_globals.net_phone, content);
+	return packet_get_1_remote(netif_globals.sess, content);
 }
 
 /** Register the device notification receiver,
  *
- * Register a  network interface layer module as the device
+ * Register a network interface layer module as the device
  * notification receiver.
  *
- * @param[in] device_id Device identifier.
- * @param[in] phone     Network interface layer module phone.
- *
- * @return EOK on success.
- * @return ENOENT if there is no such device.
+ * @param[in] sess      Session to the network interface layer module.
+ *
+ * @return EOK on success.
  * @return ELIMIT if there is another module registered.
  *
  */
-static int register_message(device_id_t device_id, int phone)
-{
-	netif_device_t *device;
-	int rc = find_device(device_id, &device);
-	if (rc != EOK)
-		return rc;
-	
-	if (device->nil_phone >= 0)
+static int register_message(async_sess_t *sess)
+{
+	fibril_rwlock_write_lock(&netif_globals.lock);
+	if (netif_globals.nil_sess != NULL) {
+		fibril_rwlock_write_unlock(&netif_globals.lock);
 		return ELIMIT;
-	
-	device->nil_phone = phone;
+	}
+	
+	netif_globals.nil_sess = sess;
+	
+	fibril_rwlock_write_unlock(&netif_globals.lock);
 	return EOK;
 }
@@ -288,31 +279,28 @@
 	*count = 0;
 	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return register_message(callback);
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
 	case NET_NETIF_PROBE:
-		return netif_probe_req_local(0, IPC_GET_DEVICE(*call),
+		return netif_probe_req_local(IPC_GET_DEVICE(*call),
 		    NETIF_GET_IRQ(*call), NETIF_GET_IO(*call));
 	
-	case IPC_M_CONNECT_TO_ME:
-		fibril_rwlock_write_lock(&netif_globals.lock);
-		
-		rc = register_message(IPC_GET_DEVICE(*call), IPC_GET_PHONE(*call));
-		
-		fibril_rwlock_write_unlock(&netif_globals.lock);
-		return rc;
-	
 	case NET_NETIF_SEND:
-		rc = packet_translate_remote(netif_globals.net_phone, &packet,
+		rc = packet_translate_remote(netif_globals.sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
 		
-		return netif_send_msg_local(0, IPC_GET_DEVICE(*call), packet,
+		return netif_send_msg_local(IPC_GET_DEVICE(*call), packet,
 		    IPC_GET_SENDER(*call));
 	
 	case NET_NETIF_START:
-		return netif_start_req_local(0, IPC_GET_DEVICE(*call));
+		return netif_start_req_local(IPC_GET_DEVICE(*call));
 	
 	case NET_NETIF_STATS:
@@ -340,5 +328,5 @@
 	
 	case NET_NETIF_STOP:
-		return netif_stop_req_local(0, IPC_GET_DEVICE(*call));
+		return netif_stop_req_local(IPC_GET_DEVICE(*call));
 	
 	case NET_NETIF_GET_ADDR:
@@ -362,5 +350,6 @@
  *
  */
-static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	/*
@@ -385,6 +374,5 @@
 		
 		/* End if said to either by the message or the processing result */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
+		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
 			return;
 		
@@ -409,5 +397,6 @@
 	async_set_client_connection(netif_client_connection);
 	
-	netif_globals.net_phone = connect_to_service(SERVICE_NETWORKING);
+	netif_globals.sess = connect_to_service(SERVICE_NETWORKING);
+	netif_globals.nil_sess = NULL;
 	netif_device_map_initialize(&netif_globals.device_map);
 	
Index: uspace/lib/net/nil/nil_remote.c
===================================================================
--- uspace/lib/net/nil/nil_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/nil/nil_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,5 +45,5 @@
 /** Notify the network interface layer about the device state change.
  *
- * @param[in] nil_phone Network interface layer phone.
+ * @param[in] sess      Network interface layer session.
  * @param[in] device_id Device identifier.
  * @param[in] state     New device state.
@@ -54,7 +54,8 @@
  *
  */
-int nil_device_state_msg(int nil_phone, device_id_t device_id, int state)
+int nil_device_state_msg(async_sess_t *sess, device_id_t device_id,
+    sysarg_t state)
 {
-	return generic_device_state_msg_remote(nil_phone, NET_NIL_DEVICE_STATE,
+	return generic_device_state_msg_remote(sess, NET_NIL_DEVICE_STATE,
 	    device_id, state, 0);
 }
@@ -65,5 +66,5 @@
  * upper layers.
  *
- * @param[in] nil_phone Network interface layer phone.
+ * @param[in] sess      Network interface layer session.
  * @param[in] device_id Source device identifier.
  * @param[in] packet    Received packet or the received packet queue.
@@ -75,8 +76,8 @@
  *
  */
-int nil_received_msg(int nil_phone, device_id_t device_id,
+int nil_received_msg(async_sess_t *sess, device_id_t device_id,
     packet_t *packet, services_t target)
 {
-	return generic_received_msg_remote(nil_phone, NET_NIL_RECEIVED,
+	return generic_received_msg_remote(sess, NET_NIL_RECEIVED,
 	    device_id, packet_get_id(packet), target, 0);
 }
Index: uspace/lib/net/nil/nil_skel.c
===================================================================
--- uspace/lib/net/nil/nil_skel.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/nil/nil_skel.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #include <bool.h>
 #include <errno.h>
+#include <ns.h>
 #include <nil_skel.h>
 #include <net_interface.h>
@@ -48,5 +49,6 @@
  *
  */
-static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	/*
@@ -75,6 +77,5 @@
 		 * result.
 		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
+		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
 			return;
 		
@@ -96,14 +97,12 @@
  * @return Other error codes as defined for the nil_initialize()
  *         function.
- * @return Other error codes as defined for the REGISTER_ME() macro
- *         function.
  *
  */
-int nil_module_start(int service)
+int nil_module_start(sysarg_t service)
 {
 	async_set_client_connection(nil_client_connection);
-	int net_phone = net_connect_module();
-	if (net_phone < 0)
-		return net_phone;
+	async_sess_t *sess = net_connect_module();
+	if (!sess)
+		return ENOENT;
 	
 	int rc = pm_init();
@@ -111,9 +110,9 @@
 		return rc;
 	
-	rc = nil_initialize(net_phone);
+	rc = nil_initialize(sess);
 	if (rc != EOK)
 		goto out;
 	
-	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
+	rc = service_register(service);
 	if (rc != EOK)
 		goto out;
Index: uspace/lib/net/tl/icmp_client.c
===================================================================
--- uspace/lib/net/tl/icmp_client.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/tl/icmp_client.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -81,5 +81,5 @@
 		*mtu = header->un.frag.mtu;
 
-	// remove debug dump
+	/* Remove debug dump */
 #ifdef CONFIG_DEBUG
 	printf("ICMP error %d (%d) in packet %d\n", header->type, header->code,
Index: uspace/lib/net/tl/icmp_remote.c
===================================================================
--- uspace/lib/net/tl/icmp_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/tl/icmp_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,12 +39,11 @@
 #include <net/modules.h>
 #include <packet_client.h>
-
-#include <async.h>
-#include <errno.h>
 #include <ipc/services.h>
 #include <ipc/icmp.h>
 #include <sys/types.h>
+#include <async.h>
+#include <errno.h>
 
-/** Sends the Destination Unreachable error notification packet.
+/** Send the Destination Unreachable error notification packet.
  *
  * Beginning of the packet is sent as the notification packet data.
@@ -52,22 +51,26 @@
  * packet.
  *
- * @param[in] icmp_phone The ICMP module phone used for (semi)remote calls.
- * @param[in] code	The error specific code.
- * @param[in] mtu	The error MTU value.
- * @param[in] packet	The original packet.
- * @return		EOK on success.
- * @return		EPERM if the ICMP error notifications are disabled.
- * @return		ENOMEM if there is not enough memory left.
+ * @param[in] sess   ICMP module session.
+ * @param[in] code   Error specific code.
+ * @param[in] mtu    Error MTU value.
+ * @param[in] packet Original packet.
+ *
+ * @return EOK on success.
+ * @return EPERM if the ICMP error notifications are disabled.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
-int
-icmp_destination_unreachable_msg(int icmp_phone, icmp_code_t code,
+int icmp_destination_unreachable_msg(async_sess_t *sess, icmp_code_t code,
     icmp_param_t mtu, packet_t *packet)
 {
-	async_msg_3(icmp_phone, NET_ICMP_DEST_UNREACH, (sysarg_t) code,
+	async_exch_t *exch = async_exchange_begin(sess);
+	async_msg_3(exch, NET_ICMP_DEST_UNREACH, (sysarg_t) code,
 	    (sysarg_t) packet_get_id(packet), (sysarg_t) mtu);
+	async_exchange_end(exch);
+	
 	return EOK;
 }
 
-/** Sends the Source Quench error notification packet.
+/** Send the Source Quench error notification packet.
  *
  * Beginning of the packet is sent as the notification packet data.
@@ -75,18 +78,23 @@
  * packet.
  *
- * @param[in] icmp_phone The ICMP module phone used for (semi)remote calls.
- * @param[in] packet	The original packet.
- * @return		EOK on success.
- * @return		EPERM if the ICMP error notifications are disabled.
- * @return		ENOMEM if there is not enough memory left.
+ * @param[in] sess   ICMP module session.
+ * @param[in] packet Original packet.
+ *
+ * @return EOK on success.
+ * @return EPERM if the ICMP error notifications are disabled.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
-int icmp_source_quench_msg(int icmp_phone, packet_t *packet)
+int icmp_source_quench_msg(async_sess_t *sess, packet_t *packet)
 {
-	async_msg_2(icmp_phone, NET_ICMP_SOURCE_QUENCH, 0,
+	async_exch_t *exch = async_exchange_begin(sess);
+	async_msg_2(exch, NET_ICMP_SOURCE_QUENCH, 0,
 	    (sysarg_t) packet_get_id(packet));
+	async_exchange_end(exch);
+	
 	return EOK;
 }
 
-/** Sends the Time Exceeded error notification packet.
+/** Send the Time Exceeded error notification packet.
  *
  * Beginning of the packet is sent as the notification packet data.
@@ -94,19 +102,25 @@
  * packet.
  *
- * @param[in] icmp_phone The ICMP module phone used for (semi)remote calls.
- * @param[in] code	The error specific code.
- * @param[in] packet	The original packet.
- * @return		EOK on success.
- * @return		EPERM if the ICMP error notifications are disabled.
- * @return		ENOMEM if there is not enough memory left.
+ * @param[in] sess   ICMP module session.
+ * @param[in] code   Error specific code.
+ * @param[in] packet Original packet.
+ *
+ * @return EOK on success.
+ * @return EPERM if the ICMP error notifications are disabled.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
-int icmp_time_exceeded_msg(int icmp_phone, icmp_code_t code, packet_t *packet)
+int icmp_time_exceeded_msg(async_sess_t *sess, icmp_code_t code,
+    packet_t *packet)
 {
-	async_msg_2(icmp_phone, NET_ICMP_TIME_EXCEEDED, (sysarg_t) code,
+	async_exch_t *exch = async_exchange_begin(sess);
+	async_msg_2(exch, NET_ICMP_TIME_EXCEEDED, (sysarg_t) code,
 	    (sysarg_t) packet_get_id(packet));
+	async_exchange_end(exch);
+	
 	return EOK;
 }
 
-/** Sends the Parameter Problem error notification packet.
+/** Send the Parameter Problem error notification packet.
  *
  * Beginning of the packet is sent as the notification packet data.
@@ -114,17 +128,22 @@
  * packet.
  *
- * @param[in] icmp_phone The ICMP module phone used for (semi)remote calls.
- * @param[in] code	The error specific code.
- * @param[in] pointer	The problematic parameter offset.
- * @param[in] packet	The original packet.
- * @return		EOK on success.
- * @return		EPERM if the ICMP error notifications are disabled.
- * @return		ENOMEM if there is not enough memory left.
+ * @param[in] sess    ICMP module session.
+ * @param[in] code    Error specific code.
+ * @param[in] pointer Problematic parameter offset.
+ * @param[in] packet  Original packet.
+ *
+ * @return EOK on success.
+ * @return EPERM if the ICMP error notifications are disabled.
+ * @return ENOMEM if there is not enough memory left.
+ *
  */
-int icmp_parameter_problem_msg(int icmp_phone, icmp_code_t code,
+int icmp_parameter_problem_msg(async_sess_t *sess, icmp_code_t code,
     icmp_param_t pointer, packet_t *packet)
 {
-	async_msg_3(icmp_phone, NET_ICMP_PARAMETERPROB, (sysarg_t) code,
+	async_exch_t *exch = async_exchange_begin(sess);
+	async_msg_3(exch, NET_ICMP_PARAMETERPROB, (sysarg_t) code,
 	    (sysarg_t) packet_get_id(packet), (sysarg_t) pointer);
+	async_exchange_end(exch);
+	
 	return EOK;
 }
@@ -132,3 +151,2 @@
 /** @}
  */
-
Index: uspace/lib/net/tl/socket_core.c
===================================================================
--- uspace/lib/net/tl/socket_core.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/tl/socket_core.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,4 @@
 #include <packet_client.h>
 #include <packet_remote.h>
-
 #include <net/socket_codes.h>
 #include <net/in.h>
@@ -44,9 +43,7 @@
 #include <net/packet.h>
 #include <net/modules.h>
-
 #include <stdint.h>
 #include <stdlib.h>
 #include <errno.h>
-
 #include <adt/dynamic_fifo.h>
 #include <adt/int_map.h>
@@ -56,5 +53,5 @@
  * switching to the sequence.
  */
-#define SOCKET_ID_TRIES	100
+#define SOCKET_ID_TRIES  100
 
 /** Bound port sockets.*/
@@ -72,70 +69,68 @@
 INT_MAP_IMPLEMENT(socket_ports, socket_port_t);
 
-/** Destroys the socket.
+/** Destroy the socket.
  *
  * If the socket is bound, the port is released.
- * Releases all buffered packets, calls the release function and removes the
+ * Release all buffered packets, call the release function and remove the
  * socket from the local sockets.
  *
- * @param[in] packet_phone The packet server phone to release buffered packets.
- * @param[in] socket	The socket to be destroyed.
- * @param[in,out] local_sockets The local sockets to be updated.
- * @param[in,out] global_sockets The global sockets to be updated.
- * @param[in] socket_release The client release callback function.
- */
-static void
-socket_destroy_core(int packet_phone, socket_core_t *socket,
+ * @param[in]     sess           Packet server session.
+ * @param[in]     socket         Socket to be destroyed.
+ * @param[in,out] local_sockets  Local sockets to be updated.
+ * @param[in,out] global_sockets Global sockets to be updated.
+ * @param[in]     socket_release Client release callback function.
+ *
+ */
+static void socket_destroy_core(async_sess_t *sess, socket_core_t *socket,
     socket_cores_t *local_sockets, socket_ports_t *global_sockets,
     void (* socket_release)(socket_core_t *socket))
 {
+	/* If bound */
+	if (socket->port) {
+		/* Release the port */
+		socket_port_release(global_sockets, socket);
+	}
+	
+	/* Release all received packets */
 	int packet_id;
-
-	// if bound
-	if (socket->port) {
-		// release the port
-		socket_port_release(global_sockets, socket);
-	}
-	
-	// release all received packets
 	while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0)
-		pq_release_remote(packet_phone, packet_id);
-
+		pq_release_remote(sess, packet_id);
+	
 	dyn_fifo_destroy(&socket->received);
 	dyn_fifo_destroy(&socket->accepted);
-
+	
 	if (socket_release)
 		socket_release(socket);
-
-	socket_cores_exclude(local_sockets, socket->socket_id);
-}
-
-/** Destroys local sockets.
- *
- * Releases all buffered packets and calls the release function for each of the
+	
+	socket_cores_exclude(local_sockets, socket->socket_id, free);
+}
+
+/** Destroy local sockets.
+ *
+ * Release all buffered packets and call the release function for each of the
  * sockets.
  *
- * @param[in] packet_phone The packet server phone to release buffered packets.
- * @param[in] local_sockets The local sockets to be destroyed.
- * @param[in,out] global_sockets The global sockets to be updated.
- * @param[in] socket_release The client release callback function.
- */
-void
-socket_cores_release(int packet_phone, socket_cores_t *local_sockets,
+ * @param[in]     sess           Packet server session.
+ * @param[in]     local_sockets  Local sockets to be destroyed.
+ * @param[in,out] global_sockets Global sockets to be updated.
+ * @param[in]     socket_release Client release callback function.
+ *
+ */
+void socket_cores_release(async_sess_t *sess, socket_cores_t *local_sockets,
     socket_ports_t *global_sockets,
     void (* socket_release)(socket_core_t *socket))
 {
-	int index;
-
 	if (!socket_cores_is_valid(local_sockets))
 		return;
-
+	
 	local_sockets->magic = 0;
-
+	
+	int index;
 	for (index = 0; index < local_sockets->next; ++index) {
 		if (socket_cores_item_is_valid(&local_sockets->items[index])) {
 			local_sockets->items[index].magic = 0;
-
+			
 			if (local_sockets->items[index].value) {
-				socket_destroy_core(packet_phone,
+				socket_destroy_core(sess,
 				    local_sockets->items[index].value,
 				    local_sockets, global_sockets,
@@ -146,5 +141,5 @@
 		}
 	}
-
+	
 	free(local_sockets->items);
 }
@@ -166,5 +161,5 @@
 	int rc;
 
-	// create a wrapper
+	/* Create a wrapper */
 	socket_ref = malloc(sizeof(*socket_ref));
 	if (!socket_ref)
@@ -172,5 +167,5 @@
 
 	*socket_ref = socket;
-	// add the wrapper
+	/* Add the wrapper */
 	rc = socket_port_map_add(&socket_port->map, key, key_length,
 	    socket_ref);
@@ -206,5 +201,5 @@
 	int rc;
 
-	// create a wrapper
+	/* Create a wrapper */
 	socket_port = malloc(sizeof(*socket_port));
 	if (!socket_port)
@@ -221,5 +216,5 @@
 		goto fail;
 	
-	// register the incomming port
+	/* Register the incoming port */
 	rc = socket_ports_add(global_sockets, port, socket_port);
 	if (rc < 0)
@@ -230,5 +225,5 @@
 
 fail:
-	socket_port_map_destroy(&socket_port->map);
+	socket_port_map_destroy(&socket_port->map, free);
 	free(socket_port);
 	return rc;
@@ -277,25 +272,25 @@
 		
 		address_in = (struct sockaddr_in *) addr;
-		// find the socket
+		/* Find the socket */
 		socket = socket_cores_find(local_sockets, socket_id);
 		if (!socket)
 			return ENOTSOCK;
 		
-		// bind a free port?
+		/* Bind a free port? */
 		if (address_in->sin_port <= 0)
 			return socket_bind_free_port(global_sockets, socket,
 			     free_ports_start, free_ports_end, last_used_port);
 		
-		// try to find the port
+		/* Try to find the port */
 		socket_port = socket_ports_find(global_sockets,
 		    ntohs(address_in->sin_port));
 		if (socket_port) {
-			// already used
+			/* Already used */
 			return EADDRINUSE;
 		}
 		
-		// if bound
+		/* If bound */
 		if (socket->port) {
-			// release the port
+			/* Release the port */
 			socket_port_release(global_sockets, socket);
 		}
@@ -333,5 +328,5 @@
 	int index;
 
-	// from the last used one
+	/* From the last used one */
 	index = last_used_port;
 	
@@ -339,18 +334,18 @@
 		++index;
 		
-		// til the range end
+		/* Till the range end */
 		if (index >= free_ports_end) {
-			// start from the range beginning
+			/* Start from the range beginning */
 			index = free_ports_start - 1;
 			do {
 				++index;
-				// til the last used one
+				/* Till the last used one */
 				if (index >= last_used_port) {
-					// none found
+					/* None found */
 					return ENOTCONN;
 				}
 			} while (socket_ports_find(global_sockets, index));
 			
-			// found, break immediately
+			/* Found, break immediately */
 			break;
 		}
@@ -376,5 +371,7 @@
 
 	count = 0;
-//	socket_id = socket_globals.last_id;
+#if 0
+	socket_id = socket_globals.last_id;
+#endif
 	do {
 		if (count < SOCKET_ID_TRIES) {
@@ -384,12 +381,14 @@
 			socket_id = 1;
 			++count;
-		// only this branch for last_id
+		/* Only this branch for last_id */
 		} else {
 			if (socket_id < INT_MAX) {
 				++ socket_id;
-/*			} else if(socket_globals.last_id) {
-*				socket_globals.last_id = 0;
-*				socket_id = 1;
-*/			} else {
+#if 0
+			} else if(socket_globals.last_id) {
+				socket_globals.last_id = 0;
+				socket_id = 1;
+#endif
+			} else {
 				return ELIMIT;
 			}
@@ -402,18 +401,20 @@
 }
 
-/** Creates a new socket.
- *
- * @param[in,out] local_sockets The local sockets to be updated.
- * @param[in] app_phone	The application phone.
- * @param[in] specific_data The socket specific data.
- * @param[in,out] socket_id The new socket identifier. A new identifier is
- *			chosen if set to zero or negative. A negative identifier
- *			is chosen if set to negative.
- * @return		EOK on success.
- * @return		EINVAL if the socket_id parameter is NULL.
- * @return		ENOMEM if there is not enough memory left.
- */
-int
-socket_create(socket_cores_t *local_sockets, int app_phone,
+/** Create a new socket.
+ *
+ * @param[in,out] local_sockets Local sockets to be updated.
+ * @param[in]     sess          Application session.
+ * @param[in]     specific_data Socket specific data.
+ * @param[in,out] socket_id     New socket identifier. A new identifier
+ *                              is chosen if set to zero or negative.
+ *                              A negative identifier is chosen if set
+ *                              to negative.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the socket_id parameter is NULL.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+int socket_create(socket_cores_t *local_sockets, async_sess_t* sess,
     void *specific_data, int *socket_id)
 {
@@ -425,5 +426,5 @@
 		return EINVAL;
 	
-	// store the socket
+	/* Store the socket */
 	if (*socket_id <= 0) {
 		positive = (*socket_id == 0);
@@ -441,6 +442,6 @@
 		return ENOMEM;
 	
-	// initialize
-	socket->phone = app_phone;
+	/* Initialize */
+	socket->sess = sess;
 	socket->port = -1;
 	socket->key = NULL;
@@ -471,37 +472,37 @@
 }
 
-/** Destroys the socket.
+/** Destroy the socket.
  *
  * If the socket is bound, the port is released.
- * Releases all buffered packets, calls the release function and removes the
+ * Release all buffered packets, call the release function and remove the
  * socket from the local sockets.
  *
- * @param[in] packet_phone The packet server phone to release buffered packets.
- * @param[in] socket_id	The socket identifier.
- * @param[in,out] local_sockets The local sockets to be updated.
- * @param[in,out] global_sockets The global sockets to be updated.
- * @param[in] socket_release The client release callback function.
- * @return		EOK on success.
- * @return		ENOTSOCK if the socket is not found.
+ * @param[in]     sess           Packet server session.
+ * @param[in]     socket_id      Socket identifier.
+ * @param[in,out] local_sockets  Local sockets to be updated.
+ * @param[in,out] global_sockets Global sockets to be updated.
+ * @param[in]     socket_release Client release callback function.
+ *
+ * @return EOK on success.
+ * @return ENOTSOCK if the socket is not found.
+ *
  */
 int
-socket_destroy(int packet_phone, int socket_id, socket_cores_t *local_sockets,
+socket_destroy(async_sess_t *sess, int socket_id, socket_cores_t *local_sockets,
     socket_ports_t *global_sockets,
     void (*socket_release)(socket_core_t *socket))
 {
-	socket_core_t *socket;
-	int accepted_id;
-
-	// find the socket
-	socket = socket_cores_find(local_sockets, socket_id);
+	/* Find the socket */
+	socket_core_t *socket = socket_cores_find(local_sockets, socket_id);
 	if (!socket)
 		return ENOTSOCK;
 	
-	// destroy all accepted sockets
+	/* Destroy all accepted sockets */
+	int accepted_id;
 	while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0)
-		socket_destroy(packet_phone, accepted_id, local_sockets,
+		socket_destroy(sess, accepted_id, local_sockets,
 		    global_sockets, socket_release);
 	
-	socket_destroy_core(packet_phone, socket, local_sockets, global_sockets,
+	socket_destroy_core(sess, socket, local_sockets, global_sockets,
 	    socket_release);
 	
@@ -535,13 +536,13 @@
 	next_packet = pq_next(packet);
 	if (!next_packet) {
-		// write all if only one fragment
+		/* Write all if only one fragment */
 		rc = data_reply(packet_get_data(packet),
 		    packet_get_data_length(packet));
 		if (rc != EOK)
 			return rc;
-		// store the total length
+		/* Store the total length */
 		*length = packet_get_data_length(packet);
 	} else {
-		// count the packet fragments
+		/* Count the packet fragments */
 		fragments = 1;
 		next_packet = pq_next(packet);
@@ -549,5 +550,5 @@
 			++fragments;
 		
-		// compute and store the fragment lengths
+		/* Compute and store the fragment lengths */
 		lengths = (size_t *) malloc(sizeof(size_t) * fragments +
 		    sizeof(size_t));
@@ -565,5 +566,5 @@
 		}
 		
-		// write the fragment lengths
+		/* Write the fragment lengths */
 		rc = data_reply(lengths, sizeof(int) * (fragments + 1));
 		if (rc != EOK) {
@@ -573,5 +574,5 @@
 		next_packet = packet;
 		
-		// write the fragments
+		/* Write the fragments */
 		for (index = 0; index < fragments; ++index) {
 			rc = data_reply(packet_get_data(next_packet),
@@ -584,5 +585,5 @@
 		}
 		
-		// store the total length
+		/* Store the total length */
 		*length = lengths[fragments];
 		free(lengths);
@@ -636,8 +637,8 @@
 		return;
 	
-	// find ports
+	/* Find ports */
 	socket_port = socket_ports_find(global_sockets, socket->port);
 	if (socket_port) {
-		// find the socket
+		/* Find the socket */
 		socket_ref = socket_port_map_find(&socket_port->map,
 		    socket->key, socket->key_length);
@@ -646,15 +647,15 @@
 			--socket_port->count;
 			
-			// release if empty
+			/* Release if empty */
 			if (socket_port->count <= 0) {
-				// destroy the map
-				socket_port_map_destroy(&socket_port->map);
-				// release the port
+				/* Destroy the map */
+				socket_port_map_destroy(&socket_port->map, free);
+				/* Release the port */
 				socket_ports_exclude(global_sockets,
-				    socket->port);
+				    socket->port, free);
 			} else {
-				// remove
+				/* Remove */
 				socket_port_map_exclude(&socket_port->map,
-				    socket->key, socket->key_length);
+				    socket->key, socket->key_length, free);
 			}
 		}
@@ -685,10 +686,10 @@
 	int rc;
 
-	// find ports
+	/* Find ports */
 	socket_port = socket_ports_find(global_sockets, port);
 	if (!socket_port)
 		return ENOENT;
 	
-	// add the socket
+	/* Add the socket */
 	rc = socket_port_add_core(socket_port, socket, key, key_length);
 	if (rc != EOK)
Index: uspace/lib/net/tl/tl_common.c
===================================================================
--- uspace/lib/net/tl/tl_common.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/tl/tl_common.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,5 +43,4 @@
 #include <ip_interface.h>
 #include <tl_remote.h>
-
 #include <net/socket_codes.h>
 #include <net/in.h>
@@ -50,5 +49,4 @@
 #include <net/device.h>
 #include <net/packet.h>
-
 #include <async.h>
 #include <ipc/services.h>
@@ -107,22 +105,21 @@
  * The reply is cached then.
  *
- * @param[in] ip_phone	The IP moduel phone for (semi)remote calls.
- * @param[in] packet_dimensions The packet dimensions cache.
- * @param[in] device_id	The device identifier.
- * @param[out] packet_dimension The IP packet dimensions.
- * @return		EOK on success.
- * @return		EBADMEM if the packet_dimension parameter is NULL.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EINVAL if the packet_dimensions cache is not valid.
- * @return		Other codes as defined for the ip_packet_size_req()
- *			function.
- */
-int
-tl_get_ip_packet_dimension(int ip_phone,
+ * @param[in]  sess              IP module session.
+ * @param[in]  packet_dimensions Packet dimensions cache.
+ * @param[in]  device_id         Device identifier.
+ * @param[out] packet_dimension  IP packet dimensions.
+ *
+ * @return EOK on success.
+ * @return EBADMEM if the packet_dimension parameter is NULL.
+ * @return ENOMEM if there is not enough memory left.
+ * @return EINVAL if the packet_dimensions cache is not valid.
+ * @return Other codes as defined for the ip_packet_size_req()
+ *         function.
+ *
+ */
+int tl_get_ip_packet_dimension(async_sess_t *sess,
     packet_dimensions_t *packet_dimensions, device_id_t device_id,
     packet_dimension_t **packet_dimension)
 {
-	int rc;
-	
 	if (!packet_dimension)
 		return EBADMEM;
@@ -133,8 +130,8 @@
 		/* Ask for and remember them if not found */
 		*packet_dimension = malloc(sizeof(**packet_dimension));
-		if(!*packet_dimension)
+		if (!*packet_dimension)
 			return ENOMEM;
 		
-		rc = ip_packet_size_req(ip_phone, device_id, *packet_dimension);
+		int rc = ip_packet_size_req(sess, device_id, *packet_dimension);
 		if (rc != EOK) {
 			free(*packet_dimension);
@@ -182,5 +179,5 @@
 			else
 				packet_dimensions_exclude(packet_dimensions,
-				    DEVICE_INVALID_ID);
+				    DEVICE_INVALID_ID, free);
 		}
 	}
@@ -236,37 +233,37 @@
 /** Prepares the packet for ICMP error notification.
  *
- * Keeps the first packet and releases all the others.
- * Releases all the packets on error.
- *
- * @param[in] packet_phone The packet server module phone.
- * @param[in] icmp_phone The ICMP module phone.
- * @param[in] packet	The packet to be send.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- * @return		ENOENT if no packet may be sent.
- */
-int
-tl_prepare_icmp_packet(int packet_phone, int icmp_phone, packet_t *packet,
-    services_t error)
-{
-	packet_t *next;
+ * Keep the first packet and release all the others.
+ * Release all the packets on error.
+ *
+ * @param[in] packet_sess Packet server module session.
+ * @param[in] icmp_sess   ICMP module phone.
+ * @param[in] packet      Packet to be send.
+ * @param[in] error       Packet error reporting service. Prefixes the
+ *                        received packet.
+ *
+ * @return EOK on success.
+ * @return ENOENT if no packet may be sent.
+ *
+ */
+int tl_prepare_icmp_packet(async_sess_t *packet_sess, async_sess_t *icmp_sess,
+    packet_t *packet, services_t error)
+{
+	/* Detach the first packet and release the others */
+	packet_t *next = pq_detach(packet);
+	if (next)
+		pq_release_remote(packet_sess, packet_get_id(next));
+	
 	uint8_t *src;
-	int length;
-
-	// detach the first packet and release the others
-	next = pq_detach(packet);
-	if (next)
-		pq_release_remote(packet_phone, packet_get_id(next));
-	
-	length = packet_get_addr(packet, &src, NULL);
-	if ((length > 0) && (!error) && (icmp_phone >= 0) &&
-	    // set both addresses to the source one (avoids the source address
-	    // deletion before setting the destination one)
+	int length = packet_get_addr(packet, &src, NULL);
+	if ((length > 0) && (!error) && (icmp_sess) &&
+	    /*
+	     * Set both addresses to the source one (avoids the source address
+	     * deletion before setting the destination one)
+	     */
 	    (packet_set_addr(packet, src, src, (size_t) length) == EOK)) {
 		return EOK;
 	} else
-		pq_release_remote(packet_phone, packet_get_id(packet));
-
+		pq_release_remote(packet_sess, packet_get_id(packet));
+	
 	return ENOENT;
 }
@@ -274,20 +271,21 @@
 /** Receives data from the socket into a packet.
  *
- * @param[in] packet_phone The packet server module phone.
- * @param[out] packet	The new created packet.
- * @param[in] prefix	Reserved packet data prefix length.
- * @param[in] dimension	The packet dimension.
- * @param[in] addr	The destination address.
- * @param[in] addrlen	The address length.
- * @return		Number of bytes received.
- * @return		EINVAL if the client does not send data.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			async_data_read_finalize() function.
- */
-int
-tl_socket_read_packet_data(int packet_phone, packet_t **packet, size_t prefix,
-    const packet_dimension_t *dimension, const struct sockaddr *addr,
-    socklen_t addrlen)
+ * @param[in]  sess      Packet server module session.
+ * @param[out] packet    New created packet.
+ * @param[in]  prefix    Reserved packet data prefix length.
+ * @param[in]  dimension Packet dimension.
+ * @param[in]  addr      Destination address.
+ * @param[in]  addrlen   Address length.
+ *
+ * @return Number of bytes received.
+ * @return EINVAL if the client does not send data.
+ * @return ENOMEM if there is not enough memory left.
+ * @return Other error codes as defined for the
+ *         async_data_read_finalize() function.
+ *
+ */
+int tl_socket_read_packet_data(async_sess_t *sess, packet_t **packet,
+    size_t prefix, const packet_dimension_t *dimension,
+    const struct sockaddr *addr, socklen_t addrlen)
 {
 	ipc_callid_t callid;
@@ -299,32 +297,32 @@
 		return EINVAL;
 
-	// get the data length
+	/* Get the data length */
 	if (!async_data_write_receive(&callid, &length))
 		return EINVAL;
 
-	// get a new packet
-	*packet = packet_get_4_remote(packet_phone, length, dimension->addr_len,
+	/* Get a new packet */
+	*packet = packet_get_4_remote(sess, length, dimension->addr_len,
 	    prefix + dimension->prefix, dimension->suffix);
 	if (!packet)
 		return ENOMEM;
 
-	// allocate space in the packet
+	/* Allocate space in the packet */
 	data = packet_suffix(*packet, length);
 	if (!data) {
-		pq_release_remote(packet_phone, packet_get_id(*packet));
+		pq_release_remote(sess, packet_get_id(*packet));
 		return ENOMEM;
 	}
 
-	// read the data into the packet
+	/* Read the data into the packet */
 	rc = async_data_write_finalize(callid, data, length);
 	if (rc != EOK) {
-		pq_release_remote(packet_phone, packet_get_id(*packet));
+		pq_release_remote(sess, packet_get_id(*packet));
 		return rc;
 	}
 	
-	// set the packet destination address
+	/* Set the packet destination address */
 	rc = packet_set_addr(*packet, NULL, (uint8_t *) addr, addrlen);
 	if (rc != EOK) {
-		pq_release_remote(packet_phone, packet_get_id(*packet));
+		pq_release_remote(sess, packet_get_id(*packet));
 		return rc;
 	}
Index: uspace/lib/net/tl/tl_remote.c
===================================================================
--- uspace/lib/net/tl/tl_remote.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/tl/tl_remote.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,22 +34,21 @@
 #include <generic.h>
 #include <packet_client.h>
-
 #include <ipc/services.h>
 #include <ipc/tl.h>
-
 #include <net/device.h>
 #include <net/packet.h>
+#include <async.h>
 
 /** Notify the remote transport layer modules about the received packet/s.
  *
- * @param[in] tl_phone  The transport layer module phone used for remote calls.
- * @param[in] device_id The device identifier.
- * @param[in] packet    The received packet or the received packet queue.
+ * @param[in] sess      Transport layer module session.
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
  *                      The packet queue is used to carry a fragmented
  *                      datagram. The first packet contains the headers,
  *                      the others contain only data.
- * @param[in] target    The target transport layer module service to be
+ * @param[in] target    Target transport layer module service to be
  *                      delivered to.
- * @param[in] error     The packet error reporting service. Prefixes the
+ * @param[in] error     Packet error reporting service. Prefixes the
  *                      received packet.
  *
@@ -57,8 +56,8 @@
  *
  */
-int tl_received_msg(int tl_phone, device_id_t device_id, packet_t *packet,
+int tl_received_msg(async_sess_t *sess, device_id_t device_id, packet_t *packet,
     services_t target, services_t error)
 {
-	return generic_received_msg_remote(tl_phone, NET_TL_RECEIVED, device_id,
+	return generic_received_msg_remote(sess, NET_TL_RECEIVED, device_id,
 	    packet_get_id(packet), target, error);
 }
Index: uspace/lib/net/tl/tl_skel.c
===================================================================
--- uspace/lib/net/tl/tl_skel.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/net/tl/tl_skel.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #include <bool.h>
 #include <errno.h>
+#include <ns.h>
 #include <tl_skel.h>
 #include <net_interface.h>
@@ -46,7 +47,9 @@
  * @param[in] iid   The initial message identifier.
  * @param[in] icall The initial message call structure.
+ * @param[in] arg   Local argument.
  *
  */
-static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	/*
@@ -77,6 +80,5 @@
 		 * result.
 		 */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
-		    (res == EHANGUP))
+		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
 			return;
 		
@@ -102,10 +104,10 @@
  *
  */
-int tl_module_start(int service)
+int tl_module_start(sysarg_t service)
 {
 	async_set_client_connection(tl_client_connection);
-	int net_phone = net_connect_module();
-	if (net_phone < 0)
-		return net_phone;
+	async_sess_t *sess = net_connect_module();
+	if (!sess)
+		return ENOENT;
 	
 	int rc = pm_init();
@@ -113,9 +115,9 @@
 		return rc;
 	
-	rc = tl_initialize(net_phone);
+	rc = tl_initialize(sess);
 	if (rc != EOK)
 		goto out;
 	
-	rc = async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
+	rc = service_register(service);
 	if (rc != EOK)
 		goto out;
Index: uspace/lib/packet/generic/packet_server.c
===================================================================
--- uspace/lib/packet/generic/packet_server.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/packet/generic/packet_server.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,5 +36,4 @@
 
 #include <packet_server.h>
-
 #include <align.h>
 #include <assert.h>
@@ -112,9 +111,9 @@
     size_t max_content, size_t max_suffix)
 {
-	// clear the packet content
+	/* Clear the packet content */
 	bzero(((void *) packet) + sizeof(packet_t),
 	    packet->length - sizeof(packet_t));
 	
-	// clear the packet header
+	/* Clear the packet header */
 	packet->order = 0;
 	packet->metric = 0;
@@ -151,5 +150,5 @@
 	assert(fibril_mutex_is_locked(&ps_globals.lock));
 
-	// already locked
+	/* Already locked */
 	packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
 	    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
@@ -317,15 +316,14 @@
  *			packet_release_wrapper() function.
  */
-int
-packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
+int packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     size_t *answer_count)
 {
 	packet_t *packet;
-
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
 	*answer_count = 0;
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
 	case NET_PACKET_CREATE_1:
 		packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX,
Index: uspace/lib/scsi/Makefile
===================================================================
--- uspace/lib/scsi/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/scsi/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2011 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+EXTRA_CFLAGS = -Iinclude
+LIBRARY = libscsi
+
+SOURCES = \
+	src/spc.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/scsi/include/scsi/sbc.h
===================================================================
--- uspace/lib/scsi/include/scsi/sbc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/scsi/include/scsi/sbc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libscsi
+ * @{
+ */
+/**
+ * @file SCSI Block Commands.
+ */
+
+#ifndef LIBSCSI_SBC_H_
+#define LIBSCSI_SBC_H_
+
+#include <stdint.h>
+
+/** SCSI command codes defined in SCSI-SBC */
+enum scsi_cmd_sbc {
+	SCSI_CMD_READ_6			= 0x08,
+	SCSI_CMD_READ_10		= 0x28,
+	SCSI_CMD_READ_12		= 0xa8,
+	SCSI_CMD_READ_16		= 0x88,
+	SCSI_CMD_READ_32		= 0x7f,
+
+	SCSI_CMD_READ_CAPACITY_10	= 0x25,
+	SCSI_CMD_READ_CAPACITY_16	= 0x9e,
+
+	SCSI_CMD_WRITE_6		= 0x0a,
+	SCSI_CMD_WRITE_10		= 0x2a,
+	SCSI_CMD_WRITE_12		= 0xaa,
+	SCSI_CMD_WRITE_16		= 0x8a
+};
+
+/** SCSI Read (10) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_READ_10) */
+	uint8_t op_code;
+	/** RdProtect, DPO, FUA, Reserved, FUA_NV, Obsolete */
+	uint8_t flags;
+	/** Logical block address */
+	uint32_t lba;
+	/** Reserved, Group Number */
+	uint8_t group_no;
+	/** Transfer length */
+	uint16_t xfer_len;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_read_10_t;
+
+/** SCSI Read (12) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_READ_12) */
+	uint8_t op_code;
+	/** RdProtect, DPO, FUA, Reserved, FUA_NV, Obsolete */
+	uint8_t flags;
+	/** Logical block address */
+	uint32_t lba;
+	/** Transfer length */
+	uint32_t xfer_len;
+	/** Reserved, Group Number */
+	uint8_t group_no;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_read_12_t;
+
+/** SCSI Read (16) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_READ_16) */
+	uint8_t op_code;
+	/** RdProtect, DPO, FUA, Reserved, FUA_NV, Reserved */
+	uint8_t flags;
+	/** Logical block address */
+	uint64_t lba;
+	/** Transfer length */
+	uint32_t xfer_len;
+	/** Reserved, Group Number */
+	uint8_t group_no;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_read_16_t;
+
+/** SCSI Read Capacity (10) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_READ_CAPACITY_10) */
+	uint8_t op_code;
+	/** Reserved, Obsolete */
+	uint8_t reserved_1;
+	/** Logical block address */
+	uint32_t lba;
+	/** Reserved */
+	uint32_t reserved_6;
+	/** Reserved, PM */
+	uint8_t pm;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_read_capacity_10_t;
+
+/** Read Capacity (10) parameter data.
+ *
+ * Returned for Read Capacity (10) command.
+ */
+typedef struct {
+	/** Logical address of last block */
+	uint32_t last_lba;
+	/** Size of block in bytes */
+	uint32_t block_size;
+} scsi_read_capacity_10_data_t;
+
+/** SCSI Write (10) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_WRITE_10) */
+	uint8_t op_code;
+	/** WrProtect, DPO, FUA, Reserved, FUA_NV, Obsolete */
+	uint8_t flags;
+	/** Logical block address */
+	uint32_t lba;
+	/** Reserved, Group Number */
+	uint8_t group_no;
+	/** Transfer length */
+	uint16_t xfer_len;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_write_10_t;
+
+/** SCSI Write (12) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_WRITE_12) */
+	uint8_t op_code;
+	/** WrProtect, DPO, FUA, Reserved, FUA_NV, Obsolete */
+	uint8_t flags;
+	/** Logical block address */
+	uint32_t lba;
+	/** Transfer length */
+	uint32_t xfer_len;
+	/** Reserved, Group Number */
+	uint8_t group_no;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_write_12_t;
+
+/** SCSI Write (16) command */
+typedef struct {
+	/** Operation code (SCSI_CMD_WRITE_16) */
+	uint8_t op_code;
+	/** WrProtect, DPO, FUA, Reserved, FUA_NV, Reserved */
+	uint8_t flags;
+	/** Logical block address */
+	uint64_t lba;
+	/** Transfer length */
+	uint32_t xfer_len;
+	/** Reserved, Group Number */
+	uint8_t group_no;
+	/** Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_write_16_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/scsi/include/scsi/spc.h
===================================================================
--- uspace/lib/scsi/include/scsi/spc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/scsi/include/scsi/spc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libscsi
+ * @{
+ */
+/**
+ * @file SCSI Primary Commands.
+ */
+
+#ifndef LIBSCSI_SPC_H_
+#define LIBSCSI_SPC_H_
+
+#include <stdint.h>
+#include <str.h>
+
+/** SCSI command codes defined in SCSI-SPC */
+enum scsi_cmd_spc {
+	SCSI_CMD_INQUIRY	= 0x12,
+	SCSI_CMD_REQUEST_SENSE	= 0x03
+};
+
+/** SCSI Inquiry command */
+typedef struct {
+	/** Operation code (SCSI_CMD_INQUIRY) */
+	uint8_t op_code;
+	/** Reserved:7-2, obsolete:1, evpd:0 */
+	uint8_t evpd;
+	/* Page Code */
+	uint8_t page_code;
+	/* Allocation Length */
+	uint16_t alloc_len;
+	/* Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_inquiry_t;
+
+/** Minimum size of inquiry data required since SCSI-2 */
+#define SCSI_STD_INQUIRY_DATA_MIN_SIZE 36
+
+/** Standard inquiry data.
+ *
+ * Returned for Inquiry command with evpd bit cleared.
+ */
+typedef struct {
+	/** Peripheral qualifier, Peripheral device type */
+	uint8_t pqual_devtype;
+	/** RMB, reserved */
+	uint8_t rmb;
+	/** Version */
+	uint8_t version;
+	/** Obsolete, NormACA, HiSup, Response Data Format */
+	uint8_t aca_hisup_rdf;
+	/** Additional Length */
+	uint8_t additional_len;
+	/** SCCS, ACC, TPGS, 3PC, Reserved, Protect */
+	uint8_t cap1;
+	/** Obsolete, EncServ, VS, MuliP, Obsolete, Addr16 */
+	uint8_t cap2;
+	/** Obsolete, WBus16, Sync, Obsolete, CmdQue, VS */
+	uint8_t cap3;
+
+	/** Vendor string */
+	uint8_t vendor[8];
+	/** Product string */
+	uint8_t product[16];
+	/** Revision string */
+	uint8_t revision[4];
+
+	/* End of required data */
+} __attribute__((packed)) scsi_std_inquiry_data_t;
+
+/** Size of struct or union member. */
+#define SCSI_MEMBER_SIZE(type, member) \
+    (sizeof(((type *)0) -> member))
+
+/** Size of string buffer needed to hold converted inquiry vendor string */
+#define SCSI_INQ_VENDOR_STR_BUFSIZE \
+    SPASCII_STR_BUFSIZE(SCSI_MEMBER_SIZE(scsi_std_inquiry_data_t, vendor))
+
+/** Size of string buffer needed to hold converted inquiry product string */
+#define SCSI_INQ_PRODUCT_STR_BUFSIZE \
+    SPASCII_STR_BUFSIZE(SCSI_MEMBER_SIZE(scsi_std_inquiry_data_t, product))
+
+/** Size of string buffer needed to hold converted inquiry revision string */
+#define SCSI_INQ_REVISION_STR_BUFSIZE \
+    SPASCII_STR_BUFSIZE(SCSI_MEMBER_SIZE(scsi_std_inquiry_data_t, revision))
+
+/** Bits in scsi_std_inquiry_data_t.pqual_devtype */
+enum scsi_pqual_devtype_bits {
+	/* Peripheral qualifier */
+	SCSI_PQDT_PQUAL_h	= 7,
+	SCSI_PQDT_PQUAL_l	= 5,
+
+	/* Peripheral device type */
+	SCSI_PQDT_DEV_TYPE_h	= 4,
+	SCSI_PQDT_DEV_TYPE_l	= 0
+};
+
+/** Bits in scsi_std_inquiry_data_t.rmb */
+enum scsi_rmb_bits {
+	SCSI_RMB_RMB		= 7
+};
+
+/** SCSI peripheral device type */
+enum scsi_device_type {
+	SCSI_DEV_BLOCK		= 0x00,
+	SCSI_DEV_STREAM		= 0x01,
+	SCSI_DEV_CD_DVD		= 0x05,
+	SCSI_DEV_CHANGER	= 0x08,
+	SCSI_DEV_ENCLOSURE	= 0x0d,
+	SCSI_DEV_OSD		= 0x11,
+
+	SCSI_DEV_LIMIT		= 0x20
+};
+
+/** SCSI Request Sense command */
+typedef struct {
+	/** Operation code (SCSI_CMD_REQUEST_SENSE) */
+	uint8_t op_code;
+	/** Reserved, Desc */
+	uint8_t desc;
+	/* Reserved */
+	uint16_t res_2;
+	/* Allocation Length */
+	uint8_t alloc_len;
+	/* Control */
+	uint8_t control;
+} __attribute__((packed)) scsi_cdb_request_sense_t;
+
+/** Minimum size of sense data.
+ *
+ * If the target returns less data, the missing bytes should be considered
+ * zero.
+ */
+#define SCSI_SENSE_DATA_MIN_SIZE 18
+
+/** Maximum size of sense data */
+#define SCSI_SENSE_DATA_MAX_SIZE 252
+
+/** Fixed-format sense data.
+ *
+ * Returned for Request Sense command with Desc bit cleared.
+ */
+typedef struct {
+	/** Valid, Response Code */
+	uint8_t valid_rcode;
+	/** Peripheral qualifier, Peripheral device type */
+	uint8_t obsolete_1;
+	/** Filemark, EOM, ILI, Reserved, Sense Key */
+	uint8_t flags_key;
+	/** Information */
+	uint32_t info;
+	/** Additional Sense Length */
+	uint8_t additional_len;
+	/** Command-specific Information */
+	uint32_t cmd_spec;
+	/** Additional Sense Code */
+	uint8_t additional_code;
+	/** Additional Sense Code Qualifier */
+	uint8_t additional_cqual;
+	/** Field-replaceable Unit Code */
+	uint8_t fru_code;
+	/** SKSV, Sense-key specific */
+	uint8_t key_spec[3];
+} __attribute__((packed)) scsi_sense_data_t;
+
+/** Sense key */
+enum scsi_sense_key {
+	SCSI_SK_NO_SENSE	= 0x0,
+	SCSI_SK_RECOVERED_ERROR	= 0x1,
+	SCSI_SK_NOT_READY	= 0x2,
+	SCSI_SK_MEDIUM_ERROR	= 0x3,
+	SCSI_SK_HARDWARE_ERROR	= 0x4,
+	SCSI_SK_ILLEGAL_REQUEST	= 0x5,
+	SCSI_SK_UNIT_ATTENTION	= 0x6,
+	SCSI_SK_DATA_PROTECT	= 0x7,
+	SCSI_SK_BLANK_CHECK	= 0x8,
+	SCSI_SK_VENDOR_SPECIFIC	= 0x9,
+	SCSI_SK_COPY_ABORTED	= 0xa,
+	SCSI_SK_ABORTED_COMMAND	= 0xb,
+	SCSI_SK_VOLUME_OVERFLOW	= 0xd,
+	SCSI_SK_MISCOMPARE	= 0xe,
+
+	SCSI_SK_LIMIT		= 0x10
+};
+
+extern const char *scsi_dev_type_str[SCSI_DEV_LIMIT];
+extern const char *scsi_sense_key_str[SCSI_SK_LIMIT];
+
+extern const char *scsi_get_dev_type_str(unsigned);
+extern const char *scsi_get_sense_key_str(unsigned);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/scsi/src/spc.c
===================================================================
--- uspace/lib/scsi/src/spc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/scsi/src/spc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "scsi/spc.h"
+
+/** String descriptions for SCSI peripheral device type.
+ *
+ * Only device types that we are ever likely to encounter are listed here.
+ */
+const char *scsi_dev_type_str[SCSI_DEV_LIMIT] = {
+	[SCSI_DEV_BLOCK]	= "Direct-Access Block Device (Disk)",
+	[SCSI_DEV_STREAM]	= "Sequential-Access Device (Tape)",
+	[SCSI_DEV_CD_DVD]	= "CD/DVD",
+	[SCSI_DEV_CHANGER]	= "Media Changer",
+	[SCSI_DEV_ENCLOSURE]	= "SCSI Enclosure",
+	[SCSI_DEV_OSD]		= "Object Storage Device"
+};
+
+const char *scsi_sense_key_str[SCSI_SK_LIMIT] = {
+	[SCSI_SK_NO_SENSE]		= "No Sense",
+	[SCSI_SK_RECOVERED_ERROR]	= "Recovered Error",
+	[SCSI_SK_NOT_READY]		= "Not Ready",
+	[SCSI_SK_MEDIUM_ERROR]		= "Medium Error",
+	[SCSI_SK_HARDWARE_ERROR]	= "Hardware Error",
+	[SCSI_SK_ILLEGAL_REQUEST]	= "Illegal Request",
+	[SCSI_SK_UNIT_ATTENTION]	= "Unit Attention",
+	[SCSI_SK_DATA_PROTECT]		= "Data Protect",
+	[SCSI_SK_BLANK_CHECK]		= "Blank Check",
+	[SCSI_SK_VENDOR_SPECIFIC]	= "Vendor-specific",
+	[SCSI_SK_COPY_ABORTED]		= "Copy Aborted",
+	[SCSI_SK_ABORTED_COMMAND]	= "Aborted Command",
+	[SCSI_SK_VOLUME_OVERFLOW]	= "Volume Overflow",
+	[SCSI_SK_MISCOMPARE]		= "Miscompare"
+};
+
+/** Get peripheral device type string.
+ *
+ * Return string description of SCSI peripheral device type.
+ * The returned string is valid indefinitely, the caller should
+ * not attempt to free it.
+ */
+const char *scsi_get_dev_type_str(unsigned dev_type)
+{
+	if (dev_type >= SCSI_DEV_LIMIT || scsi_dev_type_str[dev_type] == NULL)
+		return "Unknown";
+
+	return scsi_dev_type_str[dev_type];
+}
+
+/** Get sense key string.
+ *
+ * Return string description of SCSI sense key.
+ * The returned string is valid indefinitely, the caller should
+ * not attempt to free it.
+ */
+const char *scsi_get_sense_key_str(unsigned sense_key)
+{
+	if (sense_key >= SCSI_SK_LIMIT || scsi_sense_key_str[sense_key] == NULL)
+		return "Unknown";
+
+	return scsi_sense_key_str[sense_key];
+}
+
Index: uspace/lib/softfloat/arch/mips32/include/functions.h
===================================================================
--- uspace/lib/softfloat/arch/mips32/include/functions.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/arch/mips32/include/functions.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloatmips32 mips32	
+/** @addtogroup softfloatmips32 mips32
  * @ingroup sfl
  * @brief softfloat architecture dependent definitions 
@@ -72,6 +72,4 @@
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/arch/mips64/include/functions.h
===================================================================
--- uspace/lib/softfloat/arch/mips64/include/functions.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/softfloat/arch/mips64/include/functions.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup softfloatmips64 mips64
+ * @ingroup sfl
+ * @brief softfloat architecture dependent definitions
+ * @{
+ */
+/** @file
+ */
+
+#ifndef __SOFTFLOAT_FUNCTIONS_H__
+#define __SOFTFLOAT_FUNCTIONS_H__
+
+#define float32_to_int(X) float32_to_int32(X);
+#define float32_to_long(X) float32_to_int64(X);
+#define float32_to_longlong(X) float32_to_int64(X);
+
+#define float64_to_int(X) float64_to_int32(X);
+#define float64_to_long(X) float64_to_int64(X);
+#define float64_to_longlong(X) float64_to_int64(X);
+
+#define float32_to_uint(X) float32_to_uint32(X);
+#define float32_to_ulong(X) float32_to_uint64(X);
+#define float32_to_ulonglong(X) float32_to_uint64(X);
+
+#define float64_to_uint(X) float64_to_uint32(X);
+#define float64_to_ulong(X) float64_to_uint64(X);
+#define float64_to_ulonglong(X) float64_to_uint64(X);
+
+#define int_to_float32(X) int32_to_float32(X);
+#define long_to_float32(X) int64_to_float32(X);
+#define longlong_to_float32(X) int64_to_float32(X);
+
+#define int_to_float64(X) int32_to_float64(X);
+#define long_to_float64(X) int64_to_float64(X);
+#define longlong_to_float64(X) int64_to_float64(X);
+
+#define uint_to_float32(X) uint32_to_float32(X);
+#define ulong_to_float32(X) uint64_to_float32(X);
+#define ulonglong_to_float32(X) uint64_to_float32(X);
+
+#define uint_to_float64(X) uint32_to_float64(X);
+#define ulong_to_float64(X) uint64_to_float64(X);
+#define ulonglong_to_float64(X) uint64_to_float64(X);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/softfloat/generic/add.c
===================================================================
--- uspace/lib/softfloat/generic/add.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/generic/add.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -33,7 +33,7 @@
  */
 
-#include<sftypes.h>
-#include<add.h>
-#include<comparison.h>
+#include <sftypes.h>
+#include <add.h>
+#include <comparison.h>
 
 /** Add two Float32 numbers with same signs
@@ -139,9 +139,8 @@
 	a.parts.exp = exp1;
 	
-	/*Clear hidden bit and shift */
+	/* Clear hidden bit and shift */
 	a.parts.fraction = ((frac1 >> 6) & (~FLOAT32_HIDDEN_BIT_MASK)) ; 
 	return a;
 }
-
 
 /** Add two Float64 numbers with same signs
@@ -250,5 +249,5 @@
 	
 	a.parts.exp = exp1;
-	/*Clear hidden bit and shift */
+	/* Clear hidden bit and shift */
 	a.parts.fraction = ( (frac1 >> 6 ) & (~FLOAT64_HIDDEN_BIT_MASK));
 	
Index: uspace/lib/softfloat/generic/common.c
===================================================================
--- uspace/lib/softfloat/generic/common.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/generic/common.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -33,6 +33,6 @@
  */
 
-#include<sftypes.h>
-#include<common.h>
+#include <sftypes.h>
+#include <common.h>
 
 /* Table for fast leading zeroes counting */
@@ -213,3 +213,2 @@
 /** @}
  */
-
Index: uspace/lib/softfloat/generic/comparison.c
===================================================================
--- uspace/lib/softfloat/generic/comparison.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/generic/comparison.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -33,43 +33,47 @@
  */
 
-#include<sftypes.h>
-#include<comparison.h>
+#include <sftypes.h>
+#include <comparison.h>
 
-inline int isFloat32NaN(float32 f)
-{	/* NaN : exp = 0xff and nonzero fraction */
-	return ((f.parts.exp==0xFF)&&(f.parts.fraction));
+/* NaN : exp = 0xff and nonzero fraction */
+int isFloat32NaN(float32 f)
+{
+	return ((f.parts.exp == 0xFF) && (f.parts.fraction));
 }
 
-inline int isFloat64NaN(float64 d)
-{	/* NaN : exp = 0x7ff and nonzero fraction */
-	return ((d.parts.exp==0x7FF)&&(d.parts.fraction));
+/* NaN : exp = 0x7ff and nonzero fraction */
+int isFloat64NaN(float64 d)
+{
+	return ((d.parts.exp == 0x7FF) && (d.parts.fraction));
 }
 
-inline int isFloat32SigNaN(float32 f)
-{	/* SigNaN : exp = 0xff fraction = 0xxxxx..x (binary), where at least one x is nonzero */
-	return ((f.parts.exp==0xFF)&&(f.parts.fraction<0x400000)&&(f.parts.fraction));
+/* SigNaN : exp = 0xff fraction = 0xxxxx..x (binary), where at least one x is nonzero */
+int isFloat32SigNaN(float32 f)
+{
+	return ((f.parts.exp == 0xFF) && (f.parts.fraction < 0x400000) && (f.parts.fraction));
 }
 
-inline int isFloat64SigNaN(float64 d)
-{	/* SigNaN : exp = 0x7ff fraction = 0xxxxx..x (binary), where at least one x is nonzero */
-	return ((d.parts.exp==0x7FF)&&(d.parts.fraction)&&(d.parts.fraction<0x8000000000000ll));
+/* SigNaN : exp = 0x7ff fraction = 0xxxxx..x (binary), where at least one x is nonzero */
+int isFloat64SigNaN(float64 d)
+{
+	return ((d.parts.exp == 0x7FF) && (d.parts.fraction) && (d.parts.fraction < 0x8000000000000ll));
 }
 
-inline int isFloat32Infinity(float32 f) 
+int isFloat32Infinity(float32 f)
 {
-	return ((f.parts.exp==0xFF)&&(f.parts.fraction==0x0));
+	return ((f.parts.exp == 0xFF) && (f.parts.fraction == 0x0));
 }
 
-inline int isFloat64Infinity(float64 d) 
+int isFloat64Infinity(float64 d) 
 {
-	return ((d.parts.exp==0x7FF)&&(d.parts.fraction==0x0));
+	return ((d.parts.exp == 0x7FF) && (d.parts.fraction == 0x0));
 }
 
-inline int isFloat32Zero(float32 f)
+int isFloat32Zero(float32 f)
 {
 	return (((f.binary) & 0x7FFFFFFF) == 0);
 }
 
-inline int isFloat64Zero(float64 d)
+int isFloat64Zero(float64 d)
 {
 	return (((d.binary) & 0x7FFFFFFFFFFFFFFFll) == 0);
@@ -77,51 +81,46 @@
 
 /**
- * @return 1, if both floats are equal - but NaNs are not recognized 
+ * @return 1 if both floats are equal - but NaNs are not recognized
  */
-inline int isFloat32eq(float32 a, float32 b)
+int isFloat32eq(float32 a, float32 b)
 {
-	return ((a.binary==b.binary)||(((a.binary| b.binary)&0x7FFFFFFF)==0)); /* a equals to b or both are zeros (with any sign) */
+	/* a equals to b or both are zeros (with any sign) */
+	return ((a.binary==b.binary) || (((a.binary | b.binary) & 0x7FFFFFFF) == 0));
 }
 
 /**
- * @return 1, if a<b - but NaNs are not recognized 
+ * @return 1 if a < b - but NaNs are not recognized 
  */
-inline int isFloat32lt(float32 a, float32 b) 
+int isFloat32lt(float32 a, float32 b) 
 {
-	if (((a.binary| b.binary)&0x7FFFFFFF)==0) {
+	if (((a.binary | b.binary) & 0x7FFFFFFF) == 0)
 		return 0; /* +- zeroes */
-	};
 	
-	if ((a.parts.sign)&&(b.parts.sign)) {
-		/*if both are negative, smaller is that with greater binary value*/
-		return (a.binary>b.binary);
-		};
+	if ((a.parts.sign) && (b.parts.sign))
+		/* if both are negative, smaller is that with greater binary value */
+		return (a.binary > b.binary);
 	
-	/* lets negate signs - now will be positive numbers allways bigger than negative (first bit will be set for unsigned integer comparison)*/
-	a.parts.sign=!a.parts.sign;
-	b.parts.sign=!b.parts.sign;
-	return (a.binary<b.binary);
-			
+	/* lets negate signs - now will be positive numbers allways bigger than negative (first bit will be set for unsigned integer comparison) */
+	a.parts.sign = !a.parts.sign;
+	b.parts.sign = !b.parts.sign;
+	return (a.binary < b.binary);
 }
 
 /**
- * @return 1, if a>b - but NaNs are not recognized 
+ * @return 1 if a > b - but NaNs are not recognized 
  */
-inline int isFloat32gt(float32 a, float32 b) 
+int isFloat32gt(float32 a, float32 b) 
 {
-	if (((a.binary| b.binary)&0x7FFFFFFF)==0) {
+	if (((a.binary | b.binary) & 0x7FFFFFFF) == 0)
 		return 0; /* zeroes are equal with any sign */
-	};
 	
-	if ((a.parts.sign)&&(b.parts.sign)) {
-		/*if both are negative, greater is that with smaller binary value*/
-		return (a.binary<b.binary);
-		};
+	if ((a.parts.sign) && (b.parts.sign))
+		/* if both are negative, greater is that with smaller binary value */
+		return (a.binary < b.binary);
 	
-	/* lets negate signs - now will be positive numbers allways bigger than negative (first bit will be set for unsigned integer comparison)*/
-	a.parts.sign=!a.parts.sign;
-	b.parts.sign=!b.parts.sign;
-	return (a.binary>b.binary);
-			
+	/* lets negate signs - now will be positive numbers allways bigger than negative (first bit will be set for unsigned integer comparison) */
+	a.parts.sign = !a.parts.sign;
+	b.parts.sign = !b.parts.sign;
+	return (a.binary > b.binary);
 }
 
Index: uspace/lib/softfloat/generic/div.c
===================================================================
--- uspace/lib/softfloat/generic/div.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/generic/div.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -33,11 +33,10 @@
  */
 
-#include<sftypes.h>
-#include<add.h>
-#include<div.h>
-#include<comparison.h>
-#include<mul.h>
-#include<common.h>
-
+#include <sftypes.h>
+#include <add.h>
+#include <div.h>
+#include <comparison.h>
+#include <mul.h>
+#include <common.h>
 
 float32 divFloat32(float32 a, float32 b) 
Index: uspace/lib/softfloat/generic/mul.c
===================================================================
--- uspace/lib/softfloat/generic/mul.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/generic/mul.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -33,8 +33,8 @@
  */
 
-#include<sftypes.h>
-#include<mul.h>
-#include<comparison.h>
-#include<common.h>
+#include <sftypes.h>
+#include <mul.h>
+#include <comparison.h>
+#include <common.h>
 
 /** Multiply two 32 bit float numbers
Index: uspace/lib/softfloat/generic/other.c
===================================================================
--- uspace/lib/softfloat/generic/other.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/generic/other.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
Index: uspace/lib/softfloat/generic/softfloat.c
===================================================================
--- uspace/lib/softfloat/generic/softfloat.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/generic/softfloat.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,17 +35,17 @@
  */
 
-#include<softfloat.h>
-#include<sftypes.h>
-
-#include<add.h>
-#include<sub.h>
-#include<mul.h>
-#include<div.h>
-
-#include<conversion.h>
-#include<comparison.h>
-#include<other.h>
-
-#include<functions.h>
+#include <softfloat.h>
+#include <sftypes.h>
+
+#include <add.h>
+#include <sub.h>
+#include <mul.h>
+#include <div.h>
+
+#include <conversion.h>
+#include <comparison.h>
+#include <other.h>
+
+#include <functions.h>
 
 /* Arithmetic functions */
@@ -494,6 +494,4 @@
 }
 
-
 /** @}
  */
-
Index: uspace/lib/softfloat/generic/sub.c
===================================================================
--- uspace/lib/softfloat/generic/sub.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/generic/sub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -33,7 +33,7 @@
  */
 
-#include<sftypes.h>
-#include<sub.h>
-#include<comparison.h>
+#include <sftypes.h>
+#include <sub.h>
+#include <comparison.h>
 
 /** Subtract two float32 numbers with same signs
@@ -260,6 +260,4 @@
 }
 
-
- /** @}
- */
-
+/** @}
+ */
Index: uspace/lib/softfloat/include/add.h
===================================================================
--- uspace/lib/softfloat/include/add.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/add.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -36,12 +36,9 @@
 #define __ADD_H__
 
-float32 addFloat32(float32 a, float32 b);
-
-float64 addFloat64(float64 a, float64 b);
+extern float32 addFloat32(float32, float32);
+extern float64 addFloat64(float64, float64);
 
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/include/common.h
===================================================================
--- uspace/lib/softfloat/include/common.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/common.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -36,18 +36,17 @@
 #define __COMMON_H__
 
-#include<sftypes.h>
+#include <sftypes.h>
 
-float64 finishFloat64(int32_t cexp, uint64_t cfrac, char sign);
+extern float64 finishFloat64(int32_t, uint64_t, char);
 
-int countZeroes64(uint64_t i);
-int countZeroes32(uint32_t i);
-int countZeroes8(uint8_t i);
+extern int countZeroes64(uint64_t);
+extern int countZeroes32(uint32_t);
+extern int countZeroes8(uint8_t);
 
-void roundFloat32(int32_t *exp, uint32_t *fraction);
-void roundFloat64(int32_t *exp, uint64_t *fraction);
+extern void roundFloat32(int32_t *, uint32_t *);
+extern void roundFloat64(int32_t *, uint64_t *);
 
 #endif
 
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/include/comparison.h
===================================================================
--- uspace/lib/softfloat/include/comparison.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/comparison.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -36,24 +36,22 @@
 #define __COMPARISON_H__
 
-inline int isFloat32NaN(float32 f);
-inline int isFloat32SigNaN(float32 f);
+extern int isFloat32NaN(float32);
+extern int isFloat32SigNaN(float32);
 
-inline int isFloat32Infinity(float32 f);
-inline int isFloat32Zero(float32 f);
+extern int isFloat32Infinity(float32);
+extern int isFloat32Zero(float32);
 
-inline int isFloat64NaN(float64 d);
-inline int isFloat64SigNaN(float64 d);
+extern int isFloat64NaN(float64);
+extern int isFloat64SigNaN(float64);
 
-inline int isFloat64Infinity(float64 d);
-inline int isFloat64Zero(float64 d);
+extern int isFloat64Infinity(float64);
+extern int isFloat64Zero(float64);
 
-inline int isFloat32eq(float32 a, float32 b);
-inline int isFloat32lt(float32 a, float32 b);
-inline int isFloat32gt(float32 a, float32 b);
+extern int isFloat32eq(float32, float32);
+extern int isFloat32lt(float32, float32);
+extern int isFloat32gt(float32, float32);
 
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/include/conversion.h
===================================================================
--- uspace/lib/softfloat/include/conversion.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/conversion.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+ /** @addtogroup softfloat
  * @{
  */
@@ -36,36 +36,33 @@
 #define __CONVERSION_H__
 
-float64 convertFloat32ToFloat64(float32 a);
+extern float64 convertFloat32ToFloat64(float32);
+extern float32 convertFloat64ToFloat32(float64);
 
-float32 convertFloat64ToFloat32(float64 a);
+extern uint32_t float32_to_uint32(float32);
+extern int32_t float32_to_int32(float32);
 
-uint32_t float32_to_uint32(float32 a);
-int32_t float32_to_int32(float32 a);
+extern uint64_t float32_to_uint64(float32);
+extern int64_t float32_to_int64(float32);
 
-uint64_t float32_to_uint64(float32 a);
-int64_t float32_to_int64(float32 a);
+extern uint64_t float64_to_uint64(float64);
+extern int64_t float64_to_int64(float64);
 
-uint64_t float64_to_uint64(float64 a);
-int64_t float64_to_int64(float64 a);
+extern uint32_t float64_to_uint32(float64);
+extern int32_t float64_to_int32(float64);
 
-uint32_t float64_to_uint32(float64 a);
-int32_t float64_to_int32(float64 a);
+extern float32 uint32_to_float32(uint32_t);
+extern float32 int32_to_float32(int32_t);
 
-float32 uint32_to_float32(uint32_t i);
-float32 int32_to_float32(int32_t i);
+extern float32 uint64_to_float32(uint64_t);
+extern float32 int64_to_float32(int64_t);
 
-float32 uint64_to_float32(uint64_t i);
-float32 int64_to_float32(int64_t i);
+extern float64 uint32_to_float64(uint32_t);
+extern float64 int32_to_float64(int32_t);
 
-float64 uint32_to_float64(uint32_t i);
-float64 int32_to_float64(int32_t i);
-
-float64 uint64_to_float64(uint64_t i);
-float64 int64_to_float64(int64_t i);
+extern float64 uint64_to_float64(uint64_t);
+extern float64 int64_to_float64(int64_t);
 
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/include/div.h
===================================================================
--- uspace/lib/softfloat/include/div.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/div.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -36,13 +36,11 @@
 #define __DIV_H__
 
-float32 divFloat32(float32 a, float32 b);
-float64 divFloat64(float64 a, float64 b);
+extern float32 divFloat32(float32, float32);
+extern float64 divFloat64(float64, float64);
 
-uint64_t divFloat64estim(uint64_t a, uint64_t b);
+extern uint64_t divFloat64estim(uint64_t, uint64_t);
 
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/include/mul.h
===================================================================
--- uspace/lib/softfloat/include/mul.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/mul.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -36,14 +36,11 @@
 #define __MUL_H__
 
-float32 mulFloat32(float32 a, float32 b);
+extern float32 mulFloat32(float32, float32);
+extern float64 mulFloat64(float64, float64);
 
-float64 mulFloat64(float64 a, float64 b);
-
-void mul64integers(uint64_t a,uint64_t b, uint64_t *lo, uint64_t *hi);
+extern void mul64integers(uint64_t, uint64_t, uint64_t *, uint64_t *);
 
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/include/other.h
===================================================================
--- uspace/lib/softfloat/include/other.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/other.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -38,6 +38,4 @@
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/include/sftypes.h
===================================================================
--- uspace/lib/softfloat/include/sftypes.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/sftypes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -55,5 +55,5 @@
 	#error Unknown endianess
 #endif
-		} parts __attribute__ ((packed));
+	} parts __attribute__ ((packed));
 } float32;
 
@@ -77,6 +77,6 @@
 } float64;
 
-#define FLOAT32_MAX 0x7f800000
-#define FLOAT32_MIN 0xff800000
+#define FLOAT32_MAX  0x7f800000
+#define FLOAT32_MIN  0xff800000
 #define FLOAT64_MAX
 #define FLOAT64_MIN
@@ -86,25 +86,25 @@
  * comparing with these constants is not sufficient.
  */
-#define FLOAT32_NAN 0x7FC00001
-#define FLOAT32_SIGNAN 0x7F800001
-#define FLOAT32_INF 0x7F800000
 
-#define FLOAT64_NAN 0x7FF8000000000001ll
-#define FLOAT64_SIGNAN 0x7FF0000000000001ll
-#define FLOAT64_INF 0x7FF0000000000000ll
+#define FLOAT32_NAN     0x7FC00001
+#define FLOAT32_SIGNAN  0x7F800001
+#define FLOAT32_INF     0x7F800000
 
-#define FLOAT32_FRACTION_SIZE 23
-#define FLOAT64_FRACTION_SIZE 52
+#define FLOAT64_NAN     0x7FF8000000000001ll
+#define FLOAT64_SIGNAN  0x7FF0000000000001ll
+#define FLOAT64_INF     0x7FF0000000000000ll
 
-#define FLOAT32_HIDDEN_BIT_MASK 0x800000
-#define FLOAT64_HIDDEN_BIT_MASK 0x10000000000000ll
+#define FLOAT32_FRACTION_SIZE  23
+#define FLOAT64_FRACTION_SIZE  52
 
-#define FLOAT32_MAX_EXPONENT 0xFF
-#define FLOAT64_MAX_EXPONENT 0x7FF
+#define FLOAT32_HIDDEN_BIT_MASK  0x800000
+#define FLOAT64_HIDDEN_BIT_MASK  0x10000000000000ll
 
-#define FLOAT32_BIAS 0x7F
-#define FLOAT64_BIAS 0x3FF
-#define FLOAT80_BIAS 0x3FFF
+#define FLOAT32_MAX_EXPONENT  0xFF
+#define FLOAT64_MAX_EXPONENT  0x7FF
 
+#define FLOAT32_BIAS  0x7F
+#define FLOAT64_BIAS  0x3FF
+#define FLOAT80_BIAS  0x3FFF
 
 #endif
Index: uspace/lib/softfloat/include/softfloat.h
===================================================================
--- uspace/lib/softfloat/include/softfloat.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/softfloat.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -36,139 +36,137 @@
 #define __SOFTFLOAT_H__
 
-float __addsf3(float a, float b);
-double __adddf3(double a, double b);
-long double __addtf3(long double a, long double b);
-long double __addxf3(long double a, long double b);
- 
-float __subsf3(float a, float b);
-double __subdf3(double a, double b);
-long double __subtf3(long double a, long double b);
-long double __subxf3(long double a, long double b);
- 
-float __mulsf3(float a, float b);
-double __muldf3(double a, double b);
-long double __multf3(long double a, long double b);
-long double __mulxf3(long double a, long double b);
- 
-float __divsf3(float a, float b);
-double __divdf3(double a, double b);
-long double __divtf3(long double a, long double b);
-long double __divxf3(long double a, long double b);
- 
-float __negsf2(float a);
-double __negdf2(double a);
-long double __negtf2(long double a);
-long double __negxf2(long double a);
- 
-double __extendsfdf2(float a);
-long double __extendsftf2(float a);
-long double __extendsfxf2(float a);
-long double __extenddftf2(double a);
-long double __extenddfxf2(double a);
- 
-double __truncxfdf2(long double a);
-double __trunctfdf2(long double a);
-float __truncxfsf2(long double a);
-float __trunctfsf2(long double a);
-float __truncdfsf2(double a);
- 
-int __fixsfsi(float a);
-int __fixdfsi(double a);
-int __fixtfsi(long double a);
-int __fixxfsi(long double a);
- 
-long __fixsfdi(float a);
-long __fixdfdi(double a);
-long __fixtfdi(long double a);
-long __fixxfdi(long double a);
- 
-long long __fixsfti(float a);
-long long __fixdfti(double a);
-long long __fixtfti(long double a);
-long long __fixxfti(long double a);
- 
-unsigned int __fixunssfsi(float a);
-unsigned int __fixunsdfsi(double a);
-unsigned int __fixunstfsi(long double a);
-unsigned int __fixunsxfsi(long double a);
- 
-unsigned long __fixunssfdi(float a);
-unsigned long __fixunsdfdi(double a);
-unsigned long __fixunstfdi(long double a);
-unsigned long __fixunsxfdi(long double a);
- 
-unsigned long long __fixunssfti(float a);
-unsigned long long __fixunsdfti(double a);
-unsigned long long __fixunstfti(long double a);
-unsigned long long __fixunsxfti(long double a);
- 
-float __floatsisf(int i);
-double __floatsidf(int i);
-long double __floatsitf(int i);
-long double __floatsixf(int i);
- 
-float __floatdisf(long i);
-double __floatdidf(long i);
-long double __floatditf(long i);
-long double __floatdixf(long i);
- 
-float __floattisf(long long i);
-double __floattidf(long long i);
-long double __floattitf(long long i);
-long double __floattixf(long long i);
- 
-float __floatunsisf(unsigned int i);
-double __floatunsidf(unsigned int i);
-long double __floatunsitf(unsigned int i);
-long double __floatunsixf(unsigned int i);
- 
-float __floatundisf(unsigned long i);
-double __floatundidf(unsigned long i);
-long double __floatunditf(unsigned long i);
-long double __floatundixf(unsigned long i);
- 
-float __floatuntisf(unsigned long long i);
-double __floatuntidf(unsigned long long i);
-long double __floatuntitf(unsigned long long i);
-long double __floatuntixf(unsigned long long i);
- 
-int __cmpsf2(float a, float b);
-int __cmpdf2(double a, double b);
-int __cmptf2(long double a, long double b);
- 
-int __unordsf2(float a, float b);
-int __unorddf2(double a, double b);
-int __unordtf2(long double a, long double b);
- 
-int __eqsf2(float a, float b);
-int __eqdf2(double a, double b);
-int __eqtf2(long double a, long double b);
- 
-int __nesf2(float a, float b);
-int __nedf2(double a, double b);
-int __netf2(long double a, long double b);
- 
-int __gesf2(float a, float b);
-int __gedf2(double a, double b);
-int __getf2(long double a, long double b);
- 
-int __ltsf2(float a, float b);
-int __ltdf2(double a, double b);
-int __lttf2(long double a, long double b);
-int __lesf2(float a, float b);
-int __ledf2(double a, double b);
-int __letf2(long double a, long double b);
- 
-int __gtsf2(float a, float b);
-int __gtdf2(double a, double b);
-int __gttf2(long double a, long double b);
- 
-/* Not implemented yet*/ 
-float __powisf2(float a, int b);
+extern float __addsf3(float, float);
+extern double __adddf3(double, double);
+extern long double __addtf3(long double, long double);
+extern long double __addxf3(long double, long double);
+
+extern float __subsf3(float, float);
+extern double __subdf3(double, double);
+extern long double __subtf3(long double, long double);
+extern long double __subxf3(long double, long double);
+
+extern float __mulsf3(float, float);
+extern double __muldf3(double, double);
+extern long double __multf3(long double, long double);
+extern long double __mulxf3(long double, long double);
+
+extern float __divsf3(float, float);
+extern double __divdf3(double, double);
+extern long double __divtf3(long double, long double);
+extern long double __divxf3(long double, long double);
+
+extern float __negsf2(float);
+extern double __negdf2(double);
+extern long double __negtf2(long double);
+extern long double __negxf2(long double);
+
+extern double __extendsfdf2(float);
+extern long double __extendsftf2(float);
+extern long double __extendsfxf2(float);
+extern long double __extenddftf2(double);
+extern long double __extenddfxf2(double);
+
+extern double __truncxfdf2(long double);
+extern double __trunctfdf2(long double);
+extern float __truncxfsf2(long double);
+extern float __trunctfsf2(long double);
+extern float __truncdfsf2(double);
+
+extern int __fixsfsi(float);
+extern int __fixdfsi(double);
+extern int __fixtfsi(long double);
+extern int __fixxfsi(long double);
+
+extern long __fixsfdi(float);
+extern long __fixdfdi(double);
+extern long __fixtfdi(long double);
+extern long __fixxfdi(long double);
+
+extern long long __fixsfti(float);
+extern long long __fixdfti(double);
+extern long long __fixtfti(long double);
+extern long long __fixxfti(long double);
+
+extern unsigned int __fixunssfsi(float);
+extern unsigned int __fixunsdfsi(double);
+extern unsigned int __fixunstfsi(long double);
+extern unsigned int __fixunsxfsi(long double);
+
+extern unsigned long __fixunssfdi(float);
+extern unsigned long __fixunsdfdi(double);
+extern unsigned long __fixunstfdi(long double);
+extern unsigned long __fixunsxfdi(long double);
+
+extern unsigned long long __fixunssfti(float);
+extern unsigned long long __fixunsdfti(double);
+extern unsigned long long __fixunstfti(long double);
+extern unsigned long long __fixunsxfti(long double);
+
+extern float __floatsisf(int);
+extern double __floatsidf(int);
+extern long double __floatsitf(int);
+extern long double __floatsixf(int);
+
+extern float __floatdisf(long);
+extern double __floatdidf(long);
+extern long double __floatditf(long);
+extern long double __floatdixf(long);
+
+extern float __floattisf(long long);
+extern double __floattidf(long long);
+extern long double __floattitf(long long);
+extern long double __floattixf(long long);
+
+extern float __floatunsisf(unsigned int);
+extern double __floatunsidf(unsigned int);
+extern long double __floatunsitf(unsigned int);
+extern long double __floatunsixf(unsigned int);
+
+extern float __floatundisf(unsigned long);
+extern double __floatundidf(unsigned long);
+extern long double __floatunditf(unsigned long);
+extern long double __floatundixf(unsigned long);
+
+extern float __floatuntisf(unsigned long long);
+extern double __floatuntidf(unsigned long long);
+extern long double __floatuntitf(unsigned long long);
+extern long double __floatuntixf(unsigned long long);
+
+extern int __cmpsf2(float, float);
+extern int __cmpdf2(double, double);
+extern int __cmptf2(long double, long double);
+
+extern int __unordsf2(float, float);
+extern int __unorddf2(double, double);
+extern int __unordtf2(long double, long double);
+
+extern int __eqsf2(float, float);
+extern int __eqdf2(double, double);
+extern int __eqtf2(long double, long double);
+
+extern int __nesf2(float, float);
+extern int __nedf2(double, double);
+extern int __netf2(long double, long double);
+
+extern int __gesf2(float, float);
+extern int __gedf2(double, double);
+extern int __getf2(long double, long double);
+
+extern int __ltsf2(float, float);
+extern int __ltdf2(double, double);
+extern int __lttf2(long double, long double);
+extern int __lesf2(float, float);
+extern int __ledf2(double, double);
+extern int __letf2(long double, long double);
+
+extern int __gtsf2(float, float);
+extern int __gtdf2(double, double);
+extern int __gttf2(long double, long double);
+
+/* Not implemented yet */
+extern float __powisf2(float, int);
 
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softfloat/include/sub.h
===================================================================
--- uspace/lib/softfloat/include/sub.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softfloat/include/sub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,5 +27,5 @@
  */
 
- /** @addtogroup softfloat	
+/** @addtogroup softfloat
  * @{
  */
@@ -36,12 +36,9 @@
 #define __SUB_H__
 
-float32 subFloat32(float32 a, float32 b);
-
-float64 subFloat64(float64 a, float64 b);
+extern float32 subFloat32(float32, float32);
+extern float64 subFloat64(float64, float64);
 
 #endif
 
-
- /** @}
+/** @}
  */
-
Index: uspace/lib/softint/Makefile
===================================================================
--- uspace/lib/softint/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softint/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -31,7 +31,9 @@
 EXTRA_CFLAGS = -Iinclude
 LIBRARY = libsoftint
+SLIBRARY = libsoftint.so.0.0
+LSONAME = libsofti.so0
 
 SOURCES = \
-	generic/division.c\
+	generic/division.c \
 	generic/multiplication.c
 
Index: uspace/lib/softint/generic/multiplication.c
===================================================================
--- uspace/lib/softint/generic/multiplication.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/lib/softint/generic/multiplication.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -109,5 +109,5 @@
 	 * result does not fit in signed one */
 	if (SOFTINT_CHECK_OF && ((t2 < t1) || (t2 & (1ull << 63)))) {
-		// error, overflow
+		/* Error, overflow */
 		return (neg ? INT64_MIN : INT64_MAX);
 	}
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+LIBRARY = libusb
+EXTRA_CFLAGS += \
+	-I$(LIBDRV_PREFIX)/include \
+	-Iinclude
+
+SOURCES = \
+	src/class.c \
+	src/ddfiface.c \
+	src/debug.c \
+	src/dump.c \
+	src/hc.c \
+	src/resolve.c \
+	src/usb.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/include/usb/classes/classes.h
===================================================================
--- uspace/lib/usb/include/usb/classes/classes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/include/usb/classes/classes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,67 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB device classes (generic constants and functions).
+ */
+#ifndef LIBUSB_CLASSES_H_
+#define LIBUSB_CLASSES_H_
+
+/** USB device class. */
+typedef enum {
+	USB_CLASS_USE_INTERFACE = 0x00,
+	USB_CLASS_AUDIO = 0x01,
+	USB_CLASS_COMMUNICATIONS_CDC_CONTROL = 0x02,
+	USB_CLASS_HID = 0x03,
+	USB_CLASS_PHYSICAL = 0x05,
+	USB_CLASS_IMAGE = 0x06,
+	USB_CLASS_PRINTER = 0x07,
+	USB_CLASS_MASS_STORAGE = 0x08,
+	USB_CLASS_HUB = 0x09,
+	USB_CLASS_CDC_DATA = 0x0A,
+	USB_CLASS_SMART_CARD = 0x0B,
+	USB_CLASS_CONTENT_SECURITY = 0x0D,
+	USB_CLASS_VIDEO = 0x0E,
+	USB_CLASS_PERSONAL_HEALTHCARE = 0x0F,
+	USB_CLASS_DIAGNOSTIC = 0xDC,
+	USB_CLASS_WIRELESS_CONTROLLER = 0xE0,
+	USB_CLASS_MISCELLANEOUS = 0xEF,
+	USB_CLASS_APPLICATION_SPECIFIC = 0xFE,
+	USB_CLASS_VENDOR_SPECIFIC = 0xFF,
+	/* USB_CLASS_ = 0x, */
+} usb_class_t;
+
+const char *usb_str_class(usb_class_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * @brief USB hub related structures.
+ */
+#ifndef LIBUSB_CLASS_HUB_H_
+#define LIBUSB_CLASS_HUB_H_
+
+#include <sys/types.h>
+
+/** Hub class feature selector.
+ * @warning The constants are not unique (feature selectors are used
+ * for hub and port).
+ */
+typedef enum {
+	USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,
+	USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
+	USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,
+	USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,
+	USB_HUB_FEATURE_PORT_CONNECTION = 0,
+	USB_HUB_FEATURE_PORT_ENABLE = 1,
+	USB_HUB_FEATURE_PORT_SUSPEND = 2,
+	USB_HUB_FEATURE_PORT_OVER_CURRENT = 3,
+	USB_HUB_FEATURE_PORT_RESET = 4,
+	USB_HUB_FEATURE_PORT_POWER = 8,
+	USB_HUB_FEATURE_PORT_LOW_SPEED = 9,
+	USB_HUB_FEATURE_C_PORT_CONNECTION = 16,
+	USB_HUB_FEATURE_C_PORT_ENABLE = 17,
+	USB_HUB_FEATURE_C_PORT_SUSPEND = 18,
+	USB_HUB_FEATURE_C_PORT_OVER_CURRENT = 19,
+	USB_HUB_FEATURE_C_PORT_RESET = 20,
+	/* USB_HUB_FEATURE_ = , */
+} usb_hub_class_feature_t;
+
+
+/** Header of standard hub descriptor without the "variadic" part. */
+typedef struct {
+	/** Descriptor length. */
+	uint8_t length;
+	/** Descriptor type (0x29). */
+	uint8_t descriptor_type;
+	/** Number of downstream ports. */
+	uint8_t port_count;
+	/** Characteristics bitmask. */
+	uint16_t characteristics;
+	/** Time from power-on to stabilization of current on the port. */
+	uint8_t power_good_time;
+	/** Maximum current requirements in mA. */
+	uint8_t max_current;
+} __attribute__ ((packed)) usb_hub_descriptor_header_t;
+
+/**
+ *	@brief usb hub descriptor
+ *
+ *	For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2
+ */
+typedef struct usb_hub_descriptor_type {
+    /** Number of bytes in this descriptor, including this byte */
+    //uint8_t bDescLength;
+
+    /** Descriptor Type, value: 29H for hub descriptor */
+    //uint8_t bDescriptorType;
+
+    /** Number of downstream ports that this hub supports */
+    uint8_t ports_count;
+
+    /**
+            D1...D0: Logical Power Switching Mode
+            00: Ganged power switching (all ports power at
+            once)
+            01: Individual port power switching
+            1X: Reserved. Used only on 1.0 compliant hubs
+            that implement no power switching.
+            D2: Identifies a Compound Device
+            0: Hub is not part of a compound device
+            1: Hub is part of a compound device
+            D4...D3: Over-current Protection Mode
+            00: Global Over-current Protection. The hub
+            reports over-current as a summation of all
+            ports current draw, without a breakdown of
+            individual port over-current status.
+            01: Individual Port Over-current Protection. The
+            hub reports over-current on a per-port basis.
+            Each port has an over-current indicator.
+            1X: No Over-current Protection. This option is
+            allowed only for bus-powered hubs that do not
+            implement over-current protection.
+            D15...D5:
+            Reserved
+     */
+    uint16_t hub_characteristics;
+#define HUB_CHAR_POWER_PER_PORT_FLAG  (1 << 0)
+#define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)
+
+    /**
+            Time (in 2ms intervals) from the time the power-on
+            sequence begins on a port until power is good on that
+            port. The USB System Software uses this value to
+            determine how long to wait before accessing a
+            powered-on port.
+     */
+    uint8_t pwr_on_2_good_time;
+
+    /**
+            Maximum current requirements of the Hub Controller
+            electronics in mA.
+     */
+    uint8_t current_requirement;
+
+    /**
+            Indicates if a port has a removable device attached.
+            This field is reported on byte-granularity. Within a
+            byte, if no port exists for a given location, the field
+            representing the port characteristics returns 0.
+            Bit value definition:
+            0B - Device is removable
+            1B - Device is non-removable
+            This is a bitmap corresponding to the individual ports
+            on the hub:
+            Bit 0: Reserved for future use
+            Bit 1: Port 1
+            Bit 2: Port 2
+            ....
+            Bit n: Port n (implementation-dependent, up to a
+            maximum of 255 ports).
+     */
+    uint8_t devices_removable[32];
+
+    /**
+            This field exists for reasons of compatibility with
+            software written for 1.0 compliant devices. All bits in
+            this field should be set to 1B. This field has one bit for
+            each port on the hub with additional pad bits, if
+            necessary, to make the number of bits in the field an
+            integer multiple of 8.
+     */
+    //uint8_t * port_pwr_ctrl_mask;
+} usb_hub_descriptor_t;
+
+
+
+/**	@brief usb hub specific request types.
+ *
+ *	For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2
+ */
+typedef enum {
+    /**	This request resets a value reported in the hub status.	*/
+    USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE = 0x20,
+    /** This request resets a value reported in the port status. */
+    USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE = 0x23,
+    /** This is an optional per-port diagnostic request that returns the bus state value, as sampled at the last EOF2 point. */
+    USB_HUB_REQ_TYPE_GET_STATE = 0xA3,
+    /** This request returns the hub descriptor. */
+    USB_HUB_REQ_TYPE_GET_DESCRIPTOR = 0xA0,
+    /** This request returns the current hub status and the states that have changed since the previous acknowledgment. */
+    USB_HUB_REQ_TYPE_GET_HUB_STATUS = 0xA0,
+    /** This request returns the current port status and the current value of the port status change bits. */
+    USB_HUB_REQ_TYPE_GET_PORT_STATUS = 0xA3,
+    /** This request overwrites the hub descriptor. */
+    USB_HUB_REQ_TYPE_SET_DESCRIPTOR = 0x20,
+    /** This request sets a value reported in the hub status. */
+    USB_HUB_REQ_TYPE_SET_HUB_FEATURE = 0x20,
+    /** This request sets a value reported in the port status. */
+    USB_HUB_REQ_TYPE_SET_PORT_FEATURE = 0x23
+} usb_hub_bm_request_type_t;
+
+/** @brief hub class request codes*/
+/// \TODO these are duplicit to standart descriptors
+typedef enum {
+    /**  */
+    USB_HUB_REQUEST_GET_STATUS = 0,
+    /** */
+    USB_HUB_REQUEST_CLEAR_FEATURE = 1,
+    /** */
+    USB_HUB_REQUEST_GET_STATE = 2,
+    /** */
+    USB_HUB_REQUEST_SET_FEATURE = 3,
+    /** */
+    USB_HUB_REQUEST_GET_DESCRIPTOR = 6,
+    /** */
+    USB_HUB_REQUEST_SET_DESCRIPTOR = 7
+} usb_hub_request_t;
+
+/**
+ *	Maximum size of usb hub descriptor in bytes
+ */
+extern size_t USB_HUB_MAX_DESCRIPTOR_SIZE;
+
+
+
+
+
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/classes/massstor.h
===================================================================
--- uspace/lib/usb/include/usb/classes/massstor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/include/usb/classes/massstor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 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 libusb
+ * @{
+ */
+/** @file
+ * USB mass storage related functions and constants.
+ */
+#ifndef LIBUSB_CLASS_MASSSTOR_H_
+#define LIBUSB_CLASS_MASSSTOR_H_
+
+#include <sys/types.h>
+
+/** USB mass storage subclasses. */
+typedef enum {
+	USB_MASSSTOR_SUBCLASS_RBC = 0x01,
+	/** Also known as MMC-5. */
+	USB_MASSSTOR_SUBCLASS_ATAPI = 0x02,
+	USB_MASSSTOR_SUBCLASS_UFI = 0x04,
+	USB_MASSSTOR_SUBCLASS_SCSI = 0x06,
+	USB_MASSSTOR_SUBCLASS_LSDFS = 0x07,
+	USB_MASSSTOR_SUBCLASS_IEEE1667 = 0x08,
+	USB_MASSSTOR_SUBCLASS_VENDOR = 0xFF
+} usb_massstor_subclass_t;
+
+/** USB mass storage interface protocols. */
+typedef enum {
+	/** CBI transport with command completion interrupt. */
+	USB_MASSSTOR_PROTOCOL_CBI_CC = 0x00,
+	/** CBI transport with no command completion interrupt. */
+	USB_MASSSTOR_PROTOCOL_CBI = 0x01,
+	/** Bulk only transport. */
+	USB_MASSSTOR_PROTOCOL_BBB = 0x50,
+	/** USB attached SCSI. */
+	USB_MASSSTOR_PROTOCOL_UAS = 0x62,
+	USB_MASSSTOR_PROTOCOL_VENDOR = 0xFF
+} usb_massstor_protocol_t;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/ddfiface.h
===================================================================
--- uspace/lib/usb/include/usb/ddfiface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/include/usb/ddfiface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 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 libusb
+ * @{
+ */
+/** @file
+ * Implementations of DDF interfaces functions.
+ */
+#ifndef LIBUSB_DDFIFACE_H_
+#define LIBUSB_DDFIFACE_H_
+
+#include <sys/types.h>
+#include <usb_iface.h>
+
+int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *, devman_handle_t *);
+int usb_iface_get_address_hub_impl(ddf_fun_t *, devman_handle_t,
+    usb_address_t *);
+extern usb_iface_t usb_iface_hub_impl;
+
+int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *, devman_handle_t *);
+int usb_iface_get_address_hub_child_impl(ddf_fun_t *, devman_handle_t,
+    usb_address_t *);
+extern usb_iface_t usb_iface_hub_child_impl;
+
+int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *, devman_handle_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/include/usb/debug.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2010-2011 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 libusb
+ * @{
+ */
+/** @file
+ * Debugging related functions.
+ */
+#ifndef LIBUSB_DEBUG_H_
+#define LIBUSB_DEBUG_H_
+#include <stdio.h>
+#include <inttypes.h>
+#include <usb/usb.h>
+#include <assert.h>
+
+void usb_dump_standard_descriptor(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+
+/** Logging level. */
+typedef enum {
+	/** Fatal, unrecoverable, error.
+	 * Such error prevents the driver from working at all.
+	 */
+	USB_LOG_LEVEL_FATAL,
+
+	/** Serious but recoverable error
+	 * Shall be used for errors fatal for single device but not for
+	 * driver itself.
+	 */
+	USB_LOG_LEVEL_ERROR,
+
+	/** Warning.
+	 * Problems from which the driver is able to recover gracefully.
+	 */
+	USB_LOG_LEVEL_WARNING,
+
+	/** Information message.
+	 * This should be the last level that is printed by default to
+	 * the screen.
+	 * Typical usage is to inform that new device was found and what
+	 * are its capabilities.
+	 * Do not use for repetitive actions (such as device polling).
+	 */
+	USB_LOG_LEVEL_INFO,
+
+	/** Debugging message. */
+	USB_LOG_LEVEL_DEBUG,
+
+	/** More detailed debugging message. */
+	USB_LOG_LEVEL_DEBUG2,
+
+	/** Terminating constant for logging levels. */
+	USB_LOG_LEVEL_MAX
+} usb_log_level_t;
+
+/** Default log level. */
+#ifdef CONFIG_USB_RELEASE_BUILD
+#  define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_INFO
+#else
+#  define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_DEBUG
+#endif
+
+void usb_log_enable(usb_log_level_t, const char *);
+
+void usb_log_printf(usb_log_level_t, const char *, ...)
+	PRINTF_ATTRIBUTE(2, 3);
+
+/** Log fatal error. */
+#define usb_log_fatal(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_FATAL, format, ##__VA_ARGS__)
+
+/** Log normal (recoverable) error. */
+#define usb_log_error(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_ERROR, format, ##__VA_ARGS__)
+
+/** Log warning. */
+#define usb_log_warning(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_WARNING, format, ##__VA_ARGS__)
+
+/** Log informational message. */
+#define usb_log_info(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_INFO, format, ##__VA_ARGS__)
+
+/** Log debugging message. */
+#define usb_log_debug(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
+
+/** Log verbose debugging message. */
+#define usb_log_debug2(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_DEBUG2, format, ##__VA_ARGS__)
+
+const char *usb_debug_str_buffer(const uint8_t *, size_t, size_t);
+
+
+#endif
+/**
+ * @}
+ */
+
Index: uspace/lib/usb/include/usb/descriptor.h
===================================================================
--- uspace/lib/usb/include/usb/descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/include/usb/descriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,214 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Standard USB descriptors.
+ */
+#ifndef LIBUSB_DESCRIPTOR_H_
+#define LIBUSB_DESCRIPTOR_H_
+
+#include <async.h>
+
+/** Descriptor type. */
+typedef enum {
+	USB_DESCTYPE_DEVICE = 1,
+	USB_DESCTYPE_CONFIGURATION = 2,
+	USB_DESCTYPE_STRING = 3,
+	USB_DESCTYPE_INTERFACE = 4,
+	USB_DESCTYPE_ENDPOINT = 5,
+	USB_DESCTYPE_HID = 0x21,
+	USB_DESCTYPE_HID_REPORT = 0x22,
+	USB_DESCTYPE_HID_PHYSICAL = 0x23,
+	USB_DESCTYPE_HUB = 0x29,
+	/* USB_DESCTYPE_ = */
+} usb_descriptor_type_t;
+
+/** Standard USB device descriptor.
+ */
+typedef struct {
+	/** Size of this descriptor in bytes. */
+	uint8_t length;
+	/** Descriptor type (USB_DESCTYPE_DEVICE). */
+	uint8_t descriptor_type;
+	/** USB specification release number.
+	 * The number shall be coded as binary-coded decimal (BCD).
+	 */
+	uint16_t usb_spec_version;
+	/** Device class. */
+	uint8_t device_class;
+	/** Device sub-class. */
+	uint8_t device_subclass;
+	/** Device protocol. */
+	uint8_t device_protocol;
+	/** Maximum packet size for endpoint zero.
+	 * Valid values are only 8, 16, 32, 64).
+	 */
+	uint8_t max_packet_size;
+	/** Vendor ID. */
+	uint16_t vendor_id;
+	/** Product ID. */
+	uint16_t product_id;
+	/** Device release number (in BCD). */
+	uint16_t device_version;
+	/** Manufacturer descriptor index. */
+	uint8_t str_manufacturer;
+	/** Product descriptor index. */
+	uint8_t str_product;
+	/** Device serial number descriptor index. */
+	uint8_t str_serial_number;
+	/** Number of possible configurations. */
+	uint8_t configuration_count;
+} __attribute__ ((packed)) usb_standard_device_descriptor_t;
+
+/** Standard USB configuration descriptor.
+ */
+typedef struct {
+	/** Size of this descriptor in bytes. */
+	uint8_t length;
+	/** Descriptor type (USB_DESCTYPE_CONFIGURATION). */
+	uint8_t descriptor_type;
+	/** Total length of all data of this configuration.
+	 * This includes the combined length of all descriptors
+	 * (configuration, interface, endpoint, class-specific and
+	 * vendor-specific) valid for this configuration.
+	 */
+	uint16_t total_length;
+	/** Number of possible interfaces under this configuration. */
+	uint8_t interface_count;
+	/** Configuration value used when setting this configuration. */
+	uint8_t configuration_number;
+	/** String descriptor describing this configuration. */
+	uint8_t str_configuration;
+	/** Attribute bitmap. */
+	uint8_t attributes;
+	/** Maximum power consumption from the USB under this configuration.
+	 * Expressed in 2mA unit (e.g. 50 ~ 100mA).
+	 */
+	uint8_t max_power;
+} __attribute__ ((packed)) usb_standard_configuration_descriptor_t;
+
+/** Standard USB interface descriptor.
+ */
+typedef struct {
+	/** Size of this descriptor in bytes. */
+	uint8_t length;
+	/** Descriptor type (USB_DESCTYPE_INTERFACE). */
+	uint8_t descriptor_type;
+	/** Number of interface.
+	 * Zero-based index into array of interfaces for current configuration.
+	 */
+	uint8_t interface_number;
+	/** Alternate setting for value in interface_number. */
+	uint8_t alternate_setting;
+	/** Number of endpoints used by this interface.
+	 * This number must exclude usage of endpoint zero
+	 * (default control pipe).
+	 */
+	uint8_t endpoint_count;
+	/** Class code. */
+	uint8_t interface_class;
+	/** Subclass code. */
+	uint8_t interface_subclass;
+	/** Protocol code. */
+	uint8_t interface_protocol;
+	/** String descriptor describing this interface. */
+	uint8_t str_interface;
+} __attribute__ ((packed)) usb_standard_interface_descriptor_t;
+
+/** Standard USB endpoint descriptor.
+ */
+typedef struct {
+	/** Size of this descriptor in bytes. */
+	uint8_t length;
+	/** Descriptor type (USB_DESCTYPE_ENDPOINT). */
+	uint8_t descriptor_type;
+	/** Endpoint address together with data flow direction. */
+	uint8_t endpoint_address;
+	/** Endpoint attributes.
+	 * Includes transfer type (usb_transfer_type_t).
+	 */
+	uint8_t attributes;
+	/** Maximum packet size. */
+	uint16_t max_packet_size;
+	/** Polling interval in milliseconds.
+	 * Ignored for bulk and control endpoints.
+	 * Isochronous endpoints must use value 1.
+	 * Interrupt endpoints any value from 1 to 255.
+	 */
+	uint8_t poll_interval;
+} __attribute__ ((packed)) usb_standard_endpoint_descriptor_t;
+
+/** Part of standard USB HID descriptor specifying one class descriptor.
+ *
+ * (See HID Specification, p.22)
+ */
+typedef struct {
+	/** Type of class-specific descriptor (Report or Physical). */
+	uint8_t type;
+	/** Length of class-specific descriptor in bytes. */
+	uint16_t length;
+} __attribute__ ((packed)) usb_standard_hid_class_descriptor_info_t;
+
+/** Standard USB HID descriptor.
+ *
+ * (See HID Specification, p.22)
+ *
+ * It is actually only the "header" of the descriptor, it does not contain
+ * the last two mandatory fields (type and length of the first class-specific
+ * descriptor).
+ */
+typedef struct {
+	/** Total size of this descriptor in bytes.
+	 *
+	 * This includes all class-specific descriptor info - type + length
+	 * for each descriptor.
+	 */
+	uint8_t length;
+	/** Descriptor type (USB_DESCTYPE_HID). */
+	uint8_t descriptor_type;
+	/** HID Class Specification release. */
+	uint16_t spec_release;
+	/** Country code of localized hardware. */
+	uint8_t country_code;
+	/** Total number of class-specific (i.e. Report and Physical)
+	 * descriptors.
+	 *
+	 * @note There is always only one Report descriptor.
+	 */
+	uint8_t class_desc_count;
+	/** First mandatory class descriptor (Report) info. */
+	usb_standard_hid_class_descriptor_info_t report_desc_info;
+} __attribute__ ((packed)) usb_standard_hid_descriptor_t;
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/hc.h
===================================================================
--- uspace/lib/usb/include/usb/hc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/include/usb/hc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011 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 libusb
+ * @{
+ */
+/** @file
+ * General communication with host controller driver.
+ */
+#ifndef LIBUSB_HC_H_
+#define LIBUSB_HC_H_
+
+#include <sys/types.h>
+#include <ipc/devman.h>
+#include <ipc/loc.h>
+#include <ddf/driver.h>
+#include <bool.h>
+#include <async.h>
+#include <usb/usb.h>
+
+/** Connection to the host controller driver. */
+typedef struct {
+	/** Devman handle of the host controller. */
+	devman_handle_t hc_handle;
+	/** Session to the host controller. */
+	async_sess_t *hc_sess;
+} usb_hc_connection_t;
+
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
+    ddf_dev_t *);
+int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
+
+int usb_hc_connection_open(usb_hc_connection_t *);
+bool usb_hc_connection_is_opened(const usb_hc_connection_t *);
+int usb_hc_connection_close(usb_hc_connection_t *);
+int usb_hc_get_handle_by_address(usb_hc_connection_t *, usb_address_t,
+    devman_handle_t *);
+
+int usb_hc_get_address_by_handle(devman_handle_t);
+
+int usb_hc_find(devman_handle_t, devman_handle_t *);
+
+int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *,
+    devman_handle_t *);
+
+int usb_ddf_get_hc_handle_by_sid(service_id_t, devman_handle_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/include/usb/usb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,182 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Common USB types and functions.
+ */
+#ifndef LIBUSB_USB_H_
+#define LIBUSB_USB_H_
+
+#include <sys/types.h>
+#include <byteorder.h>
+
+/** Convert 16bit value from native (host) endianness to USB endianness. */
+#define uint16_host2usb(n) host2uint16_t_le((n))
+
+/** Convert 32bit value from native (host) endianness to USB endianness. */
+#define uint32_host2usb(n) host2uint32_t_le((n))
+
+/** Convert 16bit value from USB endianness into native (host) one. */
+#define uint16_usb2host(n) uint16_t_le2host((n))
+
+/** Convert 32bit value from USB endianness into native (host) one. */
+#define uint32_usb2host(n) uint32_t_le2host((n))
+
+
+/** USB transfer type. */
+typedef enum {
+	USB_TRANSFER_CONTROL = 0,
+	USB_TRANSFER_ISOCHRONOUS = 1,
+	USB_TRANSFER_BULK = 2,
+	USB_TRANSFER_INTERRUPT = 3
+} usb_transfer_type_t;
+
+const char * usb_str_transfer_type(usb_transfer_type_t t);
+const char * usb_str_transfer_type_short(usb_transfer_type_t t);
+
+/** USB data transfer direction. */
+typedef enum {
+	USB_DIRECTION_IN,
+	USB_DIRECTION_OUT,
+	USB_DIRECTION_BOTH
+} usb_direction_t;
+
+const char *usb_str_direction(usb_direction_t);
+
+/** USB speeds. */
+typedef enum {
+	/** USB 1.1 low speed (1.5Mbits/s). */
+	USB_SPEED_LOW,
+	/** USB 1.1 full speed (12Mbits/s). */
+	USB_SPEED_FULL,
+	/** USB 2.0 high speed (480Mbits/s). */
+	USB_SPEED_HIGH,
+	/** Psuedo-speed serving as a boundary. */
+	USB_SPEED_MAX
+} usb_speed_t;
+
+const char *usb_str_speed(usb_speed_t);
+
+
+/** USB request type target. */
+typedef enum {
+	USB_REQUEST_TYPE_STANDARD = 0,
+	USB_REQUEST_TYPE_CLASS = 1,
+	USB_REQUEST_TYPE_VENDOR = 2
+} usb_request_type_t;
+
+/** USB request recipient. */
+typedef enum {
+	USB_REQUEST_RECIPIENT_DEVICE = 0,
+	USB_REQUEST_RECIPIENT_INTERFACE = 1,
+	USB_REQUEST_RECIPIENT_ENDPOINT = 2,
+	USB_REQUEST_RECIPIENT_OTHER = 3
+} usb_request_recipient_t;
+
+/** USB address type.
+ * Negative values could be used to indicate error.
+ */
+typedef int usb_address_t;
+
+/** Default USB address. */
+#define USB_ADDRESS_DEFAULT 0
+/** Maximum address number in USB 1.1. */
+#define USB11_ADDRESS_MAX 128
+
+/** USB endpoint number type.
+ * Negative values could be used to indicate error.
+ */
+typedef int usb_endpoint_t;
+
+/** Maximum endpoint number in USB 1.1.
+ */
+#define USB11_ENDPOINT_MAX 16
+
+
+/** USB complete address type. 
+ * Pair address + endpoint is identification of transaction recipient.
+ */
+typedef struct {
+	usb_address_t address;
+	usb_endpoint_t endpoint;
+} usb_target_t;
+
+/** Compare USB targets (addresses and endpoints).
+ *
+ * @param a First target.
+ * @param b Second target.
+ * @return Whether @p a and @p b points to the same pipe on the same device.
+ */
+static inline int usb_target_same(usb_target_t a, usb_target_t b)
+{
+	return (a.address == b.address)
+	    && (a.endpoint == b.endpoint);
+}
+
+/** General handle type.
+ * Used by various USB functions as opaque handle.
+ */
+typedef sysarg_t usb_handle_t;
+
+/** USB packet identifier. */
+typedef enum {
+#define _MAKE_PID_NIBBLE(tag, type) \
+	((uint8_t)(((tag) << 2) | (type)))
+#define _MAKE_PID(tag, type) \
+	( \
+	    _MAKE_PID_NIBBLE(tag, type) \
+	    | ((~_MAKE_PID_NIBBLE(tag, type)) << 4) \
+	)
+	USB_PID_OUT = _MAKE_PID(0, 1),
+	USB_PID_IN = _MAKE_PID(2, 1),
+	USB_PID_SOF = _MAKE_PID(1, 1),
+	USB_PID_SETUP = _MAKE_PID(3, 1),
+
+	USB_PID_DATA0 = _MAKE_PID(0 ,3),
+	USB_PID_DATA1 = _MAKE_PID(2 ,3),
+
+	USB_PID_ACK = _MAKE_PID(0 ,2),
+	USB_PID_NAK = _MAKE_PID(2 ,2),
+	USB_PID_STALL = _MAKE_PID(3 ,2),
+
+	USB_PID_PRE = _MAKE_PID(3 ,0),
+	/* USB_PID_ = _MAKE_PID( ,), */
+#undef _MAKE_PID
+#undef _MAKE_PID_NIBBLE
+} usb_packet_id;
+
+/** Category for USB host controllers. */
+#define USB_HC_CATEGORY "usbhc"
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/class.c
===================================================================
--- uspace/lib/usb/src/class.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/src/class.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,92 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * @brief Class related functions.
+ */
+#include <usb/classes/classes.h>
+#include <errno.h>
+
+/** Tell string representation of USB class.
+ *
+ * @param cls Class code.
+ * @return String representation.
+ */
+const char *usb_str_class(usb_class_t cls)
+{
+	switch (cls) {
+		case USB_CLASS_USE_INTERFACE:
+			return "use-interface";
+		case USB_CLASS_AUDIO:
+			return "audio";
+		case USB_CLASS_COMMUNICATIONS_CDC_CONTROL:
+			return "communications";
+		case USB_CLASS_HID:
+			return "HID";
+		case USB_CLASS_PHYSICAL:
+			return "physical";
+		case USB_CLASS_IMAGE:
+			return "image";
+		case USB_CLASS_PRINTER:
+			return "printer";
+		case USB_CLASS_MASS_STORAGE:
+			return "mass-storage";
+		case USB_CLASS_HUB:
+			return "hub";
+		case USB_CLASS_CDC_DATA:
+			return "CDC";
+		case USB_CLASS_SMART_CARD:
+			return "smart-card";
+		case USB_CLASS_CONTENT_SECURITY:
+			return "security";
+		case USB_CLASS_VIDEO:
+			return "video";
+		case USB_CLASS_PERSONAL_HEALTHCARE:
+			return "healthcare";
+		case USB_CLASS_DIAGNOSTIC:
+			return "diagnostic";
+		case USB_CLASS_WIRELESS_CONTROLLER:
+			return "wireless";
+		case USB_CLASS_MISCELLANEOUS:
+			return "misc";
+		case USB_CLASS_APPLICATION_SPECIFIC:
+			return "application";
+		case USB_CLASS_VENDOR_SPECIFIC:
+			return "vendor";
+		default:
+			return "unknown";
+	}
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/src/ddfiface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2011 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 libusb
+ * @{
+ */
+/** @file
+ * Implementations of DDF interfaces functions (actual implementation).
+ */
+#include <ipc/devman.h>
+#include <devman.h>
+#include <async.h>
+#include <usb/ddfiface.h>
+#include <usb/hc.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <assert.h>
+
+/** DDF interface for USB device, implementation for typical hub. */
+usb_iface_t  usb_iface_hub_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_impl,
+	.get_address = usb_iface_get_address_hub_impl
+};
+
+/** DDF interface for USB device, implementation for child of a typical hub. */
+usb_iface_t  usb_iface_hub_child_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
+	.get_address = usb_iface_get_address_hub_child_impl
+};
+
+
+/** Get host controller handle, interface implementation for hub driver.
+ *
+ * @param[in] fun Device function the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Error code.
+ */
+int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+	return usb_hc_find(fun->handle, handle);
+}
+
+/** Get host controller handle, interface implementation for child of
+ * a hub driver.
+ *
+ * @param[in] fun Device function the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Error code.
+ */
+int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *fun,
+    devman_handle_t *handle)
+{
+	assert(fun != NULL);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	async_exch_t *exch = async_exchange_begin(parent_sess);
+	
+	sysarg_t hc_handle;
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &hc_handle);
+	
+	async_exchange_end(exch);
+	async_hangup(parent_sess);
+	
+	if (rc != EOK)
+		return rc;
+	
+	*handle = hc_handle;
+	return EOK;
+}
+
+/** Get host controller handle, interface implementation for HC driver.
+ *
+ * @param[in] fun Device function the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Always EOK.
+ */
+int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+
+	if (handle != NULL) {
+		*handle = fun->handle;
+	}
+
+	return EOK;
+}
+
+/** Get USB device address, interface implementation for hub driver.
+ *
+ * @param[in] fun Device function the operation is running on.
+ * @param[in] handle Devman handle of USB device we want address of.
+ * @param[out] address Storage for USB address of device with handle @p handle.
+ * @return Error code.
+ */
+int usb_iface_get_address_hub_impl(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	assert(fun);
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	async_exch_t *exch = async_exchange_begin(parent_sess);
+	
+	sysarg_t addr;
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS, handle, &addr);
+	
+	async_exchange_end(exch);
+	async_hangup(parent_sess);
+	
+	if (rc != EOK)
+		return rc;
+	
+	if (address != NULL)
+		*address = (usb_address_t) addr;
+	
+	return EOK;
+}
+
+/** Get USB device address, interface implementation for child of
+ * a hub driver.
+ *
+ * @param[in] fun Device function the operation is running on.
+ * @param[in] handle Devman handle of USB device we want address of.
+ * @param[out] address Storage for USB address of device with handle @p handle.
+ * @return Error code.
+ */
+int usb_iface_get_address_hub_child_impl(ddf_fun_t *fun,
+    devman_handle_t handle, usb_address_t *address)
+{
+	if (handle == 0) {
+		handle = fun->handle;
+	}
+	return usb_iface_get_address_hub_impl(fun, handle, address);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/debug.c
===================================================================
--- uspace/lib/usb/src/debug.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/src/debug.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2010-2011 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 libusb
+ * @{
+ */
+/** @file
+ * Debugging and logging support.
+ */
+#include <adt/list.h>
+#include <fibril_synch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ddf/log.h>
+#include <usb/debug.h>
+
+/** Level of logging messages. */
+static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
+
+/** Prefix for logging messages. */
+static const char *log_prefix = "usb";
+
+/** Serialization mutex for logging functions. */
+static FIBRIL_MUTEX_INITIALIZE(log_serializer);
+
+/** File where to store the log. */
+static FILE *log_stream = NULL;
+
+
+/** Enable logging.
+ *
+ * @param level Maximal enabled level (including this one).
+ * @param message_prefix Prefix for each printed message.
+ */
+void usb_log_enable(usb_log_level_t level, const char *message_prefix)
+{
+	log_prefix = message_prefix;
+	log_level = level;
+	if (log_stream == NULL) {
+		char *fname;
+		int rc = asprintf(&fname, "/log/%s", message_prefix);
+		if (rc > 0) {
+			log_stream = fopen(fname, "w");
+			if (log_stream != NULL)
+				setvbuf(log_stream, NULL, _IOFBF, BUFSIZ);
+			
+			free(fname);
+		}
+	}
+}
+
+/** Get log level name prefix.
+ *
+ * @param level Log level.
+ * @return String prefix for the message.
+ */
+static const char *log_level_name(usb_log_level_t level)
+{
+	switch (level) {
+		case USB_LOG_LEVEL_FATAL:
+			return " FATAL";
+		case USB_LOG_LEVEL_ERROR:
+			return " ERROR";
+		case USB_LOG_LEVEL_WARNING:
+			return " WARN";
+		case USB_LOG_LEVEL_INFO:
+			return " info";
+		default:
+			return "";
+	}
+}
+
+/** Print logging message.
+ *
+ * @param level Verbosity level of the message.
+ * @param format Formatting directive.
+ */
+void usb_log_printf(usb_log_level_t level, const char *format, ...)
+{
+	FILE *screen_stream = NULL;
+	switch (level) {
+		case USB_LOG_LEVEL_FATAL:
+		case USB_LOG_LEVEL_ERROR:
+			screen_stream = stderr;
+			break;
+		default:
+			screen_stream = stdout;
+			break;
+	}
+	assert(screen_stream != NULL);
+
+	va_list args;
+
+	/*
+	 * Serialize access to log files.
+	 * Print to screen only messages with higher level than the one
+	 * specified during logging initialization.
+	 * Print also to file, to it print one more (lower) level as well.
+	 */
+	fibril_mutex_lock(&log_serializer);
+
+	const char *level_name = log_level_name(level);
+
+	if ((log_stream != NULL) && (level <= log_level + 1)) {
+		va_start(args, format);
+
+		fprintf(log_stream, "[%s]%s: ", log_prefix, level_name);
+		vfprintf(log_stream, format, args);
+		fflush(log_stream);
+
+		va_end(args);
+	}
+
+	if (level <= log_level) {
+		va_start(args, format);
+
+		fprintf(screen_stream, "[%s]%s: ", log_prefix, level_name);
+		vfprintf(screen_stream, format, args);
+		fflush(screen_stream);
+
+		va_end(args);
+	}
+
+	fibril_mutex_unlock(&log_serializer);
+}
+
+
+#define REMAINDER_STR_FMT " (%zu)..."
+/* string + terminator + number width (enough for 4GB)*/
+#define REMAINDER_STR_LEN (5 + 1 + 10)
+
+/** How many bytes to group together. */
+#define BUFFER_DUMP_GROUP_SIZE 4
+
+/** Size of the string for buffer dumps. */
+#define BUFFER_DUMP_LEN 240 /* Ought to be enough for everybody ;-). */
+
+/** Fibril local storage for the dumped buffer. */
+static fibril_local char buffer_dump[2][BUFFER_DUMP_LEN];
+/** Fibril local storage for buffer switching. */
+static fibril_local int buffer_dump_index = 0;
+
+/** Dump buffer into string.
+ *
+ * The function dumps given buffer into hexadecimal format and stores it
+ * in a static fibril local string.
+ * That means that you do not have to deallocate the string (actually, you
+ * can not do that) and you do not have to guard it against concurrent
+ * calls to it.
+ * The only limitation is that each second call rewrites the buffer again
+ * (internally, two buffer are used in cyclic manner).
+ * Thus, it is necessary to copy the buffer elsewhere (that includes printing
+ * to screen or writing to file).
+ * Since this function is expected to be used for debugging prints only,
+ * that is not a big limitation.
+ *
+ * @warning You cannot use this function more than twice in the same printf
+ * (see detailed explanation).
+ *
+ * @param buffer Buffer to be printed (can be NULL).
+ * @param size Size of the buffer in bytes (can be zero).
+ * @param dumped_size How many bytes to actually dump (zero means all).
+ * @return Dumped buffer as a static (but fibril local) string.
+ */
+const char *usb_debug_str_buffer(const uint8_t *buffer, size_t size,
+    size_t dumped_size)
+{
+	/*
+	 * Remove previous string.
+	 */
+	bzero(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN);
+
+	/* Do the actual dump. */
+	ddf_dump_buffer(buffer_dump[buffer_dump_index], BUFFER_DUMP_LEN,
+	    buffer, 1, size, dumped_size);
+
+	/* Next time, use the other buffer. */
+	buffer_dump_index = 1 - buffer_dump_index;
+
+	/* Need to take the old one due to previous line. */
+	return buffer_dump[1 - buffer_dump_index];
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/dump.c
===================================================================
--- uspace/lib/usb/src/dump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/src/dump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2011 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 libusb
+ * @{
+ */
+/** @file
+ * Descriptor dumping.
+ */
+#include <adt/list.h>
+#include <fibril_synch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include <usb/descriptor.h>
+#include <usb/classes/classes.h>
+
+/** Mapping between descriptor id and dumping function. */
+typedef struct {
+	/** Descriptor id. */
+	int id;
+	/** Dumping function. */
+	void (*dump)(FILE *, const char *, const char *,
+	    const uint8_t *, size_t);
+} descriptor_dump_t;
+
+static void usb_dump_descriptor_device(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_configuration(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_interface(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_string(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_endpoint(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_hid(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_hub(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_generic(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+
+/** Descriptor dumpers mapping. */
+static descriptor_dump_t descriptor_dumpers[] = {
+	{ USB_DESCTYPE_DEVICE, usb_dump_descriptor_device },
+	{ USB_DESCTYPE_CONFIGURATION, usb_dump_descriptor_configuration },
+	{ USB_DESCTYPE_STRING, usb_dump_descriptor_string },
+	{ USB_DESCTYPE_INTERFACE, usb_dump_descriptor_interface },
+	{ USB_DESCTYPE_ENDPOINT, usb_dump_descriptor_endpoint },
+	{ USB_DESCTYPE_HID, usb_dump_descriptor_hid },
+	{ USB_DESCTYPE_HUB, usb_dump_descriptor_hub },
+	{ -1, usb_dump_descriptor_generic },
+	{ -1, NULL }
+};
+
+/** Dumps standard USB descriptor.
+ * The @p line_suffix must contain the newline <code>\\n</code> character.
+ * When @p line_suffix or @p line_prefix is NULL, they are substitued with
+ * default values
+ * (<code> - </code> for prefix and line termination for suffix).
+ *
+ * @param output Output file stream to dump descriptor to.
+ * @param line_prefix Prefix for each line of output.
+ * @param line_suffix Suffix of each line of output.
+ * @param descriptor Actual descriptor.
+ * @param descriptor_length Descriptor size.
+ */
+void usb_dump_standard_descriptor(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	if (descriptor_length < 2) {
+		return;
+	}
+	int type = descriptor[1];
+
+	descriptor_dump_t *dumper = descriptor_dumpers;
+	while (dumper->dump != NULL) {
+		if ((dumper->id == type) || (dumper->id < 0)) {
+			dumper->dump(output, line_prefix, line_suffix,
+			    descriptor, descriptor_length);
+			return;
+		}
+		dumper++;
+	}
+}
+
+/** Prints single line of USB descriptor dump.
+ * @warning This macro abuses heavily the naming conventions used
+ * by all dumping functions (i.e. names for output file stream (@c output) and
+ * line prefix and suffix (@c line_prefix and @c line_suffix respectively))-
+ *
+ * @param fmt Formatting string.
+ */
+#define PRINTLINE(fmt, ...) \
+	fprintf(output, "%s" fmt "%s", \
+	    line_prefix ? line_prefix : " - ", \
+	    __VA_ARGS__, \
+	    line_suffix ? line_suffix : "\n")
+
+#define BCD_INT(a) (((unsigned int)(a)) / 256)
+#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
+
+#define BCD_FMT "%x.%x"
+#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
+
+static void usb_dump_descriptor_device(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_device_descriptor_t *d
+	    = (usb_standard_device_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bcdUSB = %d (" BCD_FMT ")", d->usb_spec_version,
+	    BCD_ARGS(d->usb_spec_version));
+	PRINTLINE("bDeviceClass = 0x%02x", d->device_class);
+	PRINTLINE("bDeviceSubClass = 0x%02x", d->device_subclass);
+	PRINTLINE("bDeviceProtocol = 0x%02x", d->device_protocol);
+	PRINTLINE("bMaxPacketSize0 = %d", d->max_packet_size);
+	PRINTLINE("idVendor = 0x%04x", d->vendor_id);
+	PRINTLINE("idProduct = 0x%04x", d->product_id);
+	PRINTLINE("bcdDevice = %d", d->device_version);
+	PRINTLINE("iManufacturer = %d", d->str_manufacturer);
+	PRINTLINE("iProduct = %d", d->str_product);
+	PRINTLINE("iSerialNumber = %d", d->str_serial_number);
+	PRINTLINE("bNumConfigurations = %d", d->configuration_count);
+}
+
+static void usb_dump_descriptor_configuration(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_configuration_descriptor_t *d
+	    = (usb_standard_configuration_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	bool self_powered = d->attributes & 64;
+	bool remote_wakeup = d->attributes & 32;
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("wTotalLength = %d", d->total_length);
+	PRINTLINE("bNumInterfaces = %d", d->interface_count);
+	PRINTLINE("bConfigurationValue = %d", d->configuration_number);
+	PRINTLINE("iConfiguration = %d", d->str_configuration);
+	PRINTLINE("bmAttributes = %d [%s%s%s]", d->attributes,
+	    self_powered ? "self-powered" : "",
+	    (self_powered & remote_wakeup) ? ", " : "",
+	    remote_wakeup ? "remote-wakeup" : "");
+	PRINTLINE("MaxPower = %d (%dmA)", d->max_power,
+	    2 * d->max_power);
+}
+
+static void usb_dump_descriptor_interface(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_interface_descriptor_t *d
+	    = (usb_standard_interface_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bInterfaceNumber = %d", d->interface_number);
+	PRINTLINE("bAlternateSetting = %d", d->alternate_setting);
+	PRINTLINE("bNumEndpoints = %d", d->endpoint_count);
+	PRINTLINE("bInterfaceClass = %s", d->interface_class == 0
+	    ? "reserved (0)" : usb_str_class(d->interface_class));
+	PRINTLINE("bInterfaceSubClass = %d", d->interface_subclass);
+	PRINTLINE("bInterfaceProtocol = %d", d->interface_protocol);
+	PRINTLINE("iInterface = %d", d->str_interface);
+}
+
+static void usb_dump_descriptor_string(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+}
+
+static void usb_dump_descriptor_endpoint(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_endpoint_descriptor_t *d
+	   = (usb_standard_endpoint_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	int endpoint = d->endpoint_address & 15;
+	usb_direction_t direction = d->endpoint_address & 128
+	    ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	usb_transfer_type_t transfer_type = d->attributes & 3;
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02X", d->descriptor_type);
+	PRINTLINE("bEndpointAddress = 0x%02X [%d, %s]",
+	    d->endpoint_address, endpoint,
+	    direction == USB_DIRECTION_IN ? "in" : "out");
+	PRINTLINE("bmAttributes = %d [%s]", d->attributes,
+	    usb_str_transfer_type(transfer_type));
+	PRINTLINE("wMaxPacketSize = %d", d->max_packet_size);
+	PRINTLINE("bInterval = %dms", d->poll_interval);
+}
+
+static void usb_dump_descriptor_hid(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_hid_descriptor_t *d
+	    = (usb_standard_hid_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bcdHID = %d (" BCD_FMT ")", d->spec_release,
+	    BCD_ARGS(d->spec_release));
+	PRINTLINE("bCountryCode = %d", d->country_code);
+	PRINTLINE("bNumDescriptors = %d", d->class_desc_count);
+	PRINTLINE("bDescriptorType = %d", d->report_desc_info.type);
+	PRINTLINE("wDescriptorLength = %d", d->report_desc_info.length);
+
+	/* Print info about report descriptors. */
+	size_t i;
+	size_t count = (descriptor_length - sizeof(*d))
+	    / sizeof(usb_standard_hid_class_descriptor_info_t);
+	usb_standard_hid_class_descriptor_info_t *d2
+	    = (usb_standard_hid_class_descriptor_info_t *)
+	    (descriptor + sizeof(*d));
+	for (i = 0; i < count; i++, d2++) {
+		PRINTLINE("bDescriptorType = %d", d2->type);
+		PRINTLINE("wDescriptorLength = %d", d2->length);
+	}
+}
+
+static void usb_dump_descriptor_hub(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	/* TODO */
+}
+
+static void usb_dump_descriptor_generic(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	/* TODO */
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/hc.c
===================================================================
--- uspace/lib/usb/src/hc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/src/hc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2011 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 libusb
+ * @{
+ */
+/** @file
+ * General communication with host controller driver (implementation).
+ */
+#include <devman.h>
+#include <async.h>
+#include <dev_iface.h>
+#include <usb_iface.h>
+#include <usbhc_iface.h>
+#include <usb/hc.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param device Device connecting to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *connection,
+    ddf_dev_t *device)
+{
+	assert(connection);
+
+	if (device == NULL) {
+		return EBADMEM;
+	}
+
+	devman_handle_t hc_handle;
+	int rc = usb_hc_find(device->handle, &hc_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_hc_connection_initialize(connection, hc_handle);
+
+	return rc;
+}
+
+/** Manually initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param hc_handle Devman handle of the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_initialize(usb_hc_connection_t *connection,
+    devman_handle_t hc_handle)
+{
+	assert(connection);
+
+	connection->hc_handle = hc_handle;
+	connection->hc_sess = NULL;
+
+	return EOK;
+}
+
+/** Open connection to host controller.
+ *
+ * @param connection Connection to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_open(usb_hc_connection_t *connection)
+{
+	assert(connection);
+	
+	if (usb_hc_connection_is_opened(connection))
+		return EBUSY;
+	
+	async_sess_t *sess = devman_device_connect(EXCHANGE_ATOMIC,
+	    connection->hc_handle, 0);
+	if (!sess)
+		return ENOMEM;
+	
+	connection->hc_sess = sess;
+	return EOK;
+}
+
+/** Tells whether connection to host controller is opened.
+ *
+ * @param connection Connection to the host controller.
+ * @return Whether connection is opened.
+ */
+bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
+{
+	assert(connection);
+	return (connection->hc_sess != NULL);
+}
+
+/** Close connection to the host controller.
+ *
+ * @param connection Connection to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_close(usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	if (!usb_hc_connection_is_opened(connection)) {
+		return ENOENT;
+	}
+
+	int rc = async_hangup(connection->hc_sess);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	connection->hc_sess = NULL;
+
+	return EOK;
+}
+
+/** Get handle of USB device with given address.
+ *
+ * @param[in] connection Opened connection to host controller.
+ * @param[in] address Address of device in question.
+ * @param[out] handle Where to write the device handle.
+ * @return Error code.
+ */
+int usb_hc_get_handle_by_address(usb_hc_connection_t *connection,
+    usb_address_t address, devman_handle_t *handle)
+{
+	if (!usb_hc_connection_is_opened(connection))
+		return ENOENT;
+	
+	async_exch_t *exch = async_exchange_begin(connection->hc_sess);
+	
+	sysarg_t tmp;
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
+	    address, &tmp);
+	
+	async_exchange_end(exch);
+	
+	if ((rc == EOK) && (handle != NULL))
+		*handle = tmp;
+	
+	return rc;
+}
+
+/** Tell USB address assigned to device with given handle.
+ *
+ * @param dev_handle Devman handle of the USB device in question.
+ * @return USB address or negative error code.
+ */
+usb_address_t usb_hc_get_address_by_handle(devman_handle_t dev_handle)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, dev_handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	async_exch_t *exch = async_exchange_begin(parent_sess);
+	
+	sysarg_t address;
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS,
+	    dev_handle, &address);
+	
+	async_exchange_end(exch);
+	async_hangup(parent_sess);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return (usb_address_t) address;
+}
+
+
+/** Get host controller handle by its class index.
+ *
+ * @param sid Service ID of the HC function.
+ * @param hc_handle Where to store the HC handle
+ *	(can be NULL for existence test only).
+ * @return Error code.
+ */
+int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle)
+{
+	devman_handle_t handle;
+	int rc;
+	
+	rc = devman_fun_sid_to_handle(sid, &handle);
+	if (hc_handle != NULL)
+		*hc_handle = handle;
+	
+	return rc;
+}
+
+/** Find host controller handle that is ancestor of given device.
+ *
+ * @param[in] device_handle Device devman handle.
+ * @param[out] hc_handle Where to store handle of host controller
+ *	controlling device with @p device_handle handle.
+ * @return Error code.
+ */
+int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	async_exch_t *exch = async_exchange_begin(parent_sess);
+	
+	devman_handle_t h;
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
+	
+	async_exchange_end(exch);
+	async_hangup(parent_sess);
+	
+	if (rc != EOK)
+		return rc;
+	
+	if (hc_handle != NULL)
+		*hc_handle = h;
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/resolve.c
===================================================================
--- uspace/lib/usb/src/resolve.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/src/resolve.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2011 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 libusb
+ * @{
+ */
+/** @file
+ *
+ */
+#include <inttypes.h>
+#include <usb/hc.h>
+#include <devman.h>
+#include <errno.h>
+#include <str.h>
+#include <stdio.h>
+
+#define MAX_DEVICE_PATH 1024
+
+static bool try_parse_bus_and_address(const char *path,
+    char **func_start,
+    devman_handle_t *out_hc_handle, usb_address_t *out_device_address)
+{
+	uint64_t sid;
+	size_t address;
+	int rc;
+	char *ptr;
+
+	rc = str_uint64(path, &ptr, 10, false, &sid);
+	if (rc != EOK) {
+		return false;
+	}
+	if ((*ptr == ':') || (*ptr == '.')) {
+		ptr++;
+	} else {
+		return false;
+	}
+	rc = str_size_t(ptr, func_start, 10, false, &address);
+	if (rc != EOK) {
+		return false;
+	}
+	rc = usb_ddf_get_hc_handle_by_sid(sid, out_hc_handle);
+	if (rc != EOK) {
+		return false;
+	}
+	if (out_device_address != NULL) {
+		*out_device_address = (usb_address_t) address;
+	}
+	return true;
+}
+
+static int get_device_handle_by_address(devman_handle_t hc_handle, int addr,
+    devman_handle_t *dev_handle)
+{
+	int rc;
+	usb_hc_connection_t conn;
+
+	usb_hc_connection_initialize(&conn, hc_handle);
+	rc = usb_hc_connection_open(&conn);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle);
+
+	usb_hc_connection_close(&conn);
+
+	return rc;
+}
+
+/** Resolve handle and address of USB device from its path.
+ *
+ * This is a wrapper working on best effort principle.
+ * If the resolving fails, if will not give much details about what
+ * is wrong.
+ * Typically, error from this function would be reported to the user
+ * as "bad device specification" or "device does not exist".
+ *
+ * The path can be specified in following format:
+ *  - devman path (e.g. /hw/pci0/.../usb01_a5
+ *  - bus number and device address (e.g. 5.1)
+ *  - bus number, device address and device function (e.g. 2.1/HID0/keyboard)
+ *
+ * @param[in] dev_path Path to the device.
+ * @param[out] out_hc_handle Where to store handle of a parent host controller.
+ * @param[out] out_dev_addr Where to store device (USB) address.
+ * @param[out] out_dev_handle Where to store device handle.
+ * @return Error code.
+ */
+int usb_resolve_device_handle(const char *dev_path, devman_handle_t *out_hc_handle,
+    usb_address_t *out_dev_addr, devman_handle_t *out_dev_handle)
+{
+	if (dev_path == NULL) {
+		return EBADMEM;
+	}
+
+	bool found_hc = false;
+	bool found_addr = false;
+	devman_handle_t hc_handle, dev_handle;
+	usb_address_t dev_addr = -1;
+	int rc;
+	bool is_bus_addr;
+	char *func_start = NULL;
+	char *path = NULL;
+
+	/* First try the BUS.ADDR format. */
+	is_bus_addr = try_parse_bus_and_address(dev_path, &func_start,
+	    &hc_handle, &dev_addr);
+	if (is_bus_addr) {
+		found_hc = true;
+		found_addr = true;
+		/*
+		 * Now get the handle of the device. We will need that
+		 * in both cases. If there is only BUS.ADDR, it will
+		 * be the handle to be returned to the caller, otherwise
+		 * we will need it to resolve the path to which the
+		 * suffix would be appended.
+		 */
+		/* If there is nothing behind the BUS.ADDR, we will
+		 * get the device handle from the host controller.
+		 * Otherwise, we will
+		 */
+		rc = get_device_handle_by_address(hc_handle, dev_addr,
+		    &dev_handle);
+		if (rc != EOK) {
+			return rc;
+		}
+		if (str_length(func_start) > 0) {
+			char tmp_path[MAX_DEVICE_PATH ];
+			rc = devman_fun_get_path(dev_handle,
+			    tmp_path, MAX_DEVICE_PATH);
+			if (rc != EOK) {
+				return rc;
+			}
+			rc = asprintf(&path, "%s%s", tmp_path, func_start);
+			if (rc < 0) {
+				return ENOMEM;
+			}
+		} else {
+			/* Everything is resolved. Get out of here. */
+			goto copy_out;
+		}
+	} else {
+		path = str_dup(dev_path);
+		if (path == NULL) {
+			return ENOMEM;
+		}
+	}
+
+	/* First try to get the device handle. */
+	rc = devman_fun_get_handle(path, &dev_handle, 0);
+	if (rc != EOK) {
+		free(path);
+		/* Invalid path altogether. */
+		return rc;
+	}
+
+	/* Remove suffixes and hope that we will encounter device node. */
+	while (str_length(path) > 0) {
+		/* Get device handle first. */
+		devman_handle_t tmp_handle;
+		rc = devman_fun_get_handle(path, &tmp_handle, 0);
+		if (rc != EOK) {
+			free(path);
+			return rc;
+		}
+
+		/* Try to find its host controller. */
+		if (!found_hc) {
+			rc = usb_hc_find(tmp_handle, &hc_handle);
+			if (rc == EOK) {
+				found_hc = true;
+			}
+		}
+
+		/* Try to get its address. */
+		if (!found_addr) {
+			dev_addr = usb_hc_get_address_by_handle(tmp_handle);
+			if (dev_addr >= 0) {
+				found_addr = true;
+			}
+		}
+
+		/* Speed-up. */
+		if (found_hc && found_addr) {
+			break;
+		}
+
+		/* Remove the last suffix. */
+		char *slash_pos = str_rchr(path, '/');
+		if (slash_pos != NULL) {
+			*slash_pos = 0;
+		}
+	}
+
+	free(path);
+
+	if (!found_addr || !found_hc) {
+		return ENOENT;
+	}
+
+copy_out:
+	if (out_dev_addr != NULL) {
+		*out_dev_addr = dev_addr;
+	}
+	if (out_hc_handle != NULL) {
+		*out_hc_handle = hc_handle;
+	}
+	if (out_dev_handle != NULL) {
+		*out_dev_handle = dev_handle;
+	}
+
+	return EOK;
+}
+
+
+/**
+ * @}
+ */
+
Index: uspace/lib/usb/src/usb.c
===================================================================
--- uspace/lib/usb/src/usb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usb/src/usb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,120 @@
+/*
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Common USB functions.
+ */
+#include <usb/usb.h>
+#include <errno.h>
+
+#define ARR_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
+
+static const char *str_speed[] = {
+	"low",
+	"full",
+	"high"
+};
+
+static const char *str_transfer_type[] = {
+	"control",
+	"isochronous",
+	"bulk",
+	"interrupt"
+};
+
+static const char *str_transfer_type_short[] = {
+	"ctrl",
+	"iso",
+	"bulk",
+	"intr"
+};
+
+static const char *str_direction[] = {
+	"in",
+	"out",
+	"both"
+};
+
+/** String representation for USB transfer type.
+ *
+ * @param t Transfer type.
+ * @return Transfer type as a string (in English).
+ */
+const char *usb_str_transfer_type(usb_transfer_type_t t)
+{
+	if (t >= ARR_SIZE(str_transfer_type)) {
+		return "invalid";
+	}
+	return str_transfer_type[t];
+}
+
+/** String representation for USB transfer type (short version).
+ *
+ * @param t Transfer type.
+ * @return Transfer type as a short string for debugging messages.
+ */
+const char *usb_str_transfer_type_short(usb_transfer_type_t t)
+{
+	if (t >= ARR_SIZE(str_transfer_type_short)) {
+		return "invl";
+	}
+	return str_transfer_type_short[t];
+}
+
+/** String representation of USB direction.
+ *
+ * @param d The direction.
+ * @return Direction as a string (in English).
+ */
+const char *usb_str_direction(usb_direction_t d)
+{
+	if (d >= ARR_SIZE(str_direction)) {
+		return "invalid";
+	}
+	return str_direction[d];
+}
+
+/** String representation of USB speed.
+ *
+ * @param s The speed.
+ * @return USB speed as a string (in English).
+ */
+const char *usb_str_speed(usb_speed_t s)
+{
+	if (s >= ARR_SIZE(str_speed)) {
+		return "invalid";
+	}
+	return str_speed[s];
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/Makefile
===================================================================
--- uspace/lib/usbdev/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+LIBRARY = libusbdev
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include \
+	-Iinclude
+
+SOURCES = \
+	src/altiface.c \
+	src/devdrv.c \
+	src/devpoll.c \
+	src/dp.c \
+	src/hub.c \
+	src/pipepriv.c \
+	src/pipepriv.h \
+	src/pipes.c \
+	src/pipesinit.c \
+	src/pipesio.c \
+	src/recognise.c \
+	src/request.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usbdev/include/usb/dev/dp.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/dp.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/include/usb/dev/dp.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * USB descriptor parser.
+ */
+#ifndef LIBUSBDEV_DP_H_
+#define LIBUSBDEV_DP_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/descriptor.h>
+
+/** USB descriptors nesting.
+ * The nesting describes the logical tree USB descriptors form
+ * (e.g. that endpoint descriptor belongs to interface or that
+ * interface belongs to configuration).
+ *
+ * See usb_descriptor_type_t for descriptor constants.
+ */
+typedef struct {
+	/** Child descriptor id. */
+	int child;
+	/** Parent descriptor id. */
+	int parent;
+} usb_dp_descriptor_nesting_t;
+
+extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
+
+/** Descriptor parser structure. */
+typedef struct {
+	/** Used descriptor nesting. */
+	usb_dp_descriptor_nesting_t *nesting;
+} usb_dp_parser_t;
+
+/** Descriptor parser data. */
+typedef struct {
+	/** Data to be parsed. */
+	uint8_t *data;
+	/** Size of input data in bytes. */
+	size_t size;
+	/** Custom argument. */
+	void *arg;
+} usb_dp_parser_data_t;
+
+uint8_t *usb_dp_get_nested_descriptor(usb_dp_parser_t *,
+    usb_dp_parser_data_t *, uint8_t *);
+uint8_t *usb_dp_get_sibling_descriptor(usb_dp_parser_t *,
+    usb_dp_parser_data_t *, uint8_t *, uint8_t *);
+
+void usb_dp_walk_simple(uint8_t *, size_t, usb_dp_descriptor_nesting_t *,
+    void (*)(uint8_t *, size_t, void *), void *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/include/usb/dev/driver.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/driver.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/include/usb/dev/driver.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * USB device driver framework.
+ */
+#ifndef LIBUSBDEV_DRIVER_H_
+#define LIBUSBDEV_DRIVER_H_
+
+#include <usb/dev/pipes.h>
+
+/** Descriptors for USB device. */
+typedef struct {
+	/** Standard device descriptor. */
+	usb_standard_device_descriptor_t device;
+	/** Full configuration descriptor of current configuration. */
+	uint8_t *configuration;
+	size_t configuration_size;
+} usb_device_descriptors_t;
+
+/** Wrapper for data related to alternate interface setting.
+ * The pointers will typically point inside configuration descriptor and
+ * thus you shall not deallocate them.
+ */
+typedef struct {
+	/** Interface descriptor. */
+	usb_standard_interface_descriptor_t *interface;
+	/** Pointer to start of descriptor tree bound with this interface. */
+	uint8_t *nested_descriptors;
+	/** Size of data pointed by nested_descriptors in bytes. */
+	size_t nested_descriptors_size;
+} usb_alternate_interface_descriptors_t;
+
+/** Alternate interface settings. */
+typedef struct {
+	/** Array of alternate interfaces descriptions. */
+	usb_alternate_interface_descriptors_t *alternatives;
+	/** Size of @c alternatives array. */
+	size_t alternative_count;
+	/** Index of currently selected one. */
+	size_t current;
+} usb_alternate_interfaces_t;
+
+/** USB device structure. */
+typedef struct {
+	/** The default control pipe. */
+	usb_pipe_t ctrl_pipe;
+	/** Other endpoint pipes.
+	 * This is an array of other endpoint pipes in the same order as
+	 * in usb_driver_t.
+	 */
+	usb_endpoint_mapping_t *pipes;
+	/** Number of other endpoint pipes. */
+	size_t pipes_count;
+	/** Current interface.
+	 * Usually, drivers operate on single interface only.
+	 * This item contains the value of the interface or -1 for any.
+	 */
+	int interface_no;
+
+	/** Alternative interfaces.
+	 * Set to NULL when the driver controls whole device
+	 * (i.e. more (or any) interfaces).
+	 */
+	usb_alternate_interfaces_t *alternate_interfaces;
+
+	/** Some useful descriptors. */
+	usb_device_descriptors_t descriptors;
+
+	/** Generic DDF device backing this one. */
+	ddf_dev_t *ddf_dev;
+	/** Custom driver data.
+	 * Do not use the entry in generic device, that is already used
+	 * by the framework.
+	 */
+	void *driver_data;
+
+	/** Connection backing the pipes.
+	 * Typically, you will not need to use this attribute at all.
+	 */
+	usb_device_connection_t wire;
+} usb_device_t;
+
+/** USB driver ops. */
+typedef struct {
+	/** Callback when new device is about to be controlled by the driver. */
+	int (*add_device)(usb_device_t *);
+} usb_driver_ops_t;
+
+/** USB driver structure. */
+typedef struct {
+	/** Driver name.
+	 * This name is copied to the generic driver name and must be exactly
+	 * the same as the directory name where the driver executable resides.
+	 */
+	const char *name;
+	/** Expected endpoints description.
+	 * This description shall exclude default control endpoint (pipe zero)
+	 * and must be NULL terminated.
+	 * When only control endpoint is expected, you may set NULL directly
+	 * without creating one item array containing NULL.
+	 *
+	 * When the driver expect single interrupt in endpoint,
+	 * the initialization may look like this:
+\code
+static usb_endpoint_description_t poll_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_HUB,
+	.interface_subclass = 0,
+	.interface_protocol = 0,
+	.flags = 0
+};
+
+static usb_endpoint_description_t *hub_endpoints[] = {
+	&poll_endpoint_description,
+	NULL
+};
+
+static usb_driver_t hub_driver = {
+	.endpoints = hub_endpoints,
+	...
+};
+\endcode
+	 */
+	usb_endpoint_description_t **endpoints;
+	/** Driver ops. */
+	usb_driver_ops_t *ops;
+} usb_driver_t;
+
+int usb_driver_main(usb_driver_t *);
+
+int usb_device_select_interface(usb_device_t *, uint8_t,
+    usb_endpoint_description_t **);
+
+int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
+int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
+    usb_endpoint_description_t **, uint8_t *, size_t, int, int,
+    usb_endpoint_mapping_t **, size_t *);
+int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
+int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);
+void usb_device_destroy(usb_device_t *);
+
+size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
+int usb_alternate_interfaces_create(uint8_t *, size_t, int,
+    usb_alternate_interfaces_t **);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/include/usb/dev/hub.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/include/usb/dev/hub.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Functions needed by hub drivers.
+ *
+ * For class specific requests, see usb/classes/hub.h.
+ */
+#ifndef LIBUSBDEV_HUB_H_
+#define LIBUSBDEV_HUB_H_
+
+#include <sys/types.h>
+#include <usb/hc.h>
+
+int usb_hc_new_device_wrapper(ddf_dev_t *, usb_hc_connection_t *, usb_speed_t,
+    int (*)(int, void *), int, void *,
+    usb_address_t *, devman_handle_t *,
+    ddf_dev_ops_t *, void *, ddf_fun_t **);
+
+/** Info about device attached to host controller.
+ *
+ * This structure exists only to keep the same signature of
+ * usb_hc_register_device() when more properties of the device
+ * would have to be passed to the host controller.
+ */
+typedef struct {
+	/** Device address. */
+	usb_address_t address;
+	/** Devman handle of the device. */
+	devman_handle_t handle;
+} usb_hc_attached_device_t;
+
+usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
+int usb_hc_register_device(usb_hc_connection_t *,
+    const usb_hc_attached_device_t *);
+int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/include/usb/dev/pipes.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/pipes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/include/usb/dev/pipes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * USB pipes representation.
+ */
+#ifndef LIBUSBDEV_PIPES_H_
+#define LIBUSBDEV_PIPES_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/hc.h>
+#include <usb/descriptor.h>
+#include <ipc/devman.h>
+#include <ddf/driver.h>
+#include <fibril_synch.h>
+#include <async.h>
+
+/** Abstraction of a physical connection to the device.
+ * This type is an abstraction of the USB wire that connects the host and
+ * the function (device).
+ */
+typedef struct {
+	/** Handle of the host controller device is connected to. */
+	devman_handle_t hc_handle;
+	/** Address of the device. */
+	usb_address_t address;
+} usb_device_connection_t;
+
+/** Abstraction of a logical connection to USB device endpoint.
+ * It encapsulates endpoint attributes (transfer type etc.) as well
+ * as information about currently running sessions.
+ * This endpoint must be bound with existing usb_device_connection_t
+ * (i.e. the wire to send data over).
+ *
+ * Locking order: if you want to lock both mutexes
+ * (@c guard and @c hc_sess_mutex), lock @c guard first.
+ * It is not necessary to lock @c guard if you want to lock @c hc_sess_mutex
+ * only.
+ */
+typedef struct {
+	/** Guard of the whole pipe. */
+	fibril_mutex_t guard;
+
+	/** The connection used for sending the data. */
+	usb_device_connection_t *wire;
+
+	/** Endpoint number. */
+	usb_endpoint_t endpoint_no;
+
+	/** Endpoint transfer type. */
+	usb_transfer_type_t transfer_type;
+
+	/** Endpoint direction. */
+	usb_direction_t direction;
+
+	/** Maximum packet size for the endpoint. */
+	size_t max_packet_size;
+
+	/** Session to the host controller.
+	 * NULL when no session is active.
+	 * It is an error to access this member without @c hc_sess_mutex
+	 * being locked.
+	 * If call over the phone is to be made, it must be preceeded by
+	 * call to pipe_add_ref() [internal libusb function].
+	 */
+	async_sess_t *hc_sess;
+
+	/** Guard for serialization of requests over the session. */
+	fibril_mutex_t hc_sess_mutex;
+
+	/** Number of active transfers over the pipe. */
+	int refcount;
+	/** Number of failed attempts to open the HC phone.
+	 * When user requests usb_pipe_start_long_transfer() and the operation
+	 * fails, there is no way to report this to the user.
+	 * That the soft reference counter is increased to record the attempt.
+	 * When the user then request e.g. usb_pipe_read(), it will try to
+	 * add reference as well.
+	 * If that fails, it is reported to the user. If it is okay, the
+	 * real reference counter is incremented.
+	 * The problem might arise when ending the long transfer (since
+	 * the number of references would be only 1, but logically it shall be
+	 * two).
+	 * Decrementing the soft counter first shall solve this.
+	 */
+	int refcount_soft;
+
+	/** Whether to automatically reset halt on the endpoint.
+	 * Valid only for control endpoint zero.
+	 */
+	bool auto_reset_halt;
+} usb_pipe_t;
+
+
+/** Description of endpoint characteristics. */
+typedef struct {
+	/** Transfer type (e.g. control or interrupt). */
+	usb_transfer_type_t transfer_type;
+	/** Transfer direction (to or from a device). */
+	usb_direction_t direction;
+	/** Interface class this endpoint belongs to (-1 for any). */
+	int interface_class;
+	/** Interface subclass this endpoint belongs to (-1 for any). */
+	int interface_subclass;
+	/** Interface protocol this endpoint belongs to (-1 for any). */
+	int interface_protocol;
+	/** Extra endpoint flags. */
+	unsigned int flags;
+} usb_endpoint_description_t;
+
+/** Mapping of endpoint pipes and endpoint descriptions. */
+typedef struct {
+	/** Endpoint pipe. */
+	usb_pipe_t *pipe;
+	/** Endpoint description. */
+	const usb_endpoint_description_t *description;
+	/** Interface number the endpoint must belong to (-1 for any). */
+	int interface_no;
+	/** Alternate interface setting to choose. */
+	int interface_setting;
+	/** Found descriptor fitting the description. */
+	usb_standard_endpoint_descriptor_t *descriptor;
+	/** Interface descriptor the endpoint belongs to. */
+	usb_standard_interface_descriptor_t *interface;
+	/** Whether the endpoint was actually found. */
+	bool present;
+} usb_endpoint_mapping_t;
+
+int usb_device_connection_initialize_on_default_address(
+    usb_device_connection_t *, usb_hc_connection_t *);
+int usb_device_connection_initialize_from_device(usb_device_connection_t *,
+    ddf_dev_t *);
+int usb_device_connection_initialize(usb_device_connection_t *,
+    devman_handle_t, usb_address_t);
+
+int usb_device_get_assigned_interface(ddf_dev_t *);
+
+int usb_pipe_initialize(usb_pipe_t *, usb_device_connection_t *,
+    usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t);
+int usb_pipe_initialize_default_control(usb_pipe_t *,
+    usb_device_connection_t *);
+int usb_pipe_probe_default_control(usb_pipe_t *);
+int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
+    size_t, uint8_t *, size_t, usb_device_connection_t *);
+int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t,
+    unsigned int, usb_hc_connection_t *);
+int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
+int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
+
+void usb_pipe_start_long_transfer(usb_pipe_t *);
+void usb_pipe_end_long_transfer(usb_pipe_t *);
+
+int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
+int usb_pipe_write(usb_pipe_t *, void *, size_t);
+
+int usb_pipe_control_read(usb_pipe_t *, void *, size_t,
+    void *, size_t, size_t *);
+int usb_pipe_control_write(usb_pipe_t *, void *, size_t,
+    void *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/include/usb/dev/poll.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/poll.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/include/usb/dev/poll.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * USB device polling functions.
+ */
+#ifndef LIBUSBDEV_POLL_H_
+#define LIBUSBDEV_POLL_H_
+
+#include <usb/dev/driver.h>
+#include <time.h>
+
+typedef struct {
+	/** Level of debugging messages from auto polling.
+	 * 0 - nothing
+	 * 1 - inform about errors and polling start/end
+	 * 2 - also dump every retrieved buffer
+	 */
+	int debug;
+	/** Maximum number of consecutive errors before polling termination. */
+	size_t max_failures;
+	/** Delay between poll requests in milliseconds.
+	 * Set to negative value to use value from endpoint descriptor.
+	 */
+	int delay;
+	/** Whether to automatically try to clear the HALT feature after
+	 * the endpoint stalls.
+	 */
+	bool auto_clear_halt;
+	/** Callback when data arrives.
+	 *
+	 * @param dev Device that was polled.
+	 * @param data Data buffer (in USB endianness).
+	 * @param data_size Size of the @p data buffer in bytes.
+	 * @param arg Custom argument.
+	 * @return Whether to continue in polling.
+	 */
+	bool (*on_data)(usb_device_t *dev, uint8_t *data, size_t data_size,
+	    void *arg);
+	/** Callback when polling is terminated.
+	 *
+	 * @param dev Device where the polling was terminated.
+	 * @param due_to_errors Whether polling stopped due to several failures.
+	 * @param arg Custom argument.
+	 */
+	void (*on_polling_end)(usb_device_t *dev, bool due_to_errors,
+	    void *arg);
+	/** Callback when error occurs.
+	 *
+	 * @param dev Device where error occurred.
+	 * @param err_code Error code (as returned from usb_pipe_read).
+	 * @param arg Custom argument.
+	 * @return Whether to continue in polling.
+	 */
+	bool (*on_error)(usb_device_t *dev, int err_code, void *arg);
+} usb_device_auto_polling_t;
+
+int usb_device_auto_polling(usb_device_t *, size_t, usb_device_auto_polling_t *,
+    size_t, void *);
+
+typedef bool (*usb_polling_callback_t)(usb_device_t *,
+    uint8_t *, size_t, void *);
+typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
+
+int usb_device_auto_poll(usb_device_t *, size_t,
+    usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/include/usb/dev/recognise.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/recognise.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/include/usb/dev/recognise.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * USB device recognition.
+ */
+#ifndef LIBUSBDEV_RECOGNISE_H_
+#define LIBUSBDEV_RECOGNISE_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <ipc/devman.h>
+
+int usb_device_create_match_ids_from_device_descriptor(
+    const usb_standard_device_descriptor_t *, match_id_list_t *);
+
+int usb_device_create_match_ids_from_interface(
+    const usb_standard_device_descriptor_t *,
+    const usb_standard_interface_descriptor_t *, match_id_list_t *);
+
+int usb_device_create_match_ids(usb_pipe_t *, match_id_list_t *);
+
+int usb_device_register_child_in_devman(usb_address_t, devman_handle_t,
+    ddf_dev_t *, devman_handle_t *, ddf_dev_ops_t *, void *, ddf_fun_t **);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/include/usb/dev/request.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/request.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/include/usb/dev/request.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Standard USB requests.
+ */
+#ifndef LIBUSBDEV_REQUEST_H_
+#define LIBUSBDEV_REQUEST_H_
+
+#include <sys/types.h>
+#include <l18n/langs.h>
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/descriptor.h>
+
+/** USB device status - device is self powered (opposed to bus powered). */
+#define USB_DEVICE_STATUS_SELF_POWERED ((uint16_t)(1 << 0))
+
+/** USB device status - remote wake-up signaling is enabled. */
+#define USB_DEVICE_STATUS_REMOTE_WAKEUP ((uint16_t)(1 << 1))
+
+/** USB endpoint status - endpoint is halted (stalled). */
+#define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0))
+
+/** USB feature selector - endpoint halt (stall). */
+#define USB_FEATURE_SELECTOR_ENDPOINT_HALT (0)
+
+/** USB feature selector - device remote wake-up. */
+#define USB_FEATURE_SELECTOR_REMOTE_WAKEUP (1)
+
+/** Standard device request. */
+typedef enum {
+	USB_DEVREQ_GET_STATUS = 0,
+	USB_DEVREQ_CLEAR_FEATURE = 1,
+	USB_DEVREQ_SET_FEATURE = 3,
+	USB_DEVREQ_SET_ADDRESS = 5,
+	USB_DEVREQ_GET_DESCRIPTOR = 6,
+	USB_DEVREQ_SET_DESCRIPTOR = 7,
+	USB_DEVREQ_GET_CONFIGURATION = 8,
+	USB_DEVREQ_SET_CONFIGURATION = 9,
+	USB_DEVREQ_GET_INTERFACE = 10,
+	USB_DEVREQ_SET_INTERFACE = 11,
+	USB_DEVREQ_SYNCH_FRAME = 12,
+	USB_DEVREQ_LAST_STD
+} usb_stddevreq_t;
+
+/** Device request setup packet.
+ * The setup packet describes the request.
+ */
+typedef struct {
+	/** Request type.
+	 * The type combines transfer direction, request type and
+	 * intended recipient.
+	 */
+	uint8_t request_type;
+	/** Request identification. */
+	uint8_t request;
+	/** Main parameter to the request. */
+	union {
+		uint16_t value;
+		/* FIXME: add #ifdefs according to host endianness */
+		struct {
+			uint8_t value_low;
+			uint8_t value_high;
+		};
+	};
+	/** Auxiliary parameter to the request.
+	 * Typically, it is offset to something.
+	 */
+	uint16_t index;
+	/** Length of extra data. */
+	uint16_t length;
+} __attribute__ ((packed)) usb_device_request_setup_packet_t;
+
+int usb_control_request_set(usb_pipe_t *,
+    usb_request_type_t, usb_request_recipient_t, uint8_t,
+    uint16_t, uint16_t, void *, size_t);
+
+int usb_control_request_get(usb_pipe_t *,
+    usb_request_type_t, usb_request_recipient_t, uint8_t,
+    uint16_t, uint16_t, void *, size_t, size_t *);
+
+int usb_request_get_status(usb_pipe_t *, usb_request_recipient_t,
+    uint16_t, uint16_t *);
+int usb_request_clear_feature(usb_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint16_t, uint16_t);
+int usb_request_set_feature(usb_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint16_t, uint16_t);
+int usb_request_set_address(usb_pipe_t *, usb_address_t);
+int usb_request_get_descriptor(usb_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t, 
+    size_t *);
+int usb_request_get_descriptor_alloc(usb_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void **, size_t *);
+int usb_request_get_device_descriptor(usb_pipe_t *,
+    usb_standard_device_descriptor_t *);
+int usb_request_get_bare_configuration_descriptor(usb_pipe_t *, int,
+    usb_standard_configuration_descriptor_t *);
+int usb_request_get_full_configuration_descriptor(usb_pipe_t *, int,
+    void *, size_t, size_t *);
+int usb_request_get_full_configuration_descriptor_alloc(usb_pipe_t *,
+    int, void **, size_t *);
+int usb_request_set_descriptor(usb_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t);
+int usb_request_get_configuration(usb_pipe_t *, uint8_t *);
+int usb_request_set_configuration(usb_pipe_t *, uint8_t);
+int usb_request_get_interface(usb_pipe_t *, uint8_t, uint8_t *);
+int usb_request_set_interface(usb_pipe_t *, uint8_t, uint8_t);
+
+int usb_request_get_supported_languages(usb_pipe_t *,
+    l18_win_locales_t **, size_t *);
+int usb_request_get_string(usb_pipe_t *, size_t, l18_win_locales_t,
+    char **);
+
+int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t);
+int usb_pipe_clear_halt(usb_pipe_t *, usb_pipe_t *);
+int usb_request_get_endpoint_status(usb_pipe_t *, usb_pipe_t *, uint16_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/altiface.c
===================================================================
--- uspace/lib/usbdev/src/altiface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/altiface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Handling alternate interface settings.
+ */
+#include <usb/dev/driver.h>
+#include <usb/dev/request.h>
+#include <usb/debug.h>
+#include <usb/dev/dp.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+
+/** Count number of alternate settings of a interface.
+ *
+ * @param config_descr Full configuration descriptor.
+ * @param config_descr_size Size of @p config_descr in bytes.
+ * @param interface_no Interface number.
+ * @return Number of alternate interfaces for @p interface_no interface.
+ */
+size_t usb_interface_count_alternates(uint8_t *config_descr,
+    size_t config_descr_size, uint8_t interface_no)
+{
+	assert(config_descr != NULL);
+	assert(config_descr_size > 0);
+
+	usb_dp_parser_t dp_parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+	usb_dp_parser_data_t dp_data = {
+		.data = config_descr,
+		.size = config_descr_size,
+		.arg = NULL
+	};
+
+	size_t alternate_count = 0;
+
+	uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
+	    &dp_data, config_descr);
+	while (iface_ptr != NULL) {
+		usb_standard_interface_descriptor_t *iface
+		    = (usb_standard_interface_descriptor_t *) iface_ptr;
+		if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
+			if (iface->interface_number == interface_no) {
+				alternate_count++;
+			}
+		}
+		iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
+		    config_descr, iface_ptr);
+	}
+
+	return alternate_count;
+}
+
+/** Create alternate interface representation structure.
+ *
+ * @param[in] config_descr Configuration descriptor.
+ * @param[in] config_descr_size Size of configuration descriptor.
+ * @param[in] interface_number Interface number.
+ * @param[out] alternates_ptr Where to store pointer to allocated structure.
+ * @return Error code.
+ */
+int usb_alternate_interfaces_create(uint8_t *config_descr,
+    size_t config_descr_size, int interface_number,
+    usb_alternate_interfaces_t **alternates_ptr)
+{
+	assert(alternates_ptr != NULL);
+	assert(config_descr != NULL);
+	assert(config_descr_size > 0);
+
+	if (interface_number < 0) {
+		alternates_ptr = NULL;
+		return EOK;
+	}
+
+	usb_alternate_interfaces_t *alternates
+	    = malloc(sizeof(usb_alternate_interfaces_t));
+
+	if (alternates == NULL) {
+		return ENOMEM;
+	}
+
+	alternates->alternative_count
+	    = usb_interface_count_alternates(config_descr, config_descr_size,
+	    interface_number);
+
+	if (alternates->alternative_count == 0) {
+		free(alternates);
+		return ENOENT;
+	}
+
+	alternates->alternatives = malloc(alternates->alternative_count
+	    * sizeof(usb_alternate_interface_descriptors_t));
+	if (alternates->alternatives == NULL) {
+		free(alternates);
+		return ENOMEM;
+	}
+
+	alternates->current = 0;
+
+	usb_dp_parser_t dp_parser = {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+	usb_dp_parser_data_t dp_data = {
+		.data = config_descr,
+		.size = config_descr_size,
+		.arg = NULL
+	};
+
+	usb_alternate_interface_descriptors_t *cur_alt_iface
+	    = &alternates->alternatives[0];
+
+	uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
+	    &dp_data, dp_data.data);
+	while (iface_ptr != NULL) {
+		usb_standard_interface_descriptor_t *iface
+		    = (usb_standard_interface_descriptor_t *) iface_ptr;
+		if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
+		    || (iface->interface_number != interface_number)) {
+			iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
+			    &dp_data,
+			    dp_data.data, iface_ptr);
+			continue;
+		}
+
+		cur_alt_iface->interface = iface;
+		cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
+
+		/* Find next interface to count size of nested descriptors. */
+		iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
+		    dp_data.data, iface_ptr);
+		if (iface_ptr == NULL) {
+			uint8_t *next = dp_data.data + dp_data.size;
+			cur_alt_iface->nested_descriptors_size
+			    = next - cur_alt_iface->nested_descriptors;
+		} else {
+			cur_alt_iface->nested_descriptors_size
+			    = iface_ptr - cur_alt_iface->nested_descriptors;
+		}
+
+		cur_alt_iface++;
+	}
+
+	*alternates_ptr = alternates;
+
+	return EOK;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/devdrv.c
===================================================================
--- uspace/lib/usbdev/src/devdrv.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/devdrv.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * USB device driver framework.
+ */
+#include <usb/dev/driver.h>
+#include <usb/dev/request.h>
+#include <usb/debug.h>
+#include <usb/dev/dp.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+
+static int generic_add_device(ddf_dev_t *);
+
+static driver_ops_t generic_driver_ops = {
+	.add_device = generic_add_device
+};
+static driver_t generic_driver = {
+	.driver_ops = &generic_driver_ops
+};
+
+static usb_driver_t *driver = NULL;
+
+
+/** Main routine of USB device driver.
+ *
+ * Under normal conditions, this function never returns.
+ *
+ * @param drv USB device driver structure.
+ * @return Task exit status.
+ */
+int usb_driver_main(usb_driver_t *drv)
+{
+	assert(drv != NULL);
+
+	/* Prepare the generic driver. */
+	generic_driver.name = drv->name;
+
+	driver = drv;
+
+	return ddf_driver_main(&generic_driver);
+}
+
+/** Count number of pipes the driver expects.
+ *
+ * @param drv USB driver.
+ * @return Number of pipes (excluding default control pipe).
+ */
+static size_t count_other_pipes(usb_endpoint_description_t **endpoints)
+{
+	size_t count = 0;
+	if (endpoints == NULL) {
+		return 0;
+	}
+
+	while (endpoints[count] != NULL) {
+		count++;
+	}
+
+	return count;
+}
+
+/** Initialize endpoint pipes, excluding default control one.
+ *
+ * @param drv The device driver.
+ * @param dev Device to be initialized.
+ * @return Error code.
+ */
+static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
+    usb_device_t *dev, int alternate_setting)
+{
+	if (endpoints == NULL) {
+		dev->pipes = NULL;
+		dev->pipes_count = 0;
+		return EOK;
+	}
+
+	usb_endpoint_mapping_t *pipes;
+	size_t pipes_count;
+
+	int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
+	    dev->descriptors.configuration, dev->descriptors.configuration_size,
+	    dev->interface_no, alternate_setting,
+	    &pipes, &pipes_count);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	dev->pipes = pipes;
+	dev->pipes_count = pipes_count;
+
+	return EOK;
+}
+
+/** Callback when new device is supposed to be controlled by this driver.
+ *
+ * This callback is a wrapper for USB specific version of @c add_device.
+ *
+ * @param gen_dev Device structure as prepared by DDF.
+ * @return Error code.
+ */
+int generic_add_device(ddf_dev_t *gen_dev)
+{
+	assert(driver);
+	assert(driver->ops);
+	assert(driver->ops->add_device);
+
+	int rc;
+
+	usb_device_t *dev = NULL;
+	const char *err_msg = NULL;
+	rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);
+	if (rc != EOK) {
+		usb_log_error("USB device `%s' creation failed (%s): %s.\n",
+		    gen_dev->name, err_msg, str_error(rc));
+		return rc;
+	}
+
+	return driver->ops->add_device(dev);
+}
+
+/** Destroy existing pipes of a USB device.
+ *
+ * @param dev Device where to destroy the pipes.
+ * @return Error code.
+ */
+static int destroy_current_pipes(usb_device_t *dev)
+{
+	int rc = usb_device_destroy_pipes(dev->ddf_dev,
+	    dev->pipes, dev->pipes_count);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	dev->pipes = NULL;
+	dev->pipes_count = 0;
+
+	return EOK;
+}
+
+/** Change interface setting of a device.
+ * This function selects new alternate setting of an interface by issuing
+ * proper USB command to the device and also creates new USB pipes
+ * under @c dev->pipes.
+ *
+ * @warning This function is intended for drivers working at interface level.
+ * For drivers controlling the whole device, you need to change interface
+ * manually using usb_request_set_interface() and creating new pipes
+ * with usb_pipe_initialize_from_configuration().
+ *
+ * @warning This is a wrapper function that does several operations that
+ * can fail and that cannot be rollbacked easily. That means that a failure
+ * during the SET_INTERFACE request would result in having a device with
+ * no pipes at all (except the default control one). That is because the old
+ * pipes needs to be unregistered at HC first and the new ones could not
+ * be created.
+ *
+ * @param dev USB device.
+ * @param alternate_setting Alternate setting to choose.
+ * @param endpoints New endpoint descriptions.
+ * @return Error code.
+ */
+int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting,
+    usb_endpoint_description_t **endpoints)
+{
+	if (dev->interface_no < 0) {
+		return EINVAL;
+	}
+
+	int rc;
+
+	/* Destroy existing pipes. */
+	rc = destroy_current_pipes(dev);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Change the interface itself. */
+	rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
+	    alternate_setting);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Create new pipes. */
+	rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
+
+	return rc;
+}
+
+/** Retrieve basic descriptors from the device.
+ *
+ * @param[in] ctrl_pipe Control endpoint pipe.
+ * @param[out] descriptors Where to store the descriptors.
+ * @return Error code.
+ */
+int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe,
+    usb_device_descriptors_t *descriptors)
+{
+	assert(descriptors != NULL);
+
+	descriptors->configuration = NULL;
+
+	int rc;
+
+	/* It is worth to start a long transfer. */
+	usb_pipe_start_long_transfer(ctrl_pipe);
+
+	/* Get the device descriptor. */
+	rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	/* Get the full configuration descriptor. */
+	rc = usb_request_get_full_configuration_descriptor_alloc(
+	    ctrl_pipe, 0, (void **) &descriptors->configuration,
+	    &descriptors->configuration_size);
+
+leave:
+	usb_pipe_end_long_transfer(ctrl_pipe);
+
+	return rc;
+}
+
+/** Create pipes for a device.
+ *
+ * This is more or less a wrapper that does following actions:
+ * - allocate and initialize pipes
+ * - map endpoints to the pipes based on the descriptions
+ * - registers endpoints with the host controller
+ *
+ * @param[in] dev Generic DDF device backing the USB one.
+ * @param[in] wire Initialized backing connection to the host controller.
+ * @param[in] endpoints Endpoints description, NULL terminated.
+ * @param[in] config_descr Configuration descriptor of active configuration.
+ * @param[in] config_descr_size Size of @p config_descr in bytes.
+ * @param[in] interface_no Interface to map from.
+ * @param[in] interface_setting Interface setting (default is usually 0).
+ * @param[out] pipes_ptr Where to store array of created pipes
+ *	(not NULL terminated).
+ * @param[out] pipes_count_ptr Where to store number of pipes
+ *	(set to if you wish to ignore the count).
+ * @return Error code.
+ */
+int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,
+    usb_endpoint_description_t **endpoints,
+    uint8_t *config_descr, size_t config_descr_size,
+    int interface_no, int interface_setting,
+    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
+{
+	assert(dev != NULL);
+	assert(wire != NULL);
+	assert(endpoints != NULL);
+	assert(config_descr != NULL);
+	assert(config_descr_size > 0);
+	assert(pipes_ptr != NULL);
+
+	size_t i;
+	int rc;
+
+	size_t pipe_count = count_other_pipes(endpoints);
+	if (pipe_count == 0) {
+		*pipes_ptr = NULL;
+		return EOK;
+	}
+
+	usb_endpoint_mapping_t *pipes
+	    = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
+	if (pipes == NULL) {
+		return ENOMEM;
+	}
+
+	/* Initialize to NULL to allow smooth rollback. */
+	for (i = 0; i < pipe_count; i++) {
+		pipes[i].pipe = NULL;
+	}
+
+	/* Now allocate and fully initialize. */
+	for (i = 0; i < pipe_count; i++) {
+		pipes[i].pipe = malloc(sizeof(usb_pipe_t));
+		if (pipes[i].pipe == NULL) {
+			rc = ENOMEM;
+			goto rollback_free_only;
+		}
+		pipes[i].description = endpoints[i];
+		pipes[i].interface_no = interface_no;
+		pipes[i].interface_setting = interface_setting;
+	}
+
+	/* Find the mapping from configuration descriptor. */
+	rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
+	    config_descr, config_descr_size, wire);
+	if (rc != EOK) {
+		goto rollback_free_only;
+	}
+
+	/* Register the endpoints with HC. */
+	usb_hc_connection_t hc_conn;
+	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
+	if (rc != EOK) {
+		goto rollback_free_only;
+	}
+
+	rc = usb_hc_connection_open(&hc_conn);
+	if (rc != EOK) {
+		goto rollback_free_only;
+	}
+
+	for (i = 0; i < pipe_count; i++) {
+		if (pipes[i].present) {
+			rc = usb_pipe_register(pipes[i].pipe,
+			    pipes[i].descriptor->poll_interval, &hc_conn);
+			if (rc != EOK) {
+				goto rollback_unregister_endpoints;
+			}
+		}
+	}
+
+	usb_hc_connection_close(&hc_conn);
+
+	*pipes_ptr = pipes;
+	if (pipes_count_ptr != NULL) {
+		*pipes_count_ptr = pipe_count;
+	}
+
+	return EOK;
+
+	/*
+	 * Jump here if something went wrong after endpoints have
+	 * been registered.
+	 * This is also the target when the registration of
+	 * endpoints fails.
+	 */
+rollback_unregister_endpoints:
+	for (i = 0; i < pipe_count; i++) {
+		if (pipes[i].present) {
+			usb_pipe_unregister(pipes[i].pipe, &hc_conn);
+		}
+	}
+
+	usb_hc_connection_close(&hc_conn);
+
+	/*
+	 * Jump here if something went wrong before some actual communication
+	 * with HC. Then the only thing that needs to be done is to free
+	 * allocated memory.
+	 */
+rollback_free_only:
+	for (i = 0; i < pipe_count; i++) {
+		if (pipes[i].pipe != NULL) {
+			free(pipes[i].pipe);
+		}
+	}
+	free(pipes);
+
+	return rc;
+}
+
+/** Destroy pipes previously created by usb_device_create_pipes.
+ *
+ * @param[in] dev Generic DDF device backing the USB one.
+ * @param[in] pipes Endpoint mapping to be destroyed.
+ * @param[in] pipes_count Number of endpoints.
+ */
+int usb_device_destroy_pipes(ddf_dev_t *dev,
+    usb_endpoint_mapping_t *pipes, size_t pipes_count)
+{
+	assert(dev != NULL);
+	assert(((pipes != NULL) && (pipes_count > 0))
+	    || ((pipes == NULL) && (pipes_count == 0)));
+
+	if (pipes_count == 0) {
+		return EOK;
+	}
+
+	int rc;
+
+	/* Prepare connection to HC to allow endpoint unregistering. */
+	usb_hc_connection_t hc_conn;
+	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
+	if (rc != EOK) {
+		return rc;
+	}
+	rc = usb_hc_connection_open(&hc_conn);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Destroy the pipes. */
+	size_t i;
+	for (i = 0; i < pipes_count; i++) {
+		usb_pipe_unregister(pipes[i].pipe, &hc_conn);
+		free(pipes[i].pipe);
+	}
+
+	usb_hc_connection_close(&hc_conn);
+
+	free(pipes);
+
+	return EOK;
+}
+
+/** Initialize control pipe in a device.
+ *
+ * @param dev USB device in question.
+ * @param errmsg Where to store error context.
+ * @return
+ */
+static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
+{
+	int rc;
+
+	rc = usb_device_connection_initialize_from_device(&dev->wire,
+	    dev->ddf_dev);
+	if (rc != EOK) {
+		*errmsg = "device connection initialization";
+		return rc;
+	}
+
+	rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
+	    &dev->wire);
+	if (rc != EOK) {
+		*errmsg = "default control pipe initialization";
+		return rc;
+	}
+
+	return EOK;
+}
+
+
+/** Create new instance of USB device.
+ *
+ * @param[in] ddf_dev Generic DDF device backing the USB one.
+ * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
+ * @param[out] dev_ptr Where to store pointer to the new device.
+ * @param[out] errstr_ptr Where to store description of context
+ *	(in case error occurs).
+ * @return Error code.
+ */
+int usb_device_create(ddf_dev_t *ddf_dev,
+    usb_endpoint_description_t **endpoints,
+    usb_device_t **dev_ptr, const char **errstr_ptr)
+{
+	assert(dev_ptr != NULL);
+	assert(ddf_dev != NULL);
+
+	int rc;
+
+	usb_device_t *dev = malloc(sizeof(usb_device_t));
+	if (dev == NULL) {
+		*errstr_ptr = "structure allocation";
+		return ENOMEM;
+	}
+
+	// FIXME: proper deallocation in case of errors
+
+	dev->ddf_dev = ddf_dev;
+	dev->driver_data = NULL;
+	dev->descriptors.configuration = NULL;
+	dev->alternate_interfaces = NULL;
+
+	dev->pipes_count = 0;
+	dev->pipes = NULL;
+
+	/* Initialize backing wire and control pipe. */
+	rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Get our interface. */
+	dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
+
+	/* Retrieve standard descriptors. */
+	rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
+	    &dev->descriptors);
+	if (rc != EOK) {
+		*errstr_ptr = "descriptor retrieval";
+		return rc;
+	}
+
+	/* Create alternate interfaces. */
+	rc = usb_alternate_interfaces_create(dev->descriptors.configuration,
+	    dev->descriptors.configuration_size, dev->interface_no,
+	    &dev->alternate_interfaces);
+	if (rc != EOK) {
+		/* We will try to silently ignore this. */
+		dev->alternate_interfaces = NULL;
+	}
+
+	rc = initialize_other_pipes(endpoints, dev, 0);
+	if (rc != EOK) {
+		*errstr_ptr = "pipes initialization";
+		return rc;
+	}
+
+	*errstr_ptr = NULL;
+	*dev_ptr = dev;
+
+	return EOK;
+}
+
+/** Destroy instance of a USB device.
+ *
+ * @param dev Device to be destroyed.
+ */
+void usb_device_destroy(usb_device_t *dev)
+{
+	if (dev == NULL) {
+		return;
+	}
+
+	/* Ignore errors and hope for the best. */
+	usb_device_destroy_pipes(dev->ddf_dev, dev->pipes, dev->pipes_count);
+	if (dev->descriptors.configuration != NULL) {
+		free(dev->descriptors.configuration);
+	}
+
+	if (dev->alternate_interfaces != NULL) {
+		if (dev->alternate_interfaces->alternatives != NULL) {
+			free(dev->alternate_interfaces->alternatives);
+		}
+		free(dev->alternate_interfaces);
+	}
+
+	free(dev);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/devpoll.c
===================================================================
--- uspace/lib/usbdev/src/devpoll.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/devpoll.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * USB device driver framework - automatic interrupt polling.
+ */
+#include <usb/dev/poll.h>
+#include <usb/dev/request.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+
+/** Maximum number of failed consecutive requests before announcing failure. */
+#define MAX_FAILED_ATTEMPTS 3
+
+/** Data needed for polling. */
+typedef struct {
+	int debug;
+	size_t max_failures;
+	useconds_t delay;
+	bool auto_clear_halt;
+	bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *);
+	void (*on_polling_end)(usb_device_t *, bool, void *);
+	bool (*on_error)(usb_device_t *, int, void *);
+
+	usb_device_t *dev;
+	size_t pipe_index;
+	size_t request_size;
+	uint8_t *buffer;
+	void *custom_arg;
+} polling_data_t;
+
+
+/** Polling fibril.
+ *
+ * @param arg Pointer to polling_data_t.
+ * @return Always EOK.
+ */
+static int polling_fibril(void *arg)
+{
+	polling_data_t *polling_data = (polling_data_t *) arg;
+	assert(polling_data);
+
+	usb_pipe_t *pipe
+	    = polling_data->dev->pipes[polling_data->pipe_index].pipe;
+	
+	if (polling_data->debug > 0) {
+		usb_endpoint_mapping_t *mapping
+		    = &polling_data->dev->pipes[polling_data->pipe_index];
+		usb_log_debug("Poll%p: started polling of `%s' - " \
+		    "interface %d (%s,%d,%d), %zuB/%zu.\n",
+		    polling_data,
+		    polling_data->dev->ddf_dev->name,
+		    (int) mapping->interface->interface_number,
+		    usb_str_class(mapping->interface->interface_class),
+		    (int) mapping->interface->interface_subclass,
+		    (int) mapping->interface->interface_protocol,
+		    polling_data->request_size, pipe->max_packet_size);
+	}
+
+	size_t failed_attempts = 0;
+	while (failed_attempts <= polling_data->max_failures) {
+		int rc;
+
+		size_t actual_size;
+		rc = usb_pipe_read(pipe, polling_data->buffer,
+		    polling_data->request_size, &actual_size);
+
+		if (polling_data->debug > 1) {
+			if (rc == EOK) {
+				usb_log_debug(
+				    "Poll%p: received: '%s' (%zuB).\n",
+				    polling_data,
+				    usb_debug_str_buffer(polling_data->buffer,
+				        actual_size, 16),
+				    actual_size);
+			} else {
+				usb_log_debug(
+				    "Poll%p: polling failed: %s.\n",
+				    polling_data, str_error(rc));
+			}
+		}
+
+		/* If the pipe stalled, we can try to reset the stall. */
+		if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
+			/*
+			 * We ignore error here as this is usually a futile
+			 * attempt anyway.
+			 */
+			usb_request_clear_endpoint_halt(
+			    &polling_data->dev->ctrl_pipe,
+			    pipe->endpoint_no);
+		}
+
+		if (rc != EOK) {
+			if (polling_data->on_error != NULL) {
+				bool cont = polling_data->on_error(
+				    polling_data->dev, rc,
+				    polling_data->custom_arg);
+				if (!cont) {
+					failed_attempts
+					    = polling_data->max_failures;
+				}
+			}
+			failed_attempts++;
+			continue;
+		}
+
+		/* We have the data, execute the callback now. */
+		bool carry_on = polling_data->on_data(polling_data->dev,
+		    polling_data->buffer, actual_size,
+		    polling_data->custom_arg);
+
+		if (!carry_on) {
+			failed_attempts = 0;
+			break;
+		}
+
+		/* Reset as something might be only a temporary problem. */
+		failed_attempts = 0;
+
+		/* Take a rest before next request. */
+		async_usleep(polling_data->delay);
+	}
+
+	if (polling_data->on_polling_end != NULL) {
+		polling_data->on_polling_end(polling_data->dev,
+		    failed_attempts > 0, polling_data->custom_arg);
+	}
+
+	if (polling_data->debug > 0) {
+		if (failed_attempts > 0) {
+			usb_log_error(
+			    "Polling of device `%s' terminated: %s.\n",
+			    polling_data->dev->ddf_dev->name,
+			    "recurring failures");
+		} else {
+			usb_log_debug(
+			    "Polling of device `%s' terminated by user.\n",
+			    polling_data->dev->ddf_dev->name
+			);
+		}
+	}
+
+	/* Free the allocated memory. */
+	free(polling_data->buffer);
+	free(polling_data);
+
+	return EOK;
+}
+
+/** Start automatic device polling over interrupt in pipe.
+ *
+ * @warning It is up to the callback to produce delays between individual
+ * requests.
+ *
+ * @warning There is no guarantee when the request to the device
+ * will be sent for the first time (it is possible that this
+ * first request would be executed prior to return from this function).
+ *
+ * @param dev Device to be periodically polled.
+ * @param pipe_index Index of the endpoint pipe used for polling.
+ * @param callback Callback when data are available.
+ * @param request_size How many bytes to ask for in each request.
+ * @param terminated_callback Callback when polling is terminated.
+ * @param arg Custom argument (passed as is to the callbacks).
+ * @return Error code.
+ * @retval EOK New fibril polling the device was already started.
+ */
+int usb_device_auto_poll(usb_device_t *dev, size_t pipe_index,
+    usb_polling_callback_t callback, size_t request_size,
+    usb_polling_terminted_callback_t terminated_callback, void *arg)
+{
+	if ((dev == NULL) || (callback == NULL)) {
+		return EBADMEM;
+	}
+	if (request_size == 0) {
+		return EINVAL;
+	}
+	if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
+	    || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
+		return EINVAL;
+	}
+
+	usb_device_auto_polling_t *auto_polling
+	    = malloc(sizeof(usb_device_auto_polling_t));
+	if (auto_polling == NULL) {
+		return ENOMEM;
+	}
+
+	auto_polling->debug = 1;
+	auto_polling->auto_clear_halt = true;
+	auto_polling->delay = 0;
+	auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
+	auto_polling->on_data = callback;
+	auto_polling->on_polling_end = terminated_callback;
+	auto_polling->on_error = NULL;
+
+	int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
+	   request_size, arg);
+
+	free(auto_polling);
+
+	return rc;
+}
+
+/** Start automatic device polling over interrupt in pipe.
+ *
+ * The polling settings is copied thus it is okay to destroy the structure
+ * after this function returns.
+ *
+ * @warning There is no guarantee when the request to the device
+ * will be sent for the first time (it is possible that this
+ * first request would be executed prior to return from this function).
+ *
+ * @param dev Device to be periodically polled.
+ * @param pipe_index Index of the endpoint pipe used for polling.
+ * @param polling Polling settings.
+ * @param request_size How many bytes to ask for in each request.
+ * @param arg Custom argument (passed as is to the callbacks).
+ * @return Error code.
+ * @retval EOK New fibril polling the device was already started.
+ */
+int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
+    usb_device_auto_polling_t *polling,
+    size_t request_size, void *arg)
+{
+	if (dev == NULL) {
+		return EBADMEM;
+	}
+	if (pipe_index >= dev->pipes_count) {
+		return EINVAL;
+	}
+	if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
+	    || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
+		return EINVAL;
+	}
+	if ((polling == NULL) || (polling->on_data == NULL)) {
+		return EBADMEM;
+	}
+
+	polling_data_t *polling_data = malloc(sizeof(polling_data_t));
+	if (polling_data == NULL) {
+		return ENOMEM;
+	}
+
+	/* Fill-in the data. */
+	polling_data->buffer = malloc(sizeof(request_size));
+	if (polling_data->buffer == NULL) {
+		free(polling_data);
+		return ENOMEM;
+	}
+	polling_data->request_size = request_size;
+	polling_data->dev = dev;
+	polling_data->pipe_index = pipe_index;
+	polling_data->custom_arg = arg;
+
+	polling_data->debug = polling->debug;
+	polling_data->max_failures = polling->max_failures;
+	if (polling->delay >= 0) {
+		polling_data->delay = (useconds_t) polling->delay;
+	} else {
+		polling_data->delay = (useconds_t) dev->pipes[pipe_index]
+		    .descriptor->poll_interval;
+	}
+	polling_data->auto_clear_halt = polling->auto_clear_halt;
+
+	polling_data->on_data = polling->on_data;
+	polling_data->on_polling_end = polling->on_polling_end;
+	polling_data->on_error = polling->on_error;
+
+	fid_t fibril = fibril_create(polling_fibril, polling_data);
+	if (fibril == 0) {
+		free(polling_data->buffer);
+		free(polling_data);
+		return ENOMEM;
+	}
+	fibril_add_ready(fibril);
+
+	/* Fibril launched. That fibril will free the allocated data. */
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/dp.c
===================================================================
--- uspace/lib/usbdev/src/dp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/dp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/**
+ * @file
+ * USB descriptor parser (implementation).
+ *
+ * The descriptor parser is a generic parser for structure, where individual
+ * items are stored in single buffer and each item begins with length followed
+ * by type. These types are organized into tree hierarchy.
+ *
+ * The parser is able of only two actions: find first child and find next
+ * sibling.
+ */
+#include <stdio.h>
+#include <str_error.h>
+#include <errno.h>
+#include <assert.h>
+#include <bool.h>
+#include <usb/dev/dp.h>
+#include <usb/descriptor.h>
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+/** Nesting of standard USB descriptors. */
+usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+#undef NESTING
+#undef LAST_NESTING
+
+/** Tells whether pointer points inside descriptor data.
+ *
+ * @param data Parser data.
+ * @param ptr Pointer to be verified.
+ * @return Whether @p ptr points inside <code>data->data</code> field.
+ */
+static bool is_valid_descriptor_pointer(usb_dp_parser_data_t *data,
+    uint8_t *ptr)
+{
+	if (ptr == NULL) {
+		return false;
+	}
+
+	if (ptr < data->data) {
+		return false;
+	}
+
+	if ((size_t)(ptr - data->data) >= data->size) {
+		return false;
+	}
+
+	return true;
+}
+
+/** Get next descriptor regardless of the nesting.
+ *
+ * @param data Parser data.
+ * @param current Pointer to current descriptor.
+ * @return Pointer to start of next descriptor.
+ * @retval NULL Invalid input or no next descriptor.
+ */
+static uint8_t *get_next_descriptor(usb_dp_parser_data_t *data,
+    uint8_t *current)
+{
+	assert(is_valid_descriptor_pointer(data, current));
+
+	uint8_t current_length = *current;
+	uint8_t *next = current + current_length;
+
+	if (!is_valid_descriptor_pointer(data, next)) {
+		return NULL;
+	}
+
+	return next;
+}
+
+/** Get descriptor type.
+ *
+ * @see usb_descriptor_type_t
+ *
+ * @param data Parser data.
+ * @param start Pointer to start of the descriptor.
+ * @return Descriptor type.
+ * @retval -1 Invalid input.
+ */
+static int get_descriptor_type(usb_dp_parser_data_t *data, uint8_t *start)
+{
+	if (start == NULL) {
+		return -1;
+	}
+
+	start++;
+	if (!is_valid_descriptor_pointer(data, start)) {
+		return -1;
+	} else {
+		return (int) (*start);
+	}
+}
+
+/** Tells whether descriptors could be nested.
+ *
+ * @param parser Parser.
+ * @param child Child descriptor type.
+ * @param parent Parent descriptor type.
+ * @return Whether @p child could be child of @p parent.
+ */
+static bool is_nested_descriptor_type(usb_dp_parser_t *parser,
+    int child, int parent)
+{
+	usb_dp_descriptor_nesting_t *nesting = parser->nesting;
+	while ((nesting->child > 0) && (nesting->parent > 0)) {
+		if ((nesting->child == child) && (nesting->parent == parent)) {
+			return true;
+		}
+		nesting++;
+	}
+	return false;
+}
+
+/** Tells whether descriptors could be nested.
+ *
+ * @param parser Parser.
+ * @param data Parser data.
+ * @param child Pointer to child descriptor.
+ * @param parent Pointer to parent descriptor.
+ * @return Whether @p child could be child of @p parent.
+ */
+static bool is_nested_descriptor(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *child, uint8_t *parent)
+{
+	return is_nested_descriptor_type(parser,
+	    get_descriptor_type(data, child),
+	    get_descriptor_type(data, parent));
+}
+
+/** Find first nested descriptor of given parent.
+ *
+ * @param parser Parser.
+ * @param data Parser data.
+ * @param parent Pointer to the beginning of parent descriptor.
+ * @return Pointer to the beginning of the first nested (child) descriptor.
+ * @retval NULL No child descriptor found.
+ * @retval NULL Invalid input.
+ */
+uint8_t *usb_dp_get_nested_descriptor(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *parent)
+{
+	if (!is_valid_descriptor_pointer(data, parent)) {
+		return NULL;
+	}
+
+	uint8_t *next = get_next_descriptor(data, parent);
+	if (next == NULL) {
+		return NULL;
+	}
+
+	if (is_nested_descriptor(parser, data, next, parent)) {
+		return next;
+	} else {
+		return NULL;
+	}
+}
+
+/** Skip all nested descriptors.
+ *
+ * @param parser Parser.
+ * @param data Parser data.
+ * @param parent Pointer to the beginning of parent descriptor.
+ * @return Pointer to first non-child descriptor.
+ * @retval NULL No next descriptor.
+ * @retval NULL Invalid input.
+ */
+static uint8_t *skip_nested_descriptors(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *parent)
+{
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, parent);
+	if (child == NULL) {
+		return get_next_descriptor(data, parent);
+	}
+	uint8_t *next_child = skip_nested_descriptors(parser, data, child);
+	while (is_nested_descriptor(parser, data, next_child, parent)) {
+		next_child = skip_nested_descriptors(parser, data, next_child);
+	}
+
+	return next_child;
+}
+
+/** Get sibling descriptor.
+ *
+ * @param parser Parser.
+ * @param data Parser data.
+ * @param parent Pointer to common parent descriptor.
+ * @param sibling Left sibling.
+ * @return Pointer to first right sibling of @p sibling.
+ * @retval NULL No sibling exist.
+ * @retval NULL Invalid input.
+ */
+uint8_t *usb_dp_get_sibling_descriptor(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *parent, uint8_t *sibling)
+{
+	if (!is_valid_descriptor_pointer(data, parent)
+	    || !is_valid_descriptor_pointer(data, sibling)) {
+		return NULL;
+	}
+
+	uint8_t *possible_sibling = skip_nested_descriptors(parser, data, sibling);
+	if (possible_sibling == NULL) {
+		return NULL;
+	}
+
+	int parent_type = get_descriptor_type(data, parent);
+	int possible_sibling_type = get_descriptor_type(data, possible_sibling);
+	if (is_nested_descriptor_type(parser, possible_sibling_type, parent_type)) {
+		return possible_sibling;
+	} else {
+		return NULL;
+	}
+}
+
+/** Browser of the descriptor tree.
+ *
+ * @see usb_dp_walk_simple
+ *
+ * @param parser Descriptor parser.
+ * @param data Data for descriptor parser.
+ * @param root Pointer to current root of the tree.
+ * @param depth Current nesting depth.
+ * @param callback Callback for each found descriptor.
+ * @param arg Custom (user) argument.
+ */
+static void usb_dp_browse_simple_internal(usb_dp_parser_t *parser,
+    usb_dp_parser_data_t *data, uint8_t *root, size_t depth,
+    void (*callback)(uint8_t *, size_t, void *), void *arg)
+{
+	if (root == NULL) {
+		return;
+	}
+	callback(root, depth, arg);
+	uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
+	do {
+		usb_dp_browse_simple_internal(parser, data, child, depth + 1,
+		    callback, arg);
+		child = usb_dp_get_sibling_descriptor(parser, data,
+		    root, child);
+	} while (child != NULL);
+}
+
+/** Browse flatten descriptor tree.
+ *
+ * The callback is called with following arguments: pointer to the start
+ * of the descriptor (somewhere inside @p descriptors), depth of the nesting
+ * (starting from 0 for the first descriptor) and the custom argument.
+ * Note that the size of the descriptor is not passed because it can
+ * be read from the first byte of the descriptor.
+ *
+ * @param descriptors Descriptor data.
+ * @param descriptors_size Size of descriptor data (in bytes).
+ * @param descriptor_nesting Possible descriptor nesting.
+ * @param callback Callback for each found descriptor.
+ * @param arg Custom (user) argument.
+ */
+void usb_dp_walk_simple(uint8_t *descriptors, size_t descriptors_size,
+    usb_dp_descriptor_nesting_t *descriptor_nesting,
+    void (*callback)(uint8_t *, size_t, void *), void *arg)
+{
+	if ((descriptors == NULL) || (descriptors_size == 0)
+	    || (descriptor_nesting == NULL) || (callback == NULL)) {
+		return;
+	}
+
+	usb_dp_parser_data_t data = {
+		.data = descriptors,
+		.size = descriptors_size,
+		.arg = NULL
+	};
+
+	usb_dp_parser_t parser = {
+		.nesting = descriptor_nesting
+	};
+
+	usb_dp_browse_simple_internal(&parser, &data, descriptors,
+	    0, callback, arg);
+}
+
+/** @}
+ */
Index: uspace/lib/usbdev/src/hub.c
===================================================================
--- uspace/lib/usbdev/src/hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/hub.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Functions needed by hub drivers.
+ */
+#include <usb/dev/hub.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/request.h>
+#include <usb/dev/recognise.h>
+#include <usbhc_iface.h>
+#include <errno.h>
+#include <assert.h>
+#include <usb/debug.h>
+#include <time.h>
+#include <async.h>
+
+/** How much time to wait between attempts to register endpoint 0:0.
+ * The value is based on typical value for port reset + some overhead.
+ */
+#define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
+
+/** Check that HC connection is alright.
+ *
+ * @param conn Connection to be checked.
+ */
+#define CHECK_CONNECTION(conn) \
+	do { \
+		assert((conn)); \
+		if (!usb_hc_connection_is_opened((conn))) { \
+			return ENOENT; \
+		} \
+	} while (false)
+
+/** Ask host controller for free address assignment.
+ *
+ * @param connection Opened connection to host controller.
+ * @param speed Speed of the new device (device that will be assigned
+ *    the returned address).
+ * @return Assigned USB address or negative error code.
+ */
+usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
+    usb_speed_t speed)
+{
+	CHECK_CONNECTION(connection);
+	
+	async_exch_t *exch = async_exchange_begin(connection->hc_sess);
+	
+	sysarg_t address;
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_REQUEST_ADDRESS, speed,
+	    &address);
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK)
+		return (usb_address_t) rc;
+	
+	return (usb_address_t) address;
+}
+
+/** Inform host controller about new device.
+ *
+ * @param connection Opened connection to host controller.
+ * @param attached_device Information about the new device.
+ * @return Error code.
+ */
+int usb_hc_register_device(usb_hc_connection_t * connection,
+    const usb_hc_attached_device_t *attached_device)
+{
+	CHECK_CONNECTION(connection);
+	
+	if (attached_device == NULL)
+		return EBADMEM;
+	
+	async_exch_t *exch = async_exchange_begin(connection->hc_sess);
+	int rc = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_BIND_ADDRESS,
+	    attached_device->address, attached_device->handle);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** Inform host controller about device removal.
+ *
+ * @param connection Opened connection to host controller.
+ * @param address Address of the device that is being removed.
+ * @return Error code.
+ */
+int usb_hc_unregister_device(usb_hc_connection_t *connection,
+    usb_address_t address)
+{
+	CHECK_CONNECTION(connection);
+	
+	async_exch_t *exch = async_exchange_begin(connection->hc_sess);
+	int rc = async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_ADDRESS, address);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+
+static void unregister_control_endpoint_on_default_address(
+    usb_hc_connection_t *connection)
+{
+	usb_device_connection_t dev_conn;
+	int rc = usb_device_connection_initialize_on_default_address(&dev_conn,
+	    connection);
+	if (rc != EOK) {
+		return;
+	}
+
+	usb_pipe_t ctrl_pipe;
+	rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
+	if (rc != EOK) {
+		return;
+	}
+
+	usb_pipe_unregister(&ctrl_pipe, connection);
+}
+
+
+/** Wrapper for registering attached device to the hub.
+ *
+ * The @p enable_port function is expected to enable signaling on given
+ * port.
+ * The two arguments to it can have arbitrary meaning
+ * (the @p port_no is only a suggestion)
+ * and are not touched at all by this function
+ * (they are passed as is to the @p enable_port function).
+ *
+ * If the @p enable_port fails (i.e. does not return EOK), the device
+ * addition is canceled.
+ * The return value is then returned (it is good idea to use different
+ * error codes than those listed as return codes by this function itself).
+ *
+ * The @p connection representing connection with host controller does not
+ * need to be started.
+ * This function duplicates the connection to allow simultaneous calls of
+ * this function (i.e. from different fibrils).
+ *
+ * @param[in] parent Parent device (i.e. the hub device).
+ * @param[in] connection Connection to host controller.
+ * @param[in] dev_speed New device speed.
+ * @param[in] enable_port Function for enabling signaling through the port the
+ *	device is attached to.
+ * @param[in] port_no Port number (passed through to @p enable_port).
+ * @param[in] arg Any data argument to @p enable_port.
+ * @param[out] assigned_address USB address of the device.
+ * @param[out] assigned_handle Devman handle of the new device.
+ * @param[in] dev_ops Child device ops.
+ * @param[in] new_dev_data Arbitrary pointer to be stored in the child
+ *	as @c driver_data.
+ * @param[out] new_fun Storage where pointer to allocated child function
+ *	will be written.
+ * @return Error code.
+ * @retval ENOENT Connection to HC not opened.
+ * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
+ * @retval EBUSY Failed reserving default USB address.
+ * @retval ENOTCONN Problem connecting to the host controller via USB pipe.
+ * @retval ESTALL Problem communication with device (either SET_ADDRESS
+ *	request or requests for descriptors when creating match ids).
+ */
+int usb_hc_new_device_wrapper(ddf_dev_t *parent, usb_hc_connection_t *connection,
+    usb_speed_t dev_speed,
+    int (*enable_port)(int port_no, void *arg), int port_no, void *arg,
+    usb_address_t *assigned_address, devman_handle_t *assigned_handle,
+    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
+{
+	assert(connection != NULL);
+	// FIXME: this is awful, we are accessing directly the structure.
+	usb_hc_connection_t hc_conn = {
+		.hc_handle = connection->hc_handle,
+		.hc_sess = NULL
+	};
+
+	int rc;
+	struct timeval start_time;
+
+	rc = gettimeofday(&start_time, NULL);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_hc_connection_open(&hc_conn);
+	if (rc != EOK) {
+		return rc;
+	}
+
+
+	/*
+	 * Request new address.
+	 */
+	usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);
+	if (dev_addr < 0) {
+		usb_hc_connection_close(&hc_conn);
+		return EADDRNOTAVAIL;
+	}
+
+	/*
+	 * We will not register control pipe on default address.
+	 * The registration might fail. That means that someone else already
+	 * registered that endpoint. We will simply wait and try again.
+	 * (Someone else already wants to add a new device.)
+	 */
+	usb_device_connection_t dev_conn;
+	rc = usb_device_connection_initialize_on_default_address(&dev_conn,
+	    &hc_conn);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_free_address;
+	}
+
+	usb_pipe_t ctrl_pipe;
+	rc = usb_pipe_initialize_default_control(&ctrl_pipe,
+	    &dev_conn);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_free_address;
+	}
+
+	do {
+		rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
+		    &hc_conn);
+		if (rc != EOK) {
+			/* Do not overheat the CPU ;-). */
+			async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
+		}
+	} while (rc != EOK);
+	struct timeval end_time;
+
+	rc = gettimeofday(&end_time, NULL);
+	if (rc != EOK) {
+		goto leave_release_default_address;
+	}
+
+	/* According to the USB spec part 9.1.2 host allows 100ms time for
+	 * the insertion process to complete. According to 7.1.7.1 this is the
+	 * time between attach detected and port reset. However, the setup done
+	 * above might use much of this time so we should only wait to fill
+	 * up the 100ms quota*/
+	suseconds_t elapsed = tv_sub(&end_time, &start_time);
+	if (elapsed < 100000) {
+		async_usleep(100000 - elapsed);
+	}
+
+	/*
+	 * Endpoint is registered. We can enable the port and change
+	 * device address.
+	 */
+	rc = enable_port(port_no, arg);
+	if (rc != EOK) {
+		goto leave_release_default_address;
+	}
+	/* USB spec 7.1.7.1: The USB System Software guarantees a minimum of
+	 * 10ms for reset recovery. Device response to any bus transactions
+	 * addressed to the default device address during the reset recovery
+	 * time is undefined.
+	 */
+	async_usleep(10000);
+
+	rc = usb_pipe_probe_default_control(&ctrl_pipe);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_release_default_address;
+	}
+
+	rc = usb_request_set_address(&ctrl_pipe, dev_addr);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_release_default_address;
+	}
+
+	/*
+	 * Address changed. We can release the original endpoint, thus
+	 * allowing other to access the default address.
+	 */
+	unregister_control_endpoint_on_default_address(&hc_conn);
+
+	/*
+	 * Time to register the new endpoint.
+	 */
+	rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
+	if (rc != EOK) {
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * It is time to register the device with devman.
+	 */
+	/* FIXME: create device_register that will get opened ctrl pipe. */
+	devman_handle_t child_handle;
+	rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
+	    parent, &child_handle,
+	    dev_ops, new_dev_data, new_fun);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * And now inform the host controller about the handle.
+	 */
+	usb_hc_attached_device_t new_device = {
+		.address = dev_addr,
+		.handle = child_handle
+	};
+	rc = usb_hc_register_device(&hc_conn, &new_device);
+	if (rc != EOK) {
+		rc = EDESTADDRREQ;
+		goto leave_release_free_address;
+	}
+	
+	usb_hc_connection_close(&hc_conn);
+
+	/*
+	 * And we are done.
+	 */
+	if (assigned_address != NULL) {
+		*assigned_address = dev_addr;
+	}
+	if (assigned_handle != NULL) {
+		*assigned_handle = child_handle;
+	}
+
+	return EOK;
+
+
+
+	/*
+	 * Error handling (like nested exceptions) starts here.
+	 * Completely ignoring errors here.
+	 */
+leave_release_default_address:
+	usb_pipe_unregister(&ctrl_pipe, &hc_conn);
+
+leave_release_free_address:
+	usb_hc_unregister_device(&hc_conn, dev_addr);
+
+	usb_hc_connection_close(&hc_conn);
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/pipepriv.c
===================================================================
--- uspace/lib/usbdev/src/pipepriv.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/pipepriv.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Library internal functions on USB pipes (implementation).
+ */
+#include "pipepriv.h"
+#include <devman.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Ensure exclusive access to the IPC phone of given pipe.
+ *
+ * @param pipe Pipe to be exclusively accessed.
+ */
+void pipe_start_transaction(usb_pipe_t *pipe)
+{
+	fibril_mutex_lock(&pipe->hc_sess_mutex);
+}
+
+/** Terminate exclusive access to the IPC phone of given pipe.
+ *
+ * @param pipe Pipe to be released from exclusive usage.
+ */
+void pipe_end_transaction(usb_pipe_t *pipe)
+{
+	fibril_mutex_unlock(&pipe->hc_sess_mutex);
+}
+
+/** Ensure exclusive access to the pipe as a whole.
+ *
+ * @param pipe Pipe to be exclusively accessed.
+ */
+void pipe_acquire(usb_pipe_t *pipe)
+{
+	fibril_mutex_lock(&pipe->guard);
+}
+
+/** Terminate exclusive access to the pipe as a whole.
+ *
+ * @param pipe Pipe to be released from exclusive usage.
+ */
+void pipe_release(usb_pipe_t *pipe)
+{
+	fibril_mutex_unlock(&pipe->guard);
+}
+
+/** Add reference of active transfers over the pipe.
+ *
+ * @param pipe The USB pipe.
+ * @param hide_failure Whether to hide failure when adding reference
+ *	(use soft refcount).
+ * @return Error code.
+ * @retval EOK Currently always.
+ */
+int pipe_add_ref(usb_pipe_t *pipe, bool hide_failure)
+{
+	pipe_acquire(pipe);
+	
+	if (pipe->refcount == 0) {
+		/* Need to open the phone by ourselves. */
+		async_sess_t *sess =
+		    devman_device_connect(EXCHANGE_SERIALIZE, pipe->wire->hc_handle, 0);
+		if (!sess) {
+			if (hide_failure) {
+				pipe->refcount_soft++;
+				pipe_release(pipe);
+				return EOK;
+			}
+			
+			pipe_release(pipe);
+			return ENOMEM;
+		}
+		
+		/*
+		 * No locking is needed, refcount is zero and whole pipe
+		 * mutex is locked.
+		 */
+		
+		pipe->hc_sess = sess;
+	}
+	
+	pipe->refcount++;
+	pipe_release(pipe);
+	
+	return EOK;
+}
+
+/** Drop active transfer reference on the pipe.
+ *
+ * @param pipe The USB pipe.
+ */
+void pipe_drop_ref(usb_pipe_t *pipe)
+{
+	pipe_acquire(pipe);
+	
+	if (pipe->refcount_soft > 0) {
+		pipe->refcount_soft--;
+		pipe_release(pipe);
+		return;
+	}
+	
+	assert(pipe->refcount > 0);
+	
+	pipe->refcount--;
+	
+	if (pipe->refcount == 0) {
+		/* We were the last users, let's hang-up. */
+		async_hangup(pipe->hc_sess);
+		pipe->hc_sess = NULL;
+	}
+	
+	pipe_release(pipe);
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/pipepriv.h
===================================================================
--- uspace/lib/usbdev/src/pipepriv.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/pipepriv.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Library internal functions on USB pipes.
+ */
+#ifndef LIBUSBDEV_PIPEPRIV_H_
+#define LIBUSBDEV_PIPEPRIV_H_
+
+#include <usb/dev/pipes.h>
+#include <bool.h>
+
+void pipe_acquire(usb_pipe_t *);
+void pipe_release(usb_pipe_t *);
+
+void pipe_start_transaction(usb_pipe_t *);
+void pipe_end_transaction(usb_pipe_t *);
+
+int pipe_add_ref(usb_pipe_t *, bool);
+void pipe_drop_ref(usb_pipe_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/pipes.c
===================================================================
--- uspace/lib/usbdev/src/pipes.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/pipes.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * USB endpoint pipes miscellaneous functions.
+ */
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/debug.h>
+#include <usb/hc.h>
+#include <usbhc_iface.h>
+#include <usb_iface.h>
+#include <devman.h>
+#include <errno.h>
+#include <assert.h>
+#include "pipepriv.h"
+
+#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
+
+/** Tell USB address assigned to given device.
+ *
+ * @param sess Session to parent device.
+ * @param dev Device in question.
+ * @return USB address or error code.
+ */
+static usb_address_t get_my_address(async_sess_t *sess, ddf_dev_t *dev)
+{
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	/*
+	 * We are sending special value as a handle - zero - to get
+	 * handle of the parent function (that handle was used
+	 * when registering our device @p dev.
+	 */
+	sysarg_t address;
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS, 0, &address);
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return (usb_address_t) address;
+}
+
+/** Tell USB interface assigned to given device.
+ *
+ * @param device Device in question.
+ * @return Interface number (negative code means any).
+ */
+int usb_device_get_assigned_interface(ddf_dev_t *device)
+{
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return -1;
+	
+	async_exch_t *exch = async_exchange_begin(parent_sess);
+	
+	sysarg_t iface_no;
+	int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_INTERFACE, device->handle, &iface_no);
+	
+	async_exchange_end(exch);
+	async_hangup(parent_sess);
+	
+	if (rc != EOK)
+		return -1;
+	
+	return (int) iface_no;
+}
+
+/** Initialize connection to USB device.
+ *
+ * @param connection Connection structure to be initialized.
+ * @param dev Generic device backing the USB device.
+ * @return Error code.
+ */
+int usb_device_connection_initialize_from_device(
+    usb_device_connection_t *connection, ddf_dev_t *dev)
+{
+	assert(connection);
+	assert(dev);
+	
+	int rc;
+	devman_handle_t hc_handle;
+	usb_address_t my_address;
+	
+	rc = usb_hc_find(dev->handle, &hc_handle);
+	if (rc != EOK)
+		return rc;
+	
+	async_sess_t *parent_sess =
+	    devman_parent_device_connect(EXCHANGE_ATOMIC, dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (!parent_sess)
+		return ENOMEM;
+	
+	/*
+	 * Asking for "my" address may require several attempts.
+	 * That is because following scenario may happen:
+	 *  - parent driver (i.e. driver of parent device) announces new device
+	 *    and devman launches current driver
+	 *  - parent driver is preempted and thus does not send address-handle
+	 *    binding to HC driver
+	 *  - this driver gets here and wants the binding
+	 *  - the HC does not know the binding yet and thus it answers ENOENT
+	 *  So, we need to wait for the HC to learn the binding.
+	 */
+	
+	do {
+		my_address = get_my_address(parent_sess, dev);
+		
+		if (my_address == ENOENT) {
+			/* Be nice, let other fibrils run and try again. */
+			async_usleep(IPC_AGAIN_DELAY);
+		} else if (my_address < 0) {
+			/* Some other problem, no sense trying again. */
+			rc = my_address;
+			goto leave;
+		}
+	
+	} while (my_address < 0);
+	
+	rc = usb_device_connection_initialize(connection,
+	    hc_handle, my_address);
+	
+leave:
+	async_hangup(parent_sess);
+	return rc;
+}
+
+/** Initialize connection to USB device.
+ *
+ * @param connection Connection structure to be initialized.
+ * @param host_controller_handle Devman handle of host controller device is
+ * 	connected to.
+ * @param device_address Device USB address.
+ * @return Error code.
+ */
+int usb_device_connection_initialize(usb_device_connection_t *connection,
+    devman_handle_t host_controller_handle, usb_address_t device_address)
+{
+	assert(connection);
+
+	if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {
+		return EINVAL;
+	}
+
+	connection->hc_handle = host_controller_handle;
+	connection->address = device_address;
+
+	return EOK;
+}
+
+/** Initialize connection to USB device on default address.
+ *
+ * @param dev_connection Device connection structure to be initialized.
+ * @param hc_connection Initialized connection to host controller.
+ * @return Error code.
+ */
+int usb_device_connection_initialize_on_default_address(
+    usb_device_connection_t *dev_connection,
+    usb_hc_connection_t *hc_connection)
+{
+	assert(dev_connection);
+
+	if (hc_connection == NULL) {
+		return EBADMEM;
+	}
+
+	return usb_device_connection_initialize(dev_connection,
+	    hc_connection->hc_handle, (usb_address_t) 0);
+}
+
+/** Prepare pipe for a long transfer.
+ *
+ * By a long transfer is mean transfer consisting of several
+ * requests to the HC.
+ * Calling such function is optional and it has positive effect of
+ * improved performance because IPC session is initiated only once.
+ *
+ * @param pipe Pipe over which the transfer will happen.
+ * @return Error code.
+ */
+void usb_pipe_start_long_transfer(usb_pipe_t *pipe)
+{
+	(void) pipe_add_ref(pipe, true);
+}
+
+/** Terminate a long transfer on a pipe.
+ *
+ * @see usb_pipe_start_long_transfer
+ *
+ * @param pipe Pipe where to end the long transfer.
+ */
+void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
+{
+	pipe_drop_ref(pipe);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/pipesinit.c
===================================================================
--- uspace/lib/usbdev/src/pipesinit.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/pipesinit.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Initialization of endpoint pipes.
+ *
+ */
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/dp.h>
+#include <usb/dev/request.h>
+#include <usbhc_iface.h>
+#include <errno.h>
+#include <assert.h>
+
+#define CTRL_PIPE_MIN_PACKET_SIZE 8
+#define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
+
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+/** Nesting pairs of standard descriptors. */
+static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+/** Tells whether given descriptor is of endpoint type.
+ *
+ * @param descriptor Descriptor in question.
+ * @return Whether the given descriptor is endpoint descriptor.
+ */
+static inline bool is_endpoint_descriptor(uint8_t *descriptor)
+{
+	return descriptor[1] == USB_DESCTYPE_ENDPOINT;
+}
+
+/** Tells whether found endpoint corresponds to endpoint described by user.
+ *
+ * @param wanted Endpoint description as entered by driver author.
+ * @param found Endpoint description obtained from endpoint descriptor.
+ * @return Whether the @p found descriptor fits the @p wanted descriptor.
+ */
+static bool endpoint_fits_description(const usb_endpoint_description_t *wanted,
+    usb_endpoint_description_t *found)
+{
+#define _SAME(fieldname) ((wanted->fieldname) == (found->fieldname))
+
+	if (!_SAME(direction)) {
+		return false;
+	}
+
+	if (!_SAME(transfer_type)) {
+		return false;
+	}
+
+	if ((wanted->interface_class >= 0) && !_SAME(interface_class)) {
+		return false;
+	}
+
+	if ((wanted->interface_subclass >= 0) && !_SAME(interface_subclass)) {
+		return false;
+	}
+
+	if ((wanted->interface_protocol >= 0) && !_SAME(interface_protocol)) {
+		return false;
+	}
+
+#undef _SAME
+
+	return true;
+}
+
+/** Find endpoint mapping for a found endpoint.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param found_endpoint Description of found endpoint.
+ * @param interface_number Number of currently processed interface.
+ * @return Endpoint mapping corresponding to @p found_endpoint.
+ * @retval NULL No corresponding endpoint found.
+ */
+static usb_endpoint_mapping_t *find_endpoint_mapping(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_endpoint_description_t *found_endpoint,
+    int interface_number, int interface_setting)
+{
+	while (mapping_count > 0) {
+		bool interface_number_fits = (mapping->interface_no < 0)
+		    || (mapping->interface_no == interface_number);
+
+		bool interface_setting_fits = (mapping->interface_setting < 0)
+		    || (mapping->interface_setting == interface_setting);
+
+		bool endpoint_descriptions_fits = endpoint_fits_description(
+		    mapping->description, found_endpoint);
+
+		if (interface_number_fits
+		    && interface_setting_fits
+		    && endpoint_descriptions_fits) {
+			return mapping;
+		}
+
+		mapping++;
+		mapping_count--;
+	}
+	return NULL;
+}
+
+/** Process endpoint descriptor.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param interface Interface descriptor under which belongs the @p endpoint.
+ * @param endpoint Endpoint descriptor.
+ * @param wire Connection backing the endpoint pipes.
+ * @return Error code.
+ */
+static int process_endpoint(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_standard_interface_descriptor_t *interface,
+    usb_standard_endpoint_descriptor_t *endpoint,
+    usb_device_connection_t *wire)
+{
+	usb_endpoint_description_t description;
+
+	/*
+	 * Get endpoint characteristics.
+	 */
+
+	/* Actual endpoint number is in bits 0..3 */
+	usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F;
+
+	/* Endpoint direction is set by bit 7 */
+	description.direction = (endpoint->endpoint_address & 128)
+	    ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	/* Transfer type is in bits 0..2 and the enum values corresponds 1:1 */
+	description.transfer_type = endpoint->attributes & 3;
+
+	/*
+	 * Get interface characteristics.
+	 */
+	description.interface_class = interface->interface_class;
+	description.interface_subclass = interface->interface_subclass;
+	description.interface_protocol = interface->interface_protocol;
+
+	/*
+	 * Find the most fitting mapping and initialize the pipe.
+	 */
+	usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping,
+	    mapping_count, &description,
+	    interface->interface_number, interface->alternate_setting);
+	if (ep_mapping == NULL) {
+		return ENOENT;
+	}
+
+	if (ep_mapping->pipe == NULL) {
+		return EBADMEM;
+	}
+	if (ep_mapping->present) {
+		return EEXISTS;
+	}
+
+	int rc = usb_pipe_initialize(ep_mapping->pipe, wire,
+	    ep_no, description.transfer_type, endpoint->max_packet_size,
+	    description.direction);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	ep_mapping->present = true;
+	ep_mapping->descriptor = endpoint;
+	ep_mapping->interface = interface;
+
+	return EOK;
+}
+
+/** Process whole USB interface.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param parser Descriptor parser.
+ * @param parser_data Descriptor parser data.
+ * @param interface_descriptor Interface descriptor.
+ * @return Error code.
+ */
+static int process_interface(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_dp_parser_t *parser, usb_dp_parser_data_t *parser_data,
+    uint8_t *interface_descriptor)
+{
+	uint8_t *descriptor = usb_dp_get_nested_descriptor(parser,
+	    parser_data, interface_descriptor);
+
+	if (descriptor == NULL) {
+		return ENOENT;
+	}
+
+	do {
+		if (is_endpoint_descriptor(descriptor)) {
+			(void) process_endpoint(mapping, mapping_count,
+			    (usb_standard_interface_descriptor_t *)
+			        interface_descriptor,
+			    (usb_standard_endpoint_descriptor_t *)
+			        descriptor,
+			    (usb_device_connection_t *) parser_data->arg);
+		}
+
+		descriptor = usb_dp_get_sibling_descriptor(parser, parser_data,
+		    interface_descriptor, descriptor);
+	} while (descriptor != NULL);
+
+	return EOK;
+}
+
+/** Initialize endpoint pipes from configuration descriptor.
+ *
+ * The mapping array is expected to conform to following rules:
+ * - @c pipe must point to already allocated structure with uninitialized pipe
+ * - @c description must point to prepared endpoint description
+ * - @c descriptor does not need to be initialized (will be overwritten)
+ * - @c interface does not need to be initialized (will be overwritten)
+ * - @c present does not need to be initialized (will be overwritten)
+ *
+ * After processing the configuration descriptor, the mapping is updated
+ * in the following fashion:
+ * - @c present will be set to @c true when the endpoint was found in the
+ *   configuration
+ * - @c descriptor will point inside the configuration descriptor to endpoint
+ *   corresponding to given description (or NULL for not found descriptor)
+ * - @c interface will point inside the configuration descriptor to interface
+ *   descriptor the endpoint @c descriptor belongs to (or NULL for not found
+ *   descriptor)
+ * - @c pipe will be initialized when found, otherwise left untouched
+ * - @c description will be untouched under all circumstances
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param configuration_descriptor Full configuration descriptor (is expected
+ *	to be in USB endianness: i.e. as-is after being retrieved from
+ *	the device).
+ * @param configuration_descriptor_size Size of @p configuration_descriptor
+ *	in bytes.
+ * @param connection Connection backing the endpoint pipes.
+ * @return Error code.
+ */
+int usb_pipe_initialize_from_configuration(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    uint8_t *configuration_descriptor, size_t configuration_descriptor_size,
+    usb_device_connection_t *connection)
+{
+	assert(connection);
+
+	if (configuration_descriptor == NULL) {
+		return EBADMEM;
+	}
+	if (configuration_descriptor_size
+	    < sizeof(usb_standard_configuration_descriptor_t)) {
+		return ERANGE;
+	}
+
+	/*
+	 * Go through the mapping and set all endpoints to not present.
+	 */
+	size_t i;
+	for (i = 0; i < mapping_count; i++) {
+		mapping[i].present = false;
+		mapping[i].descriptor = NULL;
+		mapping[i].interface = NULL;
+	}
+
+	/*
+	 * Prepare the descriptor parser.
+	 */
+	usb_dp_parser_t dp_parser = {
+		.nesting = descriptor_nesting
+	};
+	usb_dp_parser_data_t dp_data = {
+		.data = configuration_descriptor,
+		.size = configuration_descriptor_size,
+		.arg = connection
+	};
+
+	/*
+	 * Iterate through all interfaces.
+	 */
+	uint8_t *interface = usb_dp_get_nested_descriptor(&dp_parser,
+	    &dp_data, configuration_descriptor);
+	if (interface == NULL) {
+		return ENOENT;
+	}
+	do {
+		(void) process_interface(mapping, mapping_count,
+		    &dp_parser, &dp_data,
+		    interface);
+		interface = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
+		    configuration_descriptor, interface);
+	} while (interface != NULL);
+
+	return EOK;
+}
+
+/** Initialize USB endpoint pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
+ * @param transfer_type Transfer type (e.g. interrupt or bulk).
+ * @param max_packet_size Maximum packet size in bytes.
+ * @param direction Endpoint direction (in/out).
+ * @return Error code.
+ */
+int usb_pipe_initialize(usb_pipe_t *pipe,
+    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    usb_direction_t direction)
+{
+	assert(pipe);
+	assert(connection);
+
+	fibril_mutex_initialize(&pipe->guard);
+	pipe->wire = connection;
+	pipe->hc_sess = NULL;
+	fibril_mutex_initialize(&pipe->hc_sess_mutex);
+	pipe->endpoint_no = endpoint_no;
+	pipe->transfer_type = transfer_type;
+	pipe->max_packet_size = max_packet_size;
+	pipe->direction = direction;
+	pipe->refcount = 0;
+	pipe->refcount_soft = 0;
+	pipe->auto_reset_halt = false;
+
+	return EOK;
+}
+
+
+/** Initialize USB endpoint pipe as the default zero control pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @return Error code.
+ */
+int usb_pipe_initialize_default_control(usb_pipe_t *pipe,
+    usb_device_connection_t *connection)
+{
+	assert(pipe);
+	assert(connection);
+
+	int rc = usb_pipe_initialize(pipe, connection,
+	    0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
+	    USB_DIRECTION_BOTH);
+
+	pipe->auto_reset_halt = true;
+
+	return rc;
+}
+
+/** Probe default control pipe for max packet size.
+ *
+ * The function tries to get the correct value of max packet size several
+ * time before giving up.
+ *
+ * The session on the pipe shall not be started.
+ *
+ * @param pipe Default control pipe.
+ * @return Error code.
+ */
+int usb_pipe_probe_default_control(usb_pipe_t *pipe)
+{
+	assert(pipe);
+	assert(DEV_DESCR_MAX_PACKET_SIZE_OFFSET < CTRL_PIPE_MIN_PACKET_SIZE);
+
+	if ((pipe->direction != USB_DIRECTION_BOTH) ||
+	    (pipe->transfer_type != USB_TRANSFER_CONTROL) ||
+	    (pipe->endpoint_no != 0)) {
+		return EINVAL;
+	}
+
+#define TRY_LOOP(attempt_var) \
+	for (attempt_var = 0; attempt_var < 3; attempt_var++)
+
+	size_t failed_attempts;
+	int rc;
+
+	usb_pipe_start_long_transfer(pipe);
+
+	uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
+	size_t transferred_size;
+	TRY_LOOP(failed_attempts) {
+		rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
+		    USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
+		    0, 0, dev_descr_start, CTRL_PIPE_MIN_PACKET_SIZE,
+		    &transferred_size);
+		if (rc == EOK) {
+			if (transferred_size != CTRL_PIPE_MIN_PACKET_SIZE) {
+				rc = ELIMIT;
+				continue;
+			}
+			break;
+		}
+	}
+	usb_pipe_end_long_transfer(pipe);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	pipe->max_packet_size
+	    = dev_descr_start[DEV_DESCR_MAX_PACKET_SIZE_OFFSET];
+
+	return EOK;
+}
+
+/** Register endpoint with the host controller.
+ *
+ * @param pipe Pipe to be registered.
+ * @param interval Polling interval.
+ * @param hc_connection Connection to the host controller (must be opened).
+ * @return Error code.
+ */
+int usb_pipe_register(usb_pipe_t *pipe,
+    unsigned int interval,
+    usb_hc_connection_t *hc_connection)
+{
+	return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,
+	    interval, hc_connection);
+}
+
+/** Register endpoint with a speed at the host controller.
+ *
+ * You will rarely need to use this function because it is needed only
+ * if the registered endpoint is of address 0 and there is no other way
+ * to tell speed of the device at address 0.
+ *
+ * @param pipe Pipe to be registered.
+ * @param speed Speed of the device
+ *	(invalid speed means use previously specified one).
+ * @param interval Polling interval.
+ * @param hc_connection Connection to the host controller (must be opened).
+ * @return Error code.
+ */
+int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,
+    unsigned int interval,
+    usb_hc_connection_t *hc_connection)
+{
+	assert(pipe);
+	assert(hc_connection);
+	
+	if (!usb_hc_connection_is_opened(hc_connection))
+		return EBADF;
+	
+#define _PACK2(high, low) (((high) << 16) + (low))
+#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
+	
+	async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
+	int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_REGISTER_ENDPOINT,
+	    _PACK2(pipe->wire->address, pipe->endpoint_no),
+	    _PACK3(speed, pipe->transfer_type, pipe->direction),
+	    _PACK2(pipe->max_packet_size, interval));
+	async_exchange_end(exch);
+	
+#undef _PACK2
+#undef _PACK3
+	
+	return rc;
+}
+
+/** Revert endpoint registration with the host controller.
+ *
+ * @param pipe Pipe to be unregistered.
+ * @param hc_connection Connection to the host controller (must be opened).
+ * @return Error code.
+ */
+int usb_pipe_unregister(usb_pipe_t *pipe,
+    usb_hc_connection_t *hc_connection)
+{
+	assert(pipe);
+	assert(hc_connection);
+	
+	if (!usb_hc_connection_is_opened(hc_connection))
+		return EBADF;
+	
+	async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
+	int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_UNREGISTER_ENDPOINT,
+	    pipe->wire->address, pipe->endpoint_no, pipe->direction);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/pipesio.c
===================================================================
--- uspace/lib/usbdev/src/pipesio.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/pipesio.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,610 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Input and output functions (reads and writes) on endpoint pipes.
+ *
+ * Note on synchronousness of the operations: there is ABSOLUTELY NO
+ * guarantee that a call to particular function will not trigger a fibril
+ * switch.
+ *
+ * Note about the implementation: the transfer requests are always divided
+ * into two functions.
+ * The outer one does checking of input parameters (e.g. that session was
+ * already started, buffers are not NULL etc), while the inner one
+ * (with _no_checks suffix) does the actual IPC (it checks for IPC errors,
+ * obviously).
+ */
+
+#include <usb/usb.h>
+#include <usb/dev/pipes.h>
+#include <errno.h>
+#include <assert.h>
+#include <usbhc_iface.h>
+#include <usb/dev/request.h>
+#include <async.h>
+#include "pipepriv.h"
+
+/** Request an in transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+static int usb_pipe_read_no_checks(usb_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	/*
+	 * Get corresponding IPC method.
+	 * In future, replace with static array of mappings
+	 * transfer type -> method.
+	 */
+	usbhc_iface_funcs_t ipc_method;
+	switch (pipe->transfer_type) {
+		case USB_TRANSFER_INTERRUPT:
+			ipc_method = IPC_M_USBHC_INTERRUPT_IN;
+			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_IN;
+			break;
+		default:
+			return ENOTSUP;
+	}
+	
+	/* Ensure serialization over the phone. */
+	pipe_start_transaction(pipe);
+	async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
+	
+	/*
+	 * Make call identifying target USB device and type of transfer.
+	 */
+	aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
+	
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		pipe_end_transaction(pipe);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Retrieve the data.
+	 */
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(exch, buffer, size,
+	    &data_request_call);
+	
+	/*
+	 * Since now on, someone else might access the backing phone
+	 * without breaking the transfer IPC protocol.
+	 */
+	async_exchange_end(exch);
+	pipe_end_transaction(pipe);
+	
+	if (data_request == 0) {
+		/*
+		 * FIXME:
+		 * How to let the other side know that we want to abort?
+		 */
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	if (data_request_rc != EOK) {
+		/* Prefer the return code of the opening request. */
+		if (opening_request_rc != EOK) {
+			return (int) opening_request_rc;
+		} else {
+			return (int) data_request_rc;
+		}
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+	
+	*size_transfered = IPC_GET_ARG2(data_request_call);
+	
+	return EOK;
+}
+
+
+/** Request a read (in) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+int usb_pipe_read(usb_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+		return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (pipe->direction != USB_DIRECTION_IN) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	int rc;
+	rc = pipe_add_ref(pipe, false);
+	if (rc != EOK) {
+		return rc;
+	}
+
+
+	size_t act_size = 0;
+
+	rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
+
+	pipe_drop_ref(pipe);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (size_transfered != NULL) {
+		*size_transfered = act_size;
+	}
+
+	return EOK;
+}
+
+
+
+
+/** Request an out transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+static int usb_pipe_write_no_check(usb_pipe_t *pipe,
+    void *buffer, size_t size)
+{
+	/*
+	 * Get corresponding IPC method.
+	 * In future, replace with static array of mappings
+	 * transfer type -> method.
+	 */
+	usbhc_iface_funcs_t ipc_method;
+	switch (pipe->transfer_type) {
+		case USB_TRANSFER_INTERRUPT:
+			ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
+			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_OUT;
+			break;
+		default:
+			return ENOTSUP;
+	}
+
+	/* Ensure serialization over the phone. */
+	pipe_start_transaction(pipe);
+	async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
+	
+	/*
+	 * Make call identifying target USB device and type of transfer.
+	 */
+	aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    ipc_method, pipe->wire->address, pipe->endpoint_no, NULL);
+	
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		pipe_end_transaction(pipe);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Send the data.
+	 */
+	int rc = async_data_write_start(exch, buffer, size);
+	
+	/*
+	 * Since now on, someone else might access the backing phone
+	 * without breaking the transfer IPC protocol.
+	 */
+	async_exchange_end(exch);
+	pipe_end_transaction(pipe);
+	
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+	
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	return (int) opening_request_rc;
+}
+
+/** Request a write (out) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+int usb_pipe_write(usb_pipe_t *pipe,
+    void *buffer, size_t size)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+		return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (pipe->direction != USB_DIRECTION_OUT) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	int rc;
+
+	rc = pipe_add_ref(pipe, false);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_pipe_write_no_check(pipe, buffer, size);
+
+	pipe_drop_ref(pipe);
+
+	return rc;
+}
+
+/** Try to clear endpoint halt of default control pipe.
+ *
+ * @param pipe Pipe for control endpoint zero.
+ */
+static void clear_self_endpoint_halt(usb_pipe_t *pipe)
+{
+	assert(pipe != NULL);
+
+	if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
+		return;
+	}
+
+
+	/* Prevent indefinite recursion. */
+	pipe->auto_reset_halt = false;
+	usb_request_clear_endpoint_halt(pipe, 0);
+	pipe->auto_reset_halt = true;
+}
+
+
+/** Request a control read transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+static int usb_pipe_control_read_no_check(usb_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	/* Ensure serialization over the phone. */
+	pipe_start_transaction(pipe);
+
+	/*
+	 * Make call identifying target USB device and control transfer type.
+	 */
+	async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
+	aid_t opening_request = async_send_3(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_CONTROL_READ, pipe->wire->address, pipe->endpoint_no,
+	    NULL);
+	
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Send the setup packet.
+	 */
+	int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		pipe_end_transaction(pipe);
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+	
+	/*
+	 * Retrieve the data.
+	 */
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(exch, data_buffer,
+	    data_buffer_size, &data_request_call);
+	
+	/*
+	 * Since now on, someone else might access the backing phone
+	 * without breaking the transfer IPC protocol.
+	 */
+	async_exchange_end(exch);
+	pipe_end_transaction(pipe);
+	
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		/* Prefer the return code of the opening request. */
+		if (opening_request_rc != EOK) {
+			return (int) opening_request_rc;
+		} else {
+			return (int) data_request_rc;
+		}
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*data_transfered_size = IPC_GET_ARG2(data_request_call);
+
+	return EOK;
+}
+
+/** Request a control read transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+int usb_pipe_control_read(usb_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer == NULL) || (data_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	int rc;
+
+	rc = pipe_add_ref(pipe, false);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	size_t act_size = 0;
+	rc = usb_pipe_control_read_no_check(pipe,
+	    setup_buffer, setup_buffer_size,
+	    data_buffer, data_buffer_size, &act_size);
+
+	if (rc == ESTALL) {
+		clear_self_endpoint_halt(pipe);
+	}
+
+	pipe_drop_ref(pipe);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (data_transfered_size != NULL) {
+		*data_transfered_size = act_size;
+	}
+
+	return EOK;
+}
+
+
+/** Request a control write transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+static int usb_pipe_control_write_no_check(usb_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	/* Ensure serialization over the phone. */
+	pipe_start_transaction(pipe);
+
+	/*
+	 * Make call identifying target USB device and control transfer type.
+	 */
+	async_exch_t *exch = async_exchange_begin(pipe->hc_sess);
+	aid_t opening_request = async_send_4(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_CONTROL_WRITE, pipe->wire->address, pipe->endpoint_no,
+	    data_buffer_size, NULL);
+	
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		pipe_end_transaction(pipe);
+		return ENOMEM;
+	}
+	
+	/*
+	 * Send the setup packet.
+	 */
+	int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		pipe_end_transaction(pipe);
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+	
+	/*
+	 * Send the data (if any).
+	 */
+	if (data_buffer_size > 0) {
+		rc = async_data_write_start(exch, data_buffer, data_buffer_size);
+		
+		/* All data sent, pipe can be released. */
+		async_exchange_end(exch);
+		pipe_end_transaction(pipe);
+	
+		if (rc != EOK) {
+			async_wait_for(opening_request, NULL);
+			return rc;
+		}
+	} else {
+		/* No data to send, we can release the pipe for others. */
+		async_exchange_end(exch);
+		pipe_end_transaction(pipe);
+	}
+	
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+/** Request a control write transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+int usb_pipe_control_write(usb_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer == NULL) && (data_buffer_size > 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer != NULL) && (data_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	int rc;
+
+	rc = pipe_add_ref(pipe, false);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_pipe_control_write_no_check(pipe,
+	    setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
+
+	if (rc == ESTALL) {
+		clear_self_endpoint_halt(pipe);
+	}
+
+	pipe_drop_ref(pipe);
+
+	return rc;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/recognise.c
===================================================================
--- uspace/lib/usbdev/src/recognise.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/recognise.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,442 @@
+/*
+ * 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 libusbdev
+ * @{
+ */
+/** @file
+ * Functions for recognition of attached devices.
+ */
+#include <sys/types.h>
+#include <fibril_synch.h>
+#include <usb/dev/pipes.h>
+#include <usb/dev/recognise.h>
+#include <usb/ddfiface.h>
+#include <usb/dev/request.h>
+#include <usb/classes/classes.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Index to append after device name for uniqueness. */
+static size_t device_name_index = 0;
+/** Mutex guard for device_name_index. */
+static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
+
+/** DDF operations of child devices. */
+ddf_dev_ops_t child_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
+};
+
+/** Get integer part from BCD coded number. */
+#define BCD_INT(a) (((unsigned int)(a)) / 256)
+/** Get fraction part from BCD coded number (as an integer, no less). */
+#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
+
+/** Format for BCD coded number to be used in printf. */
+#define BCD_FMT "%x.%x"
+/** Arguments to printf for BCD coded number. */
+#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
+
+/* FIXME: make this dynamic */
+#define MATCH_STRING_MAX 256
+
+/** Add formatted match id.
+ *
+ * @param matches List of match ids where to add to.
+ * @param score Score of the match.
+ * @param format Printf-like format
+ * @return Error code.
+ */
+static int usb_add_match_id(match_id_list_t *matches, int score,
+    const char *format, ...)
+{
+	char *match_str = NULL;
+	match_id_t *match_id = NULL;
+	int rc;
+	
+	match_str = malloc(MATCH_STRING_MAX + 1);
+	if (match_str == NULL) {
+		rc = ENOMEM;
+		goto failure;
+	}
+
+	/*
+	 * FIXME: replace with dynamic allocation of exact size
+	 */
+	va_list args;
+	va_start(args, format	);
+	vsnprintf(match_str, MATCH_STRING_MAX, format, args);
+	match_str[MATCH_STRING_MAX] = 0;
+	va_end(args);
+
+	match_id = create_match_id();
+	if (match_id == NULL) {
+		rc = ENOMEM;
+		goto failure;
+	}
+
+	match_id->id = match_str;
+	match_id->score = score;
+	add_match_id(matches, match_id);
+
+	return EOK;
+	
+failure:
+	if (match_str != NULL) {
+		free(match_str);
+	}
+	if (match_id != NULL) {
+		match_id->id = NULL;
+		delete_match_id(match_id);
+	}
+	
+	return rc;
+}
+
+/** Add match id to list or return with error code.
+ *
+ * @param match_ids List of match ids.
+ * @param score Match id score.
+ * @param format Format of the matching string
+ * @param ... Arguments for the format.
+ */
+#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
+	do { \
+		int __rc = usb_add_match_id((match_ids), (score), \
+		    format, ##__VA_ARGS__); \
+		if (__rc != EOK) { \
+			return __rc; \
+		} \
+	} while (0)
+
+/** Create device match ids based on its interface.
+ *
+ * @param[in] desc_device Device descriptor.
+ * @param[in] desc_interface Interface descriptor.
+ * @param[out] matches Initialized list of match ids.
+ * @return Error code (the two mentioned are not the only ones).
+ * @retval EINVAL Invalid input parameters (expects non NULL pointers).
+ * @retval ENOENT Device class is not "use interface".
+ */
+int usb_device_create_match_ids_from_interface(
+    const usb_standard_device_descriptor_t *desc_device,
+    const usb_standard_interface_descriptor_t *desc_interface,
+    match_id_list_t *matches)
+{
+	if (desc_interface == NULL) {
+		return EINVAL;
+	}
+	if (matches == NULL) {
+		return EINVAL;
+	}
+
+	if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {
+		return ENOENT;
+	}
+
+	const char *classname = usb_str_class(desc_interface->interface_class);
+	assert(classname != NULL);
+
+#define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"
+#define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \
+    desc_interface->interface_protocol
+
+#define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"
+#define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass
+
+#define IFACE_CLASS_FMT "interface&class=%s"
+#define IFACE_CLASS_ARGS classname
+
+#define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT
+#define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \
+    BCD_ARGS(desc_device->device_version)
+
+#define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"
+#define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id
+
+#define VENDOR_ONLY_FMT "vendor=0x%04x"
+#define VENDOR_ONLY_ARGS desc_device->vendor_id
+
+	/*
+	 * If the vendor is specified, create match ids with vendor with
+	 * higher score.
+	 * Then the same ones without the vendor part.
+	 */
+	if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {
+		/* First, interface matches with device release number. */
+		ADD_MATCHID_OR_RETURN(matches, 250,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 240,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 230,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);
+
+		/* Next, interface matches without release number. */
+		ADD_MATCHID_OR_RETURN(matches, 220,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 210,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 200,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);
+
+		/* Finally, interface matches with only vendor. */
+		ADD_MATCHID_OR_RETURN(matches, 190,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 180,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 170,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);
+	}
+
+	/* Now, the same but without any vendor specification. */
+	ADD_MATCHID_OR_RETURN(matches, 160,
+	    "usb&" IFACE_PROTOCOL_FMT,
+	    IFACE_PROTOCOL_ARGS);
+	ADD_MATCHID_OR_RETURN(matches, 150,
+	    "usb&" IFACE_SUBCLASS_FMT,
+	    IFACE_SUBCLASS_ARGS);
+	ADD_MATCHID_OR_RETURN(matches, 140,
+	    "usb&" IFACE_CLASS_FMT,
+	    IFACE_CLASS_ARGS);
+
+#undef IFACE_PROTOCOL_FMT
+#undef IFACE_PROTOCOL_ARGS
+#undef IFACE_SUBCLASS_FMT
+#undef IFACE_SUBCLASS_ARGS
+#undef IFACE_CLASS_FMT
+#undef IFACE_CLASS_ARGS
+#undef VENDOR_RELEASE_FMT
+#undef VENDOR_RELEASE_ARGS
+#undef VENDOR_PRODUCT_FMT
+#undef VENDOR_PRODUCT_ARGS
+#undef VENDOR_ONLY_FMT
+#undef VENDOR_ONLY_ARGS
+
+	/* As a last resort, try fallback driver. */
+	ADD_MATCHID_OR_RETURN(matches, 10, "usb&interface&fallback");
+
+	return EOK;
+}
+
+/** Create DDF match ids from USB device descriptor.
+ *
+ * @param matches List of match ids to extend.
+ * @param device_descriptor Device descriptor returned by given device.
+ * @return Error code.
+ */
+int usb_device_create_match_ids_from_device_descriptor(
+    const usb_standard_device_descriptor_t *device_descriptor,
+    match_id_list_t *matches)
+{
+	/*
+	 * Unless the vendor id is 0, the pair idVendor-idProduct
+	 * quite uniquely describes the device.
+	 */
+	if (device_descriptor->vendor_id != 0) {
+		/* First, with release number. */
+		ADD_MATCHID_OR_RETURN(matches, 100,
+		    "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
+		    (int) device_descriptor->vendor_id,
+		    (int) device_descriptor->product_id,
+		    BCD_ARGS(device_descriptor->device_version));
+		
+		/* Next, without release number. */
+		ADD_MATCHID_OR_RETURN(matches, 90,
+		    "usb&vendor=0x%04x&product=0x%04x",
+		    (int) device_descriptor->vendor_id,
+		    (int) device_descriptor->product_id);
+	}	
+
+	/*
+	 * If the device class points to interface we skip adding
+	 * class directly but we add a multi interface device.
+	 */
+	if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
+		ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
+		    usb_str_class(device_descriptor->device_class));
+	} else {
+		ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
+	}
+	
+	/* As a last resort, try fallback driver. */
+	ADD_MATCHID_OR_RETURN(matches, 10, "usb&fallback");
+
+	return EOK;
+}
+
+
+/** Create match ids describing attached device.
+ *
+ * @warning The list of match ids @p matches may change even when
+ * function exits with error.
+ *
+ * @param ctrl_pipe Control pipe to given device (session must be already
+ *	started).
+ * @param matches Initialized list of match ids.
+ * @return Error code.
+ */
+int usb_device_create_match_ids(usb_pipe_t *ctrl_pipe,
+    match_id_list_t *matches)
+{
+	int rc;
+	/*
+	 * Retrieve device descriptor and add matches from it.
+	 */
+	usb_standard_device_descriptor_t device_descriptor;
+
+	rc = usb_request_get_device_descriptor(ctrl_pipe, &device_descriptor);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_device_create_match_ids_from_device_descriptor(
+	    &device_descriptor, matches);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Probe for device kind and register it in devman.
+ *
+ * @param[in] address Address of the (unknown) attached device.
+ * @param[in] hc_handle Handle of the host controller.
+ * @param[in] parent Parent device.
+ * @param[out] child_handle Handle of the child device.
+ * @param[in] dev_ops Child device ops.
+ * @param[in] dev_data Arbitrary pointer to be stored in the child
+ *	as @c driver_data.
+ * @param[out] child_fun Storage where pointer to allocated child function
+ *	will be written.
+ * @return Error code.
+ */
+int usb_device_register_child_in_devman(usb_address_t address,
+    devman_handle_t hc_handle,
+    ddf_dev_t *parent, devman_handle_t *child_handle,
+    ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
+{
+	size_t this_device_name_index;
+
+	fibril_mutex_lock(&device_name_index_mutex);
+	this_device_name_index = device_name_index;
+	device_name_index++;
+	fibril_mutex_unlock(&device_name_index_mutex);
+
+	ddf_fun_t *child = NULL;
+	char *child_name = NULL;
+	int rc;
+	usb_device_connection_t dev_connection;
+	usb_pipe_t ctrl_pipe;
+
+	rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_pipe_initialize_default_control(&ctrl_pipe,
+	    &dev_connection);
+	if (rc != EOK) {
+		goto failure;
+	}
+	rc = usb_pipe_probe_default_control(&ctrl_pipe);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	/*
+	 * TODO: Once the device driver framework support persistent
+	 * naming etc., something more descriptive could be created.
+	 */
+	rc = asprintf(&child_name, "usb%02zu_a%d",
+	    this_device_name_index, address);
+	if (rc < 0) {
+		goto failure;
+	}
+
+	child = ddf_fun_create(parent, fun_inner, child_name);
+	if (child == NULL) {
+		rc = ENOMEM;
+		goto failure;
+	}
+
+	if (dev_ops != NULL) {
+		child->ops = dev_ops;
+	} else {
+		child->ops = &child_ops;
+	}
+
+	child->driver_data = dev_data;
+
+	rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = ddf_fun_bind(child);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	if (child_handle != NULL) {
+		*child_handle = child->handle;
+	}
+
+	if (child_fun != NULL) {
+		*child_fun = child;
+	}
+
+	return EOK;
+
+failure:
+	if (child != NULL) {
+		child->name = NULL;
+		/* This takes care of match_id deallocation as well. */
+		ddf_fun_destroy(child);
+	}
+	if (child_name != NULL) {
+		free(child_name);
+	}
+
+	return rc;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usbdev/src/request.c
===================================================================
--- uspace/lib/usbdev/src/request.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbdev/src/request.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,930 @@
+/*
+ * Copyright (c) 2011 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 libusbdev
+ * @{
+ */
+/** @file
+ * Standard USB requests (implementation).
+ */
+#include <usb/dev/request.h>
+#include <errno.h>
+#include <assert.h>
+#include <usb/debug.h>
+
+#define MAX_DATA_LENGTH ((size_t)(0xFFFF))
+
+/** Generic wrapper for SET requests using standard control request format.
+ *
+ * @see usb_pipe_control_write
+ *
+ * @param pipe Pipe used for the communication.
+ * @param request_type Request type (standard/class/vendor).
+ * @param recipient Request recipient (e.g. device or endpoint).
+ * @param request Actual request (e.g. GET_DESCRIPTOR).
+ * @param value Value of @c wValue field of setup packet
+ * 	(must be in USB endianness).
+ * @param index Value of @c wIndex field of setup packet
+ * 	(must be in USB endianness).
+ * @param data Data to be sent during DATA stage
+ * 	(expected to be in USB endianness).
+ * @param data_size Size of the @p data buffer (in native endianness).
+ * @return Error code.
+ * @retval EBADMEM @p pipe is NULL.
+ * @retval EBADMEM @p data is NULL and @p data_size is not zero.
+ * @retval ERANGE Data buffer too large.
+ */
+int usb_control_request_set(usb_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t request,
+    uint16_t value, uint16_t index,
+    void *data, size_t data_size)
+{
+	if (pipe == NULL) {
+		return EBADMEM;
+	}
+
+	if (data_size > MAX_DATA_LENGTH) {
+		return ERANGE;
+	}
+
+	if ((data_size > 0) && (data == NULL)) {
+		return EBADMEM;
+	}
+
+	/*
+	 * TODO: check that @p request_type and @p recipient are
+	 * within ranges.
+	 */
+
+	usb_device_request_setup_packet_t setup_packet;
+	setup_packet.request_type = (request_type << 5) | recipient;
+	setup_packet.request = request;
+	setup_packet.value = value;
+	setup_packet.index = index;
+	setup_packet.length = (uint16_t) data_size;
+
+	int rc = usb_pipe_control_write(pipe,
+	    &setup_packet, sizeof(setup_packet),
+	    data, data_size);
+
+	return rc;
+}
+
+ /** Generic wrapper for GET requests using standard control request format.
+  *
+  * @see usb_pipe_control_read
+  *
+  * @param pipe Pipe used for the communication.
+  * @param request_type Request type (standard/class/vendor).
+  * @param recipient Request recipient (e.g. device or endpoint).
+  * @param request Actual request (e.g. GET_DESCRIPTOR).
+  * @param value Value of @c wValue field of setup packet
+  * 	(must be in USB endianness).
+  * @param index Value of @c wIndex field of setup packet
+  *	(must be in USB endianness).
+  * @param data Buffer where to store data accepted during the DATA stage.
+  *	(they will come in USB endianness).
+  * @param data_size Size of the @p data buffer
+  * 	(in native endianness).
+  * @param actual_data_size Actual size of transfered data
+  * 	(in native endianness).
+  * @return Error code.
+  * @retval EBADMEM @p pipe is NULL.
+  * @retval EBADMEM @p data is NULL and @p data_size is not zero.
+  * @retval ERANGE Data buffer too large.
+  */
+int usb_control_request_get(usb_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t request,
+    uint16_t value, uint16_t index,
+    void *data, size_t data_size, size_t *actual_data_size)
+{
+	if (pipe == NULL) {
+		return EBADMEM;
+	}
+
+	if (data_size > MAX_DATA_LENGTH) {
+		return ERANGE;
+	}
+
+	if ((data_size > 0) && (data == NULL)) {
+		return EBADMEM;
+	}
+
+	/*
+	 * TODO: check that @p request_type and @p recipient are
+	 * within ranges.
+	 */
+
+	usb_device_request_setup_packet_t setup_packet;
+	setup_packet.request_type = 128 | (request_type << 5) | recipient;
+	setup_packet.request = request;
+	setup_packet.value = value;
+	setup_packet.index = index;
+	setup_packet.length = (uint16_t) data_size;
+
+	int rc = usb_pipe_control_read(pipe,
+	    &setup_packet, sizeof(setup_packet),
+	    data, data_size, actual_data_size);
+
+	return rc;
+}
+
+/** Retrieve status of a USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Recipient index (in native endianness).
+ * @param[in] recipient Recipient of the GET_STATUS request.
+ * @param[out] status Recipient status (in native endianness).
+ * @return Error code.
+ */
+int usb_request_get_status(usb_pipe_t *pipe,
+    usb_request_recipient_t recipient, uint16_t index,
+    uint16_t *status)
+{
+	if ((recipient == USB_REQUEST_RECIPIENT_DEVICE) && (index != 0)) {
+		return EINVAL;
+	}
+
+	if (status == NULL) {
+		return EBADMEM;
+	}
+
+	uint16_t status_usb_endianess;
+	size_t data_transfered_size;
+	int rc = usb_control_request_get(pipe, USB_REQUEST_TYPE_STANDARD,
+	    recipient, USB_DEVREQ_GET_STATUS, 0, uint16_host2usb(index),
+	    &status_usb_endianess, 2, &data_transfered_size);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (data_transfered_size != 2) {
+		return ELIMIT;
+	}
+
+	*status = uint16_usb2host(status_usb_endianess);
+
+	return EOK;
+}
+
+/** Clear or disable specific device feature.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] recipient Recipient of the CLEAR_FEATURE request.
+ * @param[in] feature_selector Feature selector (in native endianness).
+ * @param[in] index Recipient index (in native endianness).
+ * @return Error code.
+ */
+int usb_request_clear_feature(usb_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint16_t feature_selector, uint16_t index)
+{
+	if (request_type == USB_REQUEST_TYPE_STANDARD) {
+		if ((recipient == USB_REQUEST_RECIPIENT_DEVICE)
+		    && (index != 0)) {
+			return EINVAL;
+		}
+	}
+
+	int rc = usb_control_request_set(pipe, request_type, recipient,
+	    USB_DEVREQ_CLEAR_FEATURE,
+	    uint16_host2usb(feature_selector), uint16_host2usb(index),
+	    NULL, 0);
+
+	return rc;
+}
+
+/** Set or enable specific device feature.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] recipient Recipient of the SET_FEATURE request.
+ * @param[in] feature_selector Feature selector (in native endianness).
+ * @param[in] index Recipient index (in native endianness).
+ * @return Error code.
+ */
+int usb_request_set_feature(usb_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint16_t feature_selector, uint16_t index)
+{
+	if (request_type == USB_REQUEST_TYPE_STANDARD) {
+		if ((recipient == USB_REQUEST_RECIPIENT_DEVICE)
+		    && (index != 0)) {
+			return EINVAL;
+		}
+	}
+
+	int rc = usb_control_request_set(pipe, request_type, recipient,
+	    USB_DEVREQ_SET_FEATURE,
+	    uint16_host2usb(feature_selector), uint16_host2usb(index),
+	    NULL, 0);
+
+	return rc;
+}
+
+/** Change address of connected device.
+ * This function automatically updates the backing connection to point to
+ * the new address.
+ *
+ * @param pipe Control endpoint pipe (session must be already started).
+ * @param new_address New USB address to be set (in native endianness).
+ * @return Error code.
+ */
+int usb_request_set_address(usb_pipe_t *pipe,
+    usb_address_t new_address)
+{
+	if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
+		return EINVAL;
+	}
+
+	uint16_t addr = uint16_host2usb((uint16_t)new_address);
+
+	int rc = usb_control_request_set(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_ADDRESS,
+	    addr, 0,
+	    NULL, 0);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	assert(pipe->wire != NULL);
+	/* TODO: prevent other from accessing wire now. */
+	pipe->wire->address = new_address;
+
+	return EOK;
+}
+
+/** Retrieve USB descriptor of a USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] recipient Request recipient (device/interface/endpoint).
+ * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index.
+ * @param[out] buffer Buffer where to store the retrieved descriptor.
+ * @param[in] size Size of the @p buffer.
+ * @param[out] actual_size Number of bytes actually transferred.
+ * @return Error code.
+ */
+int usb_request_get_descriptor(usb_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void *buffer, size_t size, size_t *actual_size)
+{
+	if (buffer == NULL) {
+		return EBADMEM;
+	}
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	uint16_t wValue = descriptor_index | (descriptor_type << 8);
+
+	return usb_control_request_get(pipe,
+	    request_type, recipient,
+	    USB_DEVREQ_GET_DESCRIPTOR,
+	    wValue, language,
+	    buffer, size, actual_size);
+}
+
+/** Retrieve USB descriptor, allocate space for it.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] recipient Request recipient (device/interface/endpoint).
+ * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index.
+ * @param[out] buffer_ptr Where to store pointer to allocated buffer.
+ * @param[out] buffer_size Where to store the size of the descriptor.
+ * @return
+ */
+int usb_request_get_descriptor_alloc(usb_pipe_t * pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void **buffer_ptr, size_t *buffer_size)
+{
+	if (buffer_ptr == NULL) {
+		return EBADMEM;
+	}
+
+	int rc;
+
+	/*
+	 * Get only first byte to retrieve descriptor length.
+	 */
+	uint8_t tmp_buffer[1];
+	size_t bytes_transfered;
+	rc = usb_request_get_descriptor(pipe, request_type, recipient,
+	    descriptor_type, descriptor_index, language,
+	    &tmp_buffer, 1, &bytes_transfered);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (bytes_transfered != 1) {
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	size_t size = tmp_buffer[0];
+	if (size == 0) {
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	/*
+	 * Allocate buffer and get the descriptor again.
+	 */
+	void *buffer = malloc(size);
+	if (buffer == NULL) {
+		return ENOMEM;
+	}
+
+	rc = usb_request_get_descriptor(pipe, request_type, recipient,
+	    descriptor_type, descriptor_index, language,
+	    buffer, size, &bytes_transfered);
+	if (rc != EOK) {
+		free(buffer);
+		return rc;
+	}
+	if (bytes_transfered != size) {
+		free(buffer);
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	*buffer_ptr = buffer;
+	if (buffer_size != NULL) {
+		*buffer_size = size;
+	}
+
+	return EOK;
+}
+
+/** Retrieve standard device descriptor of a USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[out] descriptor Storage for the device descriptor.
+ * @return Error code.
+ */
+int usb_request_get_device_descriptor(usb_pipe_t *pipe,
+    usb_standard_device_descriptor_t *descriptor)
+{
+	if (descriptor == NULL) {
+		return EBADMEM;
+	}
+
+	size_t actually_transferred = 0;
+	usb_standard_device_descriptor_t descriptor_tmp;
+	int rc = usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 
+	    USB_DESCTYPE_DEVICE, 0, 0,
+	    &descriptor_tmp, sizeof(descriptor_tmp),
+	    &actually_transferred);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Verify that all data has been transferred. */
+	if (actually_transferred < sizeof(descriptor_tmp)) {
+		return ELIMIT;
+	}
+
+	/* Everything is okay, copy the descriptor. */
+	memcpy(descriptor, &descriptor_tmp,
+	    sizeof(descriptor_tmp));
+
+	return EOK;
+}
+
+/** Retrieve configuration descriptor of a USB device.
+ *
+ * The function does not retrieve additional data binded with configuration
+ * descriptor (such as its interface and endpoint descriptors) - use
+ * usb_request_get_full_configuration_descriptor() instead.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Descriptor index.
+ * @param[out] descriptor Storage for the device descriptor.
+ * @return Error code.
+ */
+int usb_request_get_bare_configuration_descriptor(usb_pipe_t *pipe,
+    int index, usb_standard_configuration_descriptor_t *descriptor)
+{
+	if (descriptor == NULL) {
+		return EBADMEM;
+	}
+
+	if ((index < 0) || (index > 0xFF)) {
+		return ERANGE;
+	}
+
+	size_t actually_transferred = 0;
+	usb_standard_configuration_descriptor_t descriptor_tmp;
+	int rc = usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_CONFIGURATION, index, 0,
+	    &descriptor_tmp, sizeof(descriptor_tmp),
+	    &actually_transferred);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Verify that all data has been transferred. */
+	if (actually_transferred < sizeof(descriptor_tmp)) {
+		return ELIMIT;
+	}
+
+	/* Everything is okay, copy the descriptor. */
+	memcpy(descriptor, &descriptor_tmp,
+	    sizeof(descriptor_tmp));
+
+	return EOK;
+}
+
+/** Retrieve full configuration descriptor of a USB device.
+ *
+ * @warning The @p buffer might be touched (i.e. its contents changed)
+ * even when error occurs.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Descriptor index.
+ * @param[out] descriptor Storage for the device descriptor.
+ * @param[in] descriptor_size Size of @p descriptor buffer.
+ * @param[out] actual_size Number of bytes actually transferred.
+ * @return Error code.
+ */
+int usb_request_get_full_configuration_descriptor(usb_pipe_t *pipe,
+    int index, void *descriptor, size_t descriptor_size, size_t *actual_size)
+{
+	if ((index < 0) || (index > 0xFF)) {
+		return ERANGE;
+	}
+
+	return usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_CONFIGURATION, index, 0,
+	    descriptor, descriptor_size, actual_size);
+}
+
+/** Retrieve full configuration descriptor, allocate space for it.
+ *
+ * The function takes care that full configuration descriptor is returned
+ * (i.e. the function will fail when less data then descriptor.totalLength
+ * is returned).
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Configuration index.
+ * @param[out] descriptor_ptr Where to store pointer to allocated buffer.
+ * @param[out] descriptor_size Where to store the size of the descriptor.
+ * @return Error code.
+ */
+int usb_request_get_full_configuration_descriptor_alloc(
+    usb_pipe_t *pipe, int index,
+    void **descriptor_ptr, size_t *descriptor_size)
+{
+	int rc;
+
+	if (descriptor_ptr == NULL) {
+		return EBADMEM;
+	}
+
+	usb_standard_configuration_descriptor_t bare_config;
+	rc = usb_request_get_bare_configuration_descriptor(pipe, index,
+	    &bare_config);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (bare_config.descriptor_type != USB_DESCTYPE_CONFIGURATION) {
+		return ENOENT;
+	}
+	if (bare_config.total_length < sizeof(bare_config)) {
+		return ELIMIT;
+	}
+
+	void *buffer = malloc(bare_config.total_length);
+	if (buffer == NULL) {
+		return ENOMEM;
+	}
+
+	size_t transferred = 0;
+	rc = usb_request_get_full_configuration_descriptor(pipe, index,
+	    buffer, bare_config.total_length, &transferred);
+	if (rc != EOK) {
+		free(buffer);
+		return rc;
+	}
+
+	if (transferred != bare_config.total_length) {
+		free(buffer);
+		return ELIMIT;
+	}
+
+	/* Everything looks okay, copy the pointers. */
+
+	*descriptor_ptr = buffer;
+
+	if (descriptor_size != NULL) {
+		*descriptor_size = bare_config.total_length;
+	}
+
+	return EOK;
+}
+
+/** Update existing or add new USB descriptor to a USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] recipient Request recipient (device/interface/endpoint).
+ * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index (in native endianness).
+ * @param[in] buffer Buffer with the new descriptor (in USB endianness).
+ * @param[in] size Size of the @p buffer in bytes (in native endianness).
+ * @return Error code.
+ */
+int usb_request_set_descriptor(usb_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void *buffer, size_t size)
+{
+	if (buffer == NULL) {
+		return EBADMEM;
+	}
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	/* FIXME: proper endianness. */
+	uint16_t wValue = descriptor_index | (descriptor_type << 8);
+
+	return usb_control_request_set(pipe,
+	    request_type, recipient,
+	    USB_DEVREQ_SET_DESCRIPTOR,
+	    wValue, language,
+	    buffer, size);
+}
+
+/** Get current configuration value of USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[out] configuration_value Current configuration value.
+ * @return Error code.
+ */
+int usb_request_get_configuration(usb_pipe_t *pipe,
+    uint8_t *configuration_value)
+{
+	uint8_t value;
+	size_t actual_size;
+
+	int rc = usb_control_request_get(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_GET_CONFIGURATION,
+	    0, 0,
+	    &value, 1, &actual_size);
+
+	if (rc != EOK) {
+		return rc;
+	}
+	if (actual_size != 1) {
+		return ELIMIT;
+	}
+
+	if (configuration_value != NULL) {
+		*configuration_value = value;
+	}
+
+	return EOK;
+}
+
+/** Set configuration of USB device.
+ *
+ * @param pipe Control endpoint pipe (session must be already started).
+ * @param configuration_value New configuration value.
+ * @return Error code.
+ */
+int usb_request_set_configuration(usb_pipe_t *pipe,
+    uint8_t configuration_value)
+{
+	uint16_t config_value
+	    = uint16_host2usb((uint16_t) configuration_value);
+
+	return usb_control_request_set(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_CONFIGURATION, config_value, 0,
+	    NULL, 0);
+}
+
+/** Get selected alternate setting for USB interface.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] interface_index Interface index.
+ * @param[out] alternate_setting Alternate setting for the interface.
+ * @return Error code.
+ */
+int usb_request_get_interface(usb_pipe_t *pipe,
+    uint8_t interface_index, uint8_t *alternate_setting)
+{
+	uint8_t value;
+	size_t actual_size;
+
+	int rc = usb_control_request_get(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DEVREQ_GET_INTERFACE,
+	    0, uint16_host2usb((uint16_t) interface_index),
+	    &value, 1, &actual_size);
+
+	if (rc != EOK) {
+		return rc;
+	}
+	if (actual_size != 1) {
+		return ELIMIT;
+	}
+
+	if (alternate_setting != NULL) {
+		*alternate_setting = value;
+	}
+
+	return EOK;
+}
+
+/** Select alternate setting for USB interface.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] interface_index Interface index.
+ * @param[in] alternate_setting Alternate setting to select.
+ * @return Error code.
+ */
+int usb_request_set_interface(usb_pipe_t *pipe,
+    uint8_t interface_index, uint8_t alternate_setting)
+{
+	return usb_control_request_set(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DEVREQ_SET_INTERFACE,
+	    uint16_host2usb((uint16_t) alternate_setting),
+	    uint16_host2usb((uint16_t) interface_index),
+	    NULL, 0);
+}
+
+/** Get list of supported languages by USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[out] languages_ptr Where to store pointer to allocated array of
+ *	supported languages.
+ * @param[out] languages_count Number of supported languages.
+ * @return Error code.
+ */
+int usb_request_get_supported_languages(usb_pipe_t *pipe,
+    l18_win_locales_t **languages_ptr, size_t *languages_count)
+{
+	int rc;
+
+	if (languages_ptr == NULL) {
+		return EBADMEM;
+	}
+	if (languages_count == NULL) {
+		return EBADMEM;
+	}
+
+	uint8_t *string_descriptor = NULL;
+	size_t string_descriptor_size = 0;
+	rc = usb_request_get_descriptor_alloc(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_STRING, 0, 0,
+	    (void **) &string_descriptor, &string_descriptor_size);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (string_descriptor_size <= 2) {
+		free(string_descriptor);
+		return EEMPTY;
+	}
+	/* Subtract first 2 bytes (length and descriptor type). */
+	string_descriptor_size -= 2;
+
+	/* Odd number of bytes - descriptor is broken? */
+	if ((string_descriptor_size % 2) != 0) {
+		/* FIXME: shall we return with error or silently ignore? */
+		free(string_descriptor);
+		return ESTALL;
+	}
+
+	size_t langs_count = string_descriptor_size / 2;
+	l18_win_locales_t *langs
+	    = malloc(sizeof(l18_win_locales_t) * langs_count);
+	if (langs == NULL) {
+		free(string_descriptor);
+		return ENOMEM;
+	}
+
+	size_t i;
+	for (i = 0; i < langs_count; i++) {
+		/* Language code from the descriptor is in USB endianness. */
+		/* FIXME: is this really correct? */
+		uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8)
+		    + string_descriptor[2 + 2 * i];
+		langs[i] = uint16_usb2host(lang_code);
+	}
+
+	free(string_descriptor);
+
+	*languages_ptr = langs;
+	*languages_count =langs_count;
+
+	return EOK;
+}
+
+/** Get string (descriptor) from USB device.
+ *
+ * The string is returned in native encoding of the operating system.
+ * For HelenOS, that is UTF-8.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index String index (in native endianness),
+ *	first index has number 1 (index from descriptors can be used directly).
+ * @param[in] lang String language (in native endianness).
+ * @param[out] string_ptr Where to store allocated string in native encoding.
+ * @return Error code.
+ */
+int usb_request_get_string(usb_pipe_t *pipe,
+    size_t index, l18_win_locales_t lang, char **string_ptr)
+{
+	if (string_ptr == NULL) {
+		return EBADMEM;
+	}
+	/*
+	 * Index is actually one byte value and zero index is used
+	 * to retrieve list of supported languages.
+	 */
+	if ((index < 1) || (index > 0xFF)) {
+		return ERANGE;
+	}
+	/* Language is actually two byte value. */
+	if (lang > 0xFFFF) {
+		return ERANGE;
+	}
+
+	int rc;
+
+	/* Prepare dynamically allocated variables. */
+	uint8_t *string = NULL;
+	wchar_t *string_chars = NULL;
+
+	/* Get the actual descriptor. */
+	size_t string_size;
+	rc = usb_request_get_descriptor_alloc(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_STRING, index, uint16_host2usb(lang),
+	    (void **) &string, &string_size);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	if (string_size <= 2) {
+		rc =  EEMPTY;
+		goto leave;
+	}
+	/* Subtract first 2 bytes (length and descriptor type). */
+	string_size -= 2;
+
+	/* Odd number of bytes - descriptor is broken? */
+	if ((string_size % 2) != 0) {
+		/* FIXME: shall we return with error or silently ignore? */
+		rc = ESTALL;
+		goto leave;
+	}
+
+	size_t string_char_count = string_size / 2;
+	string_chars = malloc(sizeof(wchar_t) * (string_char_count + 1));
+	if (string_chars == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	/*
+	 * Build a wide string.
+	 * And do not forget to set NULL terminator (string descriptors
+	 * do not have them).
+	 */
+	size_t i;
+	for (i = 0; i < string_char_count; i++) {
+		uint16_t uni_char = (string[2 + 2 * i + 1] << 8)
+		    + string[2 + 2 * i];
+		string_chars[i] = uni_char;
+	}
+	string_chars[string_char_count] = 0;
+
+
+	/* Convert to normal string. */
+	char *str = wstr_to_astr(string_chars);
+	if (str == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	*string_ptr = str;
+	rc = EOK;
+
+leave:
+	if (string != NULL) {
+		free(string);
+	}
+	if (string_chars != NULL) {
+		free(string_chars);
+	}
+
+	return rc;
+}
+
+/** Clear halt bit of an endpoint pipe (after pipe stall).
+ *
+ * @param pipe Control pipe.
+ * @param ep_index Endpoint index (in native endianness).
+ * @return Error code.
+ */
+int usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
+{
+	return usb_request_clear_feature(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT,
+	    uint16_host2usb(USB_FEATURE_SELECTOR_ENDPOINT_HALT),
+	    uint16_host2usb(ep_index));
+}
+
+/** Clear halt bit of an endpoint pipe (after pipe stall).
+ *
+ * @param ctrl_pipe Control pipe.
+ * @param target_pipe Which pipe is halted and shall be cleared.
+ * @return Error code.
+ */
+int usb_pipe_clear_halt(usb_pipe_t *ctrl_pipe, usb_pipe_t *target_pipe)
+{
+	if ((ctrl_pipe == NULL) || (target_pipe == NULL)) {
+		return EINVAL;
+	}
+	return usb_request_clear_endpoint_halt(ctrl_pipe,
+	    target_pipe->endpoint_no);
+}
+
+/** Get endpoint status.
+ *
+ * @param[in] ctrl_pipe Control pipe.
+ * @param[in] pipe Of which pipe the status shall be received.
+ * @param[out] status Where to store pipe status (in native endianness).
+ * @return Error code.
+ */
+int usb_request_get_endpoint_status(usb_pipe_t *ctrl_pipe, usb_pipe_t *pipe,
+    uint16_t *status)
+{
+	uint16_t status_tmp;
+	uint16_t pipe_index = (uint16_t) pipe->endpoint_no;
+	int rc = usb_request_get_status(ctrl_pipe,
+	    USB_REQUEST_RECIPIENT_ENDPOINT, uint16_host2usb(pipe_index),
+	    &status_tmp);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (status != NULL) {
+		*status = uint16_usb2host(status_tmp);
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/Makefile
===================================================================
--- uspace/lib/usbhid/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+LIBRARY = libusbhid
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include \
+	-Iinclude
+
+SOURCES = \
+	src/hiddescriptor.c \
+	src/hidiface.c \
+	src/hidparser.c \
+	src/hidpath.c \
+	src/hidreport.c \
+	src/consumer.c \
+	src/hidreq.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usbhid/include/usb/hid/hid.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/hid.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,75 @@
+/*
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * @brief USB HID device related types.
+ */
+#ifndef LIBUSBHID_HID_H_
+#define LIBUSBHID_HID_H_
+
+#include <usb/usb.h>
+#include <usb/hid/hidparser.h>
+#include <usb/descriptor.h>
+
+/** USB/HID device requests. */
+typedef enum {
+	USB_HIDREQ_GET_REPORT = 1,
+	USB_HIDREQ_GET_IDLE = 2,
+	USB_HIDREQ_GET_PROTOCOL = 3,
+	/* Values 4 to 8 are reserved. */
+	USB_HIDREQ_SET_REPORT = 9,
+	USB_HIDREQ_SET_IDLE = 10,
+	USB_HIDREQ_SET_PROTOCOL = 11
+} usb_hid_request_t;
+
+typedef enum {
+	USB_HID_PROTOCOL_BOOT = 0,
+	USB_HID_PROTOCOL_REPORT = 1
+} usb_hid_protocol_t;
+
+/** USB/HID subclass constants. */
+typedef enum {
+	USB_HID_SUBCLASS_NONE = 0,
+	USB_HID_SUBCLASS_BOOT = 1
+} usb_hid_subclass_t;
+
+/** USB/HID interface protocols. */
+typedef enum {
+	USB_HID_PROTOCOL_NONE = 0,
+	USB_HID_PROTOCOL_KEYBOARD = 1,
+	USB_HID_PROTOCOL_MOUSE = 2
+} usb_hid_iface_protocol_t;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/hid_report_items.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hid_report_items.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/hid_report_items.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2011 Matej Klonfar
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * @brief USB HID Report descriptor item tags.
+ */
+#ifndef LIBUSB_HID_REPORT_ITEMS_H_
+#define LIBUSB_HID_REPORT_ITEMS_H_
+
+#include <stdint.h>
+
+/*---------------------------------------------------------------------------*/
+/*
+ * Item prefix
+ */
+
+/** Returns size of item data in bytes */
+#define USB_HID_ITEM_SIZE(data) 	((uint8_t)(data & 0x3))
+
+/** Returns item tag */
+#define USB_HID_ITEM_TAG(data) 		((uint8_t)((data & 0xF0) >> 4))
+
+/** Returns class of item tag */
+#define USB_HID_ITEM_TAG_CLASS(data)	((uint8_t)((data & 0xC) >> 2))
+
+/** Returns if the item is the short item or long item. Long items are not
+ * supported. */
+#define USB_HID_ITEM_IS_LONG(data)	(data == 0xFE)
+
+/*---------------------------------------------------------------------------*/
+/*
+ * Extended usage macros
+ */
+
+/** Recognizes if the given usage is extended (contains also usage page).  */
+#define USB_HID_IS_EXTENDED_USAGE(usage)	((usage & 0xFFFF0000) != 0)
+
+/** Cuts usage page of the extended usage. */
+#define USB_HID_EXTENDED_USAGE_PAGE(usage)	((usage & 0xFFFF0000) >> 16)
+
+/** Cuts usage of the extended usage */
+#define USB_HID_EXTENDED_USAGE(usage)		(usage & 0xFFFF)
+
+/*---------------------------------------------------------------------------*/
+/*
+ * Input/Output/Feature Item flags
+ */
+/** 
+ * Indicates whether the item is data (0) or a constant (1) value. Data
+ * indicates the item is defining report fields that contain modifiable device
+ * data. Constant indicates the item is a static read-only field in a report
+ * and cannot be modified (written) by the host.
+ */
+#define USB_HID_ITEM_FLAG_CONSTANT(flags) 	((flags & 0x1) == 0x1)
+
+/**
+ * Indicates whether the item creates variable (1) or array (0) data fields in
+ * reports. 
+ */
+#define USB_HID_ITEM_FLAG_VARIABLE(flags) 	((flags & 0x2) == 0x2)
+
+/**
+ * Indicates whether the data is absolute (0) (based on a fixed origin) or
+ * relative (1) (indicating the change in value from the last report). Mouse
+ * devices usually provide relative data, while tablets usually provide
+ * absolute data.
+ */
+#define USB_HID_ITEM_FLAG_RELATIVE(flags) 	((flags & 0x4) == 0x4)
+
+/** Indicates whether the data “rolls over” when reaching either the extreme
+ * high or low value. For example, a dial that can spin freely 360 degrees
+ * might output values from 0 to 10. If Wrap is indicated, the next value
+ * reported after passing the 10 position in the increasing direction would be
+ * 0.
+ */
+#define USB_HID_ITEM_FLAG_WRAP(flags)		((flags & 0x8) == 0x8)
+
+/**
+ * Indicates whether the raw data from the device has been processed in some
+ * way, and no longer represents a linear relationship between what is
+ * measured and the data that is reported.
+ */
+#define USB_HID_ITEM_FLAG_LINEAR(flags)		((flags & 0x10) == 0x10)
+
+/**
+ * Indicates whether the control has a preferred state to which it will return
+ * when the user is not physically interacting with the control. Push buttons
+ * (as opposed to toggle buttons) and self- centering joysticks are examples.
+ */
+#define USB_HID_ITEM_FLAG_PREFERRED(flags)	((flags & 0x20) == 0x20)
+
+/**
+ * Indicates whether the control has a state in which it is not sending
+ * meaningful data. One possible use of the null state is for controls that
+ * require the user to physically interact with the control in order for it to
+ * report useful data.
+ */
+#define USB_HID_ITEM_FLAG_POSITION(flags)	((flags & 0x40) == 0x40)
+
+/**
+ * Indicates whether the Feature or Output control's value should be changed
+ * by the host or not.  Volatile output can change with or without host
+ * interaction. To avoid synchronization problems, volatile controls should be
+ * relative whenever possible.
+ */
+#define USB_HID_ITEM_FLAG_VOLATILE(flags)	((flags & 0x80) == 0x80)
+
+/**
+ * Indicates that the control emits a fixed-size stream of bytes. The contents
+ * of the data field are determined by the application. The contents of the
+ * buffer are not interpreted as a single numeric quantity. Report data
+ * defined by a Buffered Bytes item must be aligned on an 8-bit boundary.
+ */
+#define USB_HID_ITEM_FLAG_BUFFERED(flags)	((flags & 0x100) == 0x100)
+
+/*---------------------------------------------------------------------------*/
+
+/* MAIN ITEMS */
+
+/**
+ * Main items are used to either define or group certain types of data fields
+ * within a Report descriptor.
+ */
+#define USB_HID_TAG_CLASS_MAIN			0x0
+
+/**
+ * An Input item describes information about the data provided by one or more
+ * physical controls. An application can use this information to interpret the
+ * data provided by the device. All data fields defined in a single item share
+ * an identical data format.
+ */
+#define USB_HID_REPORT_TAG_INPUT		0x8
+
+/**
+ * The Output item is used to define an output data field in a report. This
+ * item is similar to an Input item except it describes data sent to the
+ * device—for example, LED states.
+ */
+#define USB_HID_REPORT_TAG_OUTPUT		0x9
+
+/**
+ * Feature items describe device configuration information that can be sent to
+ * the device.
+ */
+#define USB_HID_REPORT_TAG_FEATURE		0xB
+
+/**
+ * A Collection item identifies a relationship between two or more data
+ * (Input, Output, or Feature.) 
+ */
+#define USB_HID_REPORT_TAG_COLLECTION		0xA
+
+/**
+ * While the Collection item opens a collection of data, the End Collection
+ * item closes a collection.
+ */
+#define USB_HID_REPORT_TAG_END_COLLECTION	0xC
+
+/*---------------------------------------------------------------------------*/
+
+/* GLOBAL ITEMS */
+
+/**
+ * Global items describe rather than define data from a control.
+ */
+#define USB_HID_TAG_CLASS_GLOBAL		0x1
+
+/**
+ * Unsigned integer specifying the current Usage Page. Since a usage are 32
+ * bit values, Usage Page items can be used to conserve space in a report
+ * descriptor by setting the high order 16 bits of a subsequent usages. Any
+ * usage that follows which is defines 16 bits or less is interpreted as a
+ * Usage ID and concatenated with the Usage Page to form a 32 bit Usage.
+ */
+#define USB_HID_REPORT_TAG_USAGE_PAGE		0x0
+
+/** 
+ * Extent value in logical units. This is the minimum value that a variable
+ * or array item will report. For example, a mouse reporting x position values
+ * from 0 to 128 would have a Logical Minimum of 0 and a Logical Maximum of
+ * 128.
+ */
+#define USB_HID_REPORT_TAG_LOGICAL_MINIMUM	0x1
+
+/** 
+ * Extent value in logical units. This is the maximum value that a variable
+ * or array item will report.
+ */
+#define USB_HID_REPORT_TAG_LOGICAL_MAXIMUM	0x2
+
+/** 
+ * Minimum value for the physical extent of a variable item. This represents
+ * the Logical Minimum with units applied to it.
+ */
+#define USB_HID_REPORT_TAG_PHYSICAL_MINIMUM 	0x3
+
+/** 
+ * Maximum value for the physical extent of a variable item.
+ */
+#define USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM 	0x4
+
+/** 
+ * Value of the unit exponent in base 10. See the table later in this section
+ * for more information.
+ */
+#define USB_HID_REPORT_TAG_UNIT_EXPONENT	0x5
+
+/** 
+ * Unit values.
+ */
+#define USB_HID_REPORT_TAG_UNIT			0x6
+
+/** 
+ * Unsigned integer specifying the size of the report fields in bits. This
+ * allows the parser to build an item map for the report handler to use.
+ */
+#define USB_HID_REPORT_TAG_REPORT_SIZE		0x7
+
+/** 
+ * Unsigned value that specifies the Report ID. If a Report ID tag is used
+ * anywhere in Report descriptor, all data reports for the device are preceded
+ * by a single byte ID field. All items succeeding the first Report ID tag but
+ * preceding a second Report ID tag are included in a report prefixed by a
+ * 1-byte ID. All items succeeding the second but preceding a third Report ID
+ * tag are included in a second report prefixed by a second ID, and so on.
+ */
+#define USB_HID_REPORT_TAG_REPORT_ID		0x8
+
+/** 
+ * Unsigned integer specifying the number of data fields for the item;
+ * determines how many fields are included in the report for this particular
+ * item (and consequently how many bits are added to the report).
+ */
+#define USB_HID_REPORT_TAG_REPORT_COUNT		0x9
+
+/** 
+ * Places a copy of the global item state table on the stack.
+ */
+#define USB_HID_REPORT_TAG_PUSH			0xA
+
+/** 
+ * Replaces the item state table with the top structure from the stack.
+ */
+#define USB_HID_REPORT_TAG_POP			0xB
+
+/*---------------------------------------------------------------------------*/
+
+/* LOCAL ITEMS */
+
+/**
+ * Local item tags define characteristics of controls. These items do not
+ * carry over to the next Main item. If a Main item defines more than one
+ * control, it may be preceded by several similar Local item tags. For
+ * example, an Input item may have several Usage tags associated with it, one
+ * for each control.
+ */
+#define USB_HID_TAG_CLASS_LOCAL			0x2
+
+/**
+ * Usage index for an item usage; represents a suggested usage for the item or
+ * collection. In the case where an item represents multiple controls, a Usage
+ * tag may suggest a usage for every variable or element in an array.
+ */
+#define USB_HID_REPORT_TAG_USAGE		0x0
+
+/**
+ * Defines the starting usage associated with an array or bitmap.
+ */
+#define USB_HID_REPORT_TAG_USAGE_MINIMUM	0x1
+
+/**
+ * Defines the ending usage associated with an array or bitmap.
+ */
+#define USB_HID_REPORT_TAG_USAGE_MAXIMUM	0x2
+
+/**
+ * Determines the body part used for a control. Index points to a designator
+ * in the Physical descriptor.
+ */
+#define USB_HID_REPORT_TAG_DESIGNATOR_INDEX	0x3
+
+/**
+ * Defines the index of the starting designator associated with an array or
+ * bitmap.
+ */
+#define USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM	0x4
+
+/**
+ * Defines the index of the ending designator associated with an array or
+ * bitmap.
+ */
+#define USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM	0x5
+
+/**
+ * String index for a String descriptor; allows a string to be associated with
+ * a particular item or control.
+ */
+#define USB_HID_REPORT_TAG_STRING_INDEX		0x7
+
+/**
+ * Specifies the first string index when assigning a group of sequential
+ * strings to controls in an array or bitmap.
+ */
+#define USB_HID_REPORT_TAG_STRING_MINIMUM	0x8
+
+/**
+ * Specifies the last string index when assigning a group of sequential
+ * strings to controls in an array or bitmap.
+ */
+#define USB_HID_REPORT_TAG_STRING_MAXIMUM	0x9
+
+/**
+ * Defines the beginning or end of a set of local items (1 = open set, 0 =
+ * close set).
+ *
+ * Usages other than the first (most preferred) usage defined are not
+ * accessible by system software.
+ */
+#define USB_HID_REPORT_TAG_DELIMITER		0xA
+
+/*---------------------------------------------------------------------------*/
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/hiddescriptor.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hiddescriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/hiddescriptor.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Matej Klonfar
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB HID report descriptor and report data parser
+ */
+#ifndef LIBUSB_HIDDESCRIPTOR_H_
+#define LIBUSB_HIDDESCRIPTOR_H_
+
+#include <stdint.h>
+#include <adt/list.h>
+#include <usb/hid/hid_report_items.h>
+#include <usb/hid/hidpath.h>
+#include <usb/hid/hidtypes.h>
+
+int usb_hid_parse_report_descriptor(usb_hid_report_t *report, 
+		const uint8_t *data, size_t size);
+
+void usb_hid_free_report(usb_hid_report_t *report);
+
+void usb_hid_descriptor_print(usb_hid_report_t *report);
+
+int usb_hid_report_init(usb_hid_report_t *report);
+
+int usb_hid_report_append_fields(usb_hid_report_t *report,
+		usb_hid_report_item_t *report_item);
+
+usb_hid_report_description_t * usb_hid_report_find_description(
+		const usb_hid_report_t *report, uint8_t report_id,
+		usb_hid_report_type_t type);
+
+int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data,
+		size_t item_size, usb_hid_report_item_t *report_item,
+		usb_hid_report_path_t *usage_path);
+
+int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, 
+		size_t item_size, usb_hid_report_item_t *report_item,
+		usb_hid_report_path_t *usage_path);
+
+int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, 
+		size_t item_size, usb_hid_report_item_t *report_item,
+		usb_hid_report_path_t *usage_path);
+
+int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, 
+		size_t item_size, usb_hid_report_item_t *report_item,
+		usb_hid_report_path_t *usage_path);
+
+void usb_hid_descriptor_print_list(list_t *list);
+
+void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item);
+
+void usb_hid_free_report_list(list_t *list);
+
+usb_hid_report_item_t *usb_hid_report_item_clone(
+		const usb_hid_report_item_t *item);
+
+uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
+
+usb_hid_report_path_t *usb_hid_report_path_try_insert(usb_hid_report_t*report,
+		usb_hid_report_path_t *cmp_path);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/hidparser.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidparser.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/hidparser.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011 Matej Klonfar
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * USB HID report descriptor and report data parser
+ */
+#ifndef LIBUSBHID_HIDPARSER_H_
+#define LIBUSBHID_HIDPARSER_H_
+
+#include <stdint.h>
+#include <adt/list.h>
+#include <usb/hid/hid_report_items.h>
+#include <usb/hid/hidpath.h>
+#include <usb/hid/hidtypes.h>
+#include <usb/hid/hiddescriptor.h>
+
+
+/*
+ * Input report parser functions
+ */
+int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data,
+		size_t size, uint8_t *report_id);
+
+/*
+ * Output report parser functions
+ */
+uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 
+		uint8_t report_id);
+
+void usb_hid_report_output_free(uint8_t *output);
+
+size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id,
+		usb_hid_report_type_t type);
+
+size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id,
+		usb_hid_report_type_t type);
+
+
+int usb_hid_report_output_translate(usb_hid_report_t *report, 
+		uint8_t report_id, uint8_t *buffer, size_t size);
+
+
+/*
+ * Report descriptor structure observing functions
+ */
+usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
+		usb_hid_report_field_t *field, usb_hid_report_path_t *path,
+		int flags, usb_hid_report_type_t type);
+
+uint8_t usb_hid_get_next_report_id(usb_hid_report_t *report, 
+		uint8_t report_id, usb_hid_report_type_t type);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/hidpath.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidpath.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/hidpath.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2011 Matej Klonfar
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB HID report descriptor and report data parser
+ */
+#ifndef LIBUSB_HIDPATH_H_
+#define LIBUSB_HIDPATH_H_
+
+#include <usb/hid/hidparser.h>
+#include <stdint.h>
+#include <adt/list.h>
+
+
+/*---------------------------------------------------------------------------*/
+/*
+ * Flags of usage paths comparison modes.
+ *
+ */
+/** Wanted usage path must be exactly the same as the searched one.  This
+ * option cannot be combined with the others. 
+ */
+#define USB_HID_PATH_COMPARE_STRICT		0
+
+/**
+ * Wanted usage path must be the suffix in the searched one.
+ */
+#define USB_HID_PATH_COMPARE_END		1
+
+/** 
+ * Only usage page are compared along the usage path.  This option can be
+ * combined with others. 
+ */
+#define USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY	2
+
+/** 
+ * Searched usage page must be prefix of the other one.
+ */
+#define USB_HID_PATH_COMPARE_BEGIN		4
+
+/** 
+ * Searched couple of usage page and usage can be anywhere in usage path.
+ * This option is deprecated.
+ */
+#define USB_HID_PATH_COMPARE_ANYWHERE		8
+
+/*----------------------------------------------------------------------------*/
+/** 
+ * Item of usage path structure. Last item of linked list describes one item
+ * in report, the others describe superior Collection tags. Usage and Usage
+ * page of report item can be changed due to data in report. 
+ */
+typedef struct {
+	/** Usage page of report item. Zero when usage page can be changed. */
+	uint32_t usage_page;
+	/** Usage of report item. Zero when usage can be changed. */	
+	uint32_t usage;
+
+	/** Attribute of Collection tag in report descriptor*/
+	uint8_t flags;
+
+	/** Link to usb_hid_report_path_t.items list */
+	link_t rpath_items_link;
+} usb_hid_report_usage_path_t;
+
+
+/*---------------------------------------------------------------------------*/
+/** 
+ * USB HID usage path structure.
+ * */
+typedef struct {
+	/** Length of usage path */
+	int depth;
+
+	/** Report id. Zero is reserved and means that report id is not used.
+	 * */
+	uint8_t report_id;
+
+	/** Link to usb_hid_report_path_t.collection_paths list. */
+	link_t cpath_link;
+
+	/** List of usage path items. */
+	list_t items;	/* of usb_hid_report_usage_path_t */
+} usb_hid_report_path_t;
+
+/*---------------------------------------------------------------------------*/
+usb_hid_report_path_t *usb_hid_report_path(void);
+
+void usb_hid_report_path_free(usb_hid_report_path_t *path);
+
+int usb_hid_report_path_set_report_id(usb_hid_report_path_t *usage_path,
+		uint8_t report_id);
+
+int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, 
+		int32_t usage_page, int32_t usage);
+
+void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path);
+
+void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path);
+
+void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, 
+		int32_t tag, int32_t data);
+
+int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path,
+		usb_hid_report_path_t *path, int flags);
+
+usb_hid_report_path_t *usb_hid_report_path_clone(
+		usb_hid_report_path_t *usage_path);
+
+void usb_hid_print_usage_path(usb_hid_report_path_t *path);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/hidreport.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidreport.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/hidreport.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * USB HID report parser initialization from descriptors.
+ */
+
+#ifndef LIBUSBHID_HIDREPORT_H_
+#define LIBUSBHID_HIDREPORT_H_
+
+#include <usb/dev/driver.h>
+#include <usb/hid/hidparser.h>
+
+/**
+ * Retrieves the Report descriptor from the USB device and initializes the
+ * report parser.
+ *
+ * \param[in] dev USB device representing a HID device.
+ * \param[in/out] parser HID Report parser.
+ * \param[out] report_desc Place to save report descriptor into.
+ * \param[out] report_size
+ *
+ * \retval EOK if successful.
+ * \retval EINVAL if one of the parameters is not given (is NULL).
+ * \retval ENOENT if there are some descriptors missing.
+ * \retval ENOMEM if an error with allocation occured.
+ * \retval EINVAL if the Report descriptor's size does not match the size 
+ *         from the interface descriptor.
+ * \return Other value inherited from function usb_pipe_start_session(),
+ *         usb_pipe_end_session() or usb_request_get_descriptor().
+ */
+int usb_hid_process_report_descriptor(usb_device_t *dev, 
+    usb_hid_report_t *report, uint8_t **report_desc, size_t *report_size);
+
+#endif /* LIBUSB_HIDREPORT_H_ */
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/hidtypes.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/hidtypes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/hidtypes.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2011 Matej Klonfar
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Basic data structures for USB HID Report descriptor and report parser.
+ */
+#ifndef LIBUSB_HIDTYPES_H_
+#define LIBUSB_HIDTYPES_H_
+
+#include <stdint.h>
+#include <adt/list.h>
+
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Maximum amount of specified usages for one report item
+ */
+#define USB_HID_MAX_USAGES	0xffff
+
+/**
+ * Converts integer from unsigned two's complement format format to signed
+ * one.
+ *
+ * @param x Number to convert
+ * @param size Length of the unsigned number in bites
+ * @return signed int
+ */
+#define USB_HID_UINT32_TO_INT32(x, size)	\
+	((((x) & (1 << ((size) - 1))) != 0) ?   \
+	 -(~((x) - 1) & ((1 << size) - 1)) : (x))
+
+/**
+ * Convert integer from signed format to unsigned. If number is negative the
+ * two's complement format is used.
+ *
+ * @param x Number to convert
+ * @param size Length of result number in bites
+ * @return unsigned int
+ */
+#define USB_HID_INT32_TO_UINT32(x, size)	\
+	(((x) < 0 ) ? ((1 << (size)) + (x)) : (x))
+
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Enum of report types
+ */
+typedef enum {
+	/** Input report. Data are sent from device to system */
+	USB_HID_REPORT_TYPE_INPUT = 1,
+
+	/** Output report. Data are sent from system to device */
+	USB_HID_REPORT_TYPE_OUTPUT = 2,
+
+	/** Feature report. Describes device configuration information that
+	 * can be sent to the device */
+	USB_HID_REPORT_TYPE_FEATURE = 3
+} usb_hid_report_type_t;
+
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Description of all reports described in one report descriptor.
+ */
+typedef struct {
+	/** Count of available reports. */
+	int report_count;
+
+	/** List of description of reports. */
+	list_t reports; /* of usb_hid_report_description_t */
+
+	/** List of all used usage/collection paths. */
+	list_t collection_paths;
+
+	/** Length of list of usage paths. */
+	int collection_paths_count;
+
+	/** Flag whether report ids are used. */
+	int use_report_ids;
+
+	/** Report id of last parsed report. */
+	uint8_t last_report_id;
+	
+} usb_hid_report_t;
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Description of one concrete report
+ */
+typedef struct {
+	/** Report id. Zero when no report id is used. */
+	uint8_t report_id;
+
+	/** Type of report */
+	usb_hid_report_type_t type;
+
+	/** Bit length of the report */
+	size_t bit_length;
+
+	/** Number of items in report */
+	size_t item_length;
+	
+	/** List of report items in report */
+	list_t report_items;
+
+	/** Link to usb_hid_report_t.reports list. */
+	link_t reports_link;
+} usb_hid_report_description_t;
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Description of one field/item in report 
+ */
+typedef struct {
+	/** Bit offset of the field */
+	int offset;
+
+	/** Bit size of the field */
+	size_t size;
+
+	/** Usage page. Zero when usage page can be changed. */
+	uint16_t usage_page;
+
+	/** Usage. Zero when usage can be changed. */
+	uint16_t usage;
+
+	/** Item's attributes */
+	uint8_t item_flags;
+
+	/** Usage/Collection path of the field. */
+	usb_hid_report_path_t *collection_path;
+
+	/** 
+	 * The lowest valid logical value (value with the device operates)
+	 */
+	int32_t logical_minimum;
+
+	/**
+	 * The greatest valid logical value
+	 */
+	int32_t logical_maximum;
+
+	/**
+	 * The lowest valid physical value (value with the system operates)
+	 */
+	int32_t physical_minimum;
+
+	/** The greatest valid physical value */
+	int32_t physical_maximum;
+
+	/** The lowest valid usage index */
+	int32_t usage_minimum;
+
+	/** The greatest valid usage index */
+	int32_t usage_maximum;
+	
+	/** Unit of the value */
+	uint32_t unit;
+
+	/** Unit exponent */
+	uint32_t unit_exponent;
+
+	/** Array of possible usages */
+	uint32_t *usages;
+
+	/** Size of the array of usages */
+	size_t usages_count;
+
+	/** Parsed value */
+	int32_t value;
+
+	/** Link to usb_hid_report_description_t.report_items list */
+	link_t ritems_link;
+} usb_hid_report_field_t;
+
+/*---------------------------------------------------------------------------*/
+
+/**
+ * State table for report descriptor parsing
+ */
+typedef struct {
+	/** report id */	
+	int32_t id;
+	
+	/** Extended usage page */
+	uint16_t extended_usage_page;
+
+	/** Array of usages specified for this item */
+	uint32_t usages[USB_HID_MAX_USAGES];
+	
+	/** Length of usages array */
+	int usages_count;
+
+	/** Usage page*/
+	uint32_t usage_page;
+
+	/** Minimum valid usage index */	
+	int32_t usage_minimum;
+	
+	/** Maximum valid usage index */	
+	int32_t usage_maximum;
+	
+	/** Minimum valid logical value */	
+	int32_t logical_minimum;
+	
+	/** Maximum valid logical value */	
+	int32_t logical_maximum;
+
+	/** Length of the items in bits*/	
+	int32_t size;
+
+	/** COunt of items*/	
+	int32_t count;
+
+	/**  Bit offset of the item in report */	
+	size_t offset;
+
+	/** Unit exponent */	
+	int32_t unit_exponent;
+	/** Unit of the value */	
+	int32_t unit;
+
+	/** String index */
+	uint32_t string_index;
+
+	/** Minimum valid string index */	
+	uint32_t string_minimum;
+
+	/** Maximum valid string index */	
+	uint32_t string_maximum;
+
+	/** The designator index */	
+	uint32_t designator_index;
+
+	/** Minimum valid designator value*/	
+	uint32_t designator_minimum;
+
+	/** Maximum valid designator value*/	
+	uint32_t designator_maximum;
+
+	/** Minimal valid physical value*/	
+	int32_t physical_minimum;
+
+	/** Maximal valid physical value */	
+	int32_t physical_maximum;
+
+	/** Items attributes*/	
+	uint8_t item_flags;
+
+	/** Report type */
+	usb_hid_report_type_t type;
+
+	/** current collection path*/	
+	usb_hid_report_path_t *usage_path;
+
+	/** Unused*/	
+	link_t link;
+
+	int in_delimiter;
+} usb_hid_report_item_t;
+/*---------------------------------------------------------------------------*/
+/**
+ * Enum of the keyboard modifiers 
+ */
+typedef enum {
+	USB_HID_MOD_LCTRL = 0x01,
+	USB_HID_MOD_LSHIFT = 0x02,
+	USB_HID_MOD_LALT = 0x04,
+	USB_HID_MOD_LGUI = 0x08,
+	USB_HID_MOD_RCTRL = 0x10,
+	USB_HID_MOD_RSHIFT = 0x20,
+	USB_HID_MOD_RALT = 0x40,
+	USB_HID_MOD_RGUI = 0x80,
+	USB_HID_MOD_COUNT = 8
+} usb_hid_modifiers_t;
+
+static const usb_hid_modifiers_t 
+    usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
+	USB_HID_MOD_LCTRL,
+	USB_HID_MOD_LSHIFT,
+	USB_HID_MOD_LALT,
+	USB_HID_MOD_LGUI,
+	USB_HID_MOD_RCTRL,
+	USB_HID_MOD_RSHIFT,
+	USB_HID_MOD_RALT,
+	USB_HID_MOD_RGUI
+};
+/*---------------------------------------------------------------------------*/
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/iface.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/iface.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011 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 libusbhid
+ * @{
+ */
+/** @file
+ * Client functions for accessing USB HID interface.
+ */
+#ifndef LIBUSBHID_CLASSES_HID_IFACE_H_
+#define LIBUSBHID_CLASSES_HID_IFACE_H_
+
+#include <sys/types.h>
+#include <async.h>
+
+extern int usbhid_dev_get_event_length(async_sess_t *, size_t *);
+extern int usbhid_dev_get_event(async_sess_t *, uint8_t *, size_t, size_t *,
+    int *, unsigned int);
+extern int usbhid_dev_get_report_descriptor_length(async_sess_t *, size_t *);
+extern int usbhid_dev_get_report_descriptor(async_sess_t *, uint8_t *, size_t,
+    size_t *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/request.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/request.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/request.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * HID class-specific requests.
+ */
+
+#ifndef USB_KBD_HIDREQ_H_
+#define USB_KBD_HIDREQ_H_
+
+#include <stdint.h>
+
+#include <usb/hid/hid.h>
+#include <usb/dev/pipes.h>
+
+/*----------------------------------------------------------------------------*/
+
+int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size);
+
+int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t protocol);
+
+int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration);
+
+int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size, 
+    size_t *actual_size);
+
+int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t *protocol);
+
+int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration);
+
+/*----------------------------------------------------------------------------*/
+
+#endif /* USB_KBD_HIDREQ_H_ */
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/usages/consumer.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/usages/consumer.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/usages/consumer.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * USB multimedia key usage to string mapping.
+ */
+
+#ifndef LIBUSBHID_CONSUMER_H_
+#define LIBUSBHID_CONSUMER_H_
+
+const char *usbhid_multimedia_usage_to_str(int usage);
+
+#endif /* LIBUSBHID_CONSUMER_H_ */
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/usages/core.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/usages/core.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/usages/core.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,77 @@
+/*
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * @brief USB HID Usage Tables.
+ */
+#ifndef LIBUSBHID_HIDUT_H_
+#define LIBUSBHID_HIDUT_H_
+
+/** USB/HID Usage Pages. */
+typedef enum {
+	USB_HIDUT_PAGE_GENERIC_DESKTOP = 1,
+	USB_HIDUT_PAGE_SIMULATION = 2,
+	USB_HIDUT_PAGE_VR = 3,
+	USB_HIDUT_PAGE_SPORT = 4,
+	USB_HIDUT_PAGE_GAME = 5,
+	USB_HIDUT_PAGE_GENERIC_DEVICE = 6,
+	USB_HIDUT_PAGE_KEYBOARD = 7,
+	USB_HIDUT_PAGE_LED = 8,
+	USB_HIDUT_PAGE_BUTTON = 9,
+	USB_HIDUT_PAGE_ORDINAL = 0x0a,
+	USB_HIDUT_PAGE_TELEPHONY_DEVICE = 0x0b,
+	USB_HIDUT_PAGE_CONSUMER = 0x0c
+} usb_hidut_usage_page_t;
+
+/** Usages for Generic Desktop Page. */
+typedef enum {
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_POINTER = 1,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_MOUSE = 2,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_JOYSTICK = 4,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_GAMEPAD = 5,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD = 6,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYPAD = 7,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_X = 0x30,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_Y = 0x31,
+	USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL = 0x38
+	/* USB_HIDUT_USAGE_GENERIC_DESKTOP_ = , */
+	
+} usb_hidut_usage_generic_desktop_t;
+
+typedef enum {
+	USB_HIDUT_USAGE_CONSUMER_CONSUMER_CONTROL = 1
+} usb_hidut_usage_consumer_t;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/include/usb/hid/usages/kbdgen.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/usages/kbdgen.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/usages/kbdgen.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,175 @@
+/*
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * @brief USB HID key codes.
+ * @details
+ * This is not a typical header as by default it is equal to empty file.
+ * However, by cleverly defining the USB_HIDUT_KBD_KEY you can use it
+ * to generate conversion tables etc.
+ *
+ * For example, this creates enum for known keys:
+ * @code
+#define USB_HIDUT_KBD_KEY(name, usage_id, l, lc, l1, l2) \
+	USB_KBD_KEY_##name = usage_id,
+typedef enum {
+	#include <usb/hidutkbd.h>
+} usb_key_code_t;
+ @endcode
+ *
+ * Maybe, it might be better that you would place such enums into separate
+ * files and create them as separate step before compiling to allow tools
+ * such as Doxygen get the definitions right.
+ *
+ * @warning This file does not include guard to prevent multiple inclusions
+ * into a single file.
+ */
+
+
+#ifndef USB_HIDUT_KBD_KEY
+/** Declare keyboard key.
+ * @param name Key name (identifier).
+ * @param usage_id Key code (see Keyboard/Keypad Page (0x07) in HUT1.12.
+ * @param letter Corresponding character (0 if not applicable).
+ * @param letter_caps Corresponding character with Caps on.
+ * @param letter_mod1 Corresponding character with modifier #1 on.
+ * @param letter_mod2 Corresponding character with modifier #2 on.
+ */
+#define USB_HIDUT_KBD_KEY(name, usage_id, letter, letter_caps, letter_mod1, letter_mod2)
+
+#endif
+
+#define __NONPRINT(name, usage_id) \
+	USB_HIDUT_KBD_KEY(name, usage_id, 0, 0, 0, 0)
+
+/* US alphabet letters */
+USB_HIDUT_KBD_KEY(A, 0x04, 'a', 'A', 0, 0)
+USB_HIDUT_KBD_KEY(B, 0x05, 'b', 'B', 0, 0)
+USB_HIDUT_KBD_KEY(C, 0x06, 'c', 'C', 0, 0)
+USB_HIDUT_KBD_KEY(D, 0x07, 'd', 'D', 0, 0)
+USB_HIDUT_KBD_KEY(E, 0x08, 'e', 'E', 0, 0)
+USB_HIDUT_KBD_KEY(F, 0x09, 'f', 'F', 0, 0)
+USB_HIDUT_KBD_KEY(G, 0x0A, 'g', 'G', 0, 0)
+USB_HIDUT_KBD_KEY(H, 0x0B, 'h', 'H', 0, 0)
+USB_HIDUT_KBD_KEY(I, 0x0C, 'i', 'I', 0, 0)
+USB_HIDUT_KBD_KEY(J, 0x0D, 'j', 'J', 0, 0)
+USB_HIDUT_KBD_KEY(K, 0x0E, 'k', 'K', 0, 0)
+USB_HIDUT_KBD_KEY(L, 0x0F, 'l', 'L', 0, 0)
+USB_HIDUT_KBD_KEY(M, 0x10, 'm', 'M', 0, 0)
+USB_HIDUT_KBD_KEY(N, 0x11, 'n', 'N', 0, 0)
+USB_HIDUT_KBD_KEY(O, 0x12, 'o', 'O', 0, 0)
+USB_HIDUT_KBD_KEY(P, 0x13, 'p', 'P', 0, 0)
+USB_HIDUT_KBD_KEY(Q, 0x14, 'q', 'Q', 0, 0)
+USB_HIDUT_KBD_KEY(R, 0x15, 'r', 'R', 0, 0)
+USB_HIDUT_KBD_KEY(S, 0x16, 's', 'S', 0, 0)
+USB_HIDUT_KBD_KEY(T, 0x17, 't', 'T', 0, 0)
+USB_HIDUT_KBD_KEY(U, 0x18, 'u', 'U', 0, 0)
+USB_HIDUT_KBD_KEY(V, 0x19, 'v', 'V', 0, 0)
+USB_HIDUT_KBD_KEY(W, 0x1A, 'w', 'W', 0, 0)
+USB_HIDUT_KBD_KEY(X, 0x1B, 'x', 'X', 0, 0)
+USB_HIDUT_KBD_KEY(Y, 0x1C, 'y', 'Y', 0, 0)
+USB_HIDUT_KBD_KEY(Z, 0x1D, 'z', 'Z', 0, 0)
+
+/* Keyboard digits */
+USB_HIDUT_KBD_KEY(1, 0x1E, '1', '!', 0, 0)
+USB_HIDUT_KBD_KEY(2, 0x1F, '2', '@', 0, 0)
+USB_HIDUT_KBD_KEY(3, 0x20, '3', '#', 0, 0)
+USB_HIDUT_KBD_KEY(4, 0x21, '4', '$', 0, 0)
+USB_HIDUT_KBD_KEY(5, 0x22, '5', '%', 0, 0)
+USB_HIDUT_KBD_KEY(6, 0x23, '6', '^', 0, 0)
+USB_HIDUT_KBD_KEY(7, 0x24, '7', '&', 0, 0)
+USB_HIDUT_KBD_KEY(8, 0x25, '8', '*', 0, 0)
+USB_HIDUT_KBD_KEY(9, 0x26, '9', '(', 0, 0)
+USB_HIDUT_KBD_KEY(0, 0x27, '0', ')', 0, 0)
+
+/* More-or-less typewriter command keys */
+USB_HIDUT_KBD_KEY(ENTER, 0x28, '\n', 0, 0, 0)
+USB_HIDUT_KBD_KEY(ESCAPE, 0x29, 0, 0, 0, 0)
+USB_HIDUT_KBD_KEY(BACKSPACE, 0x2A, '\b', 0, 0, 0)
+USB_HIDUT_KBD_KEY(TAB, 0x2B, '\t', 0, 0, 0)
+USB_HIDUT_KBD_KEY(SPACE, 0x2C, ' ', 0, 0, 0)
+
+/* Special (printable) characters */
+USB_HIDUT_KBD_KEY(DASH, 0x2D, '-', '_', 0, 0)
+USB_HIDUT_KBD_KEY(EQUALS, 0x2E, '=', '+', 0, 0)
+USB_HIDUT_KBD_KEY(LEFT_BRACKET, 0x2F, '[', '{', 0, 0)
+USB_HIDUT_KBD_KEY(RIGHT_BRACKET, 0x30, ']', '}', 0, 0)
+USB_HIDUT_KBD_KEY(BACKSLASH, 0x31, '\\', '|', 0, 0)
+USB_HIDUT_KBD_KEY(HASH, 0x32, '#', '~', 0, 0)
+USB_HIDUT_KBD_KEY(SEMICOLON, 0x33, ';', ':', 0, 0)
+USB_HIDUT_KBD_KEY(APOSTROPHE, 0x34, '\'', '"', 0, 0)
+USB_HIDUT_KBD_KEY(GRAVE_ACCENT, 0x35, '`', '~', 0, 0)
+USB_HIDUT_KBD_KEY(COMMA, 0x36, ',', '<', 0, 0)
+USB_HIDUT_KBD_KEY(PERIOD, 0x37, '.', '>', 0, 0)
+USB_HIDUT_KBD_KEY(SLASH, 0x38, '/', '?', 0, 0)
+
+USB_HIDUT_KBD_KEY(CAPS_LOCK, 0x39, 0, 0, 0, 0)
+
+/* Function keys */
+__NONPRINT( F1, 0x3A)
+__NONPRINT( F2, 0x3B)
+__NONPRINT( F3, 0x3C)
+__NONPRINT( F4, 0x3D)
+__NONPRINT( F5, 0x3E)
+__NONPRINT( F6, 0x3F)
+__NONPRINT( F7, 0x40)
+__NONPRINT( F8, 0x41)
+__NONPRINT( F9, 0x42)
+__NONPRINT(F10, 0x43)
+__NONPRINT(F11, 0x44)
+__NONPRINT(F12, 0x45)
+
+/* Cursor movement keys & co. */
+__NONPRINT(PRINT_SCREEN, 0x46)
+__NONPRINT(SCROLL_LOCK, 0x47)
+__NONPRINT(PAUSE, 0x48)
+__NONPRINT(INSERT, 0x49)
+__NONPRINT(HOME, 0x4A)
+__NONPRINT(PAGE_UP, 0x4B)
+__NONPRINT(DELETE, 0x4C)
+__NONPRINT(END, 0x4D)
+__NONPRINT(PAGE_DOWN, 0x4E)
+__NONPRINT(RIGHT_ARROW, 0x4F)
+__NONPRINT(LEFT_ARROW, 0x50)
+__NONPRINT(DOWN_ARROW, 0x51)
+__NONPRINT(UP_ARROW, 0x52)
+
+
+
+
+/* USB_HIDUT_KBD_KEY(, 0x, '', '', 0, 0) */
+
+#undef __NONPRINT
+
+/**
+ * @}
+ */
+
Index: uspace/lib/usbhid/include/usb/hid/usages/led.h
===================================================================
--- uspace/lib/usbhid/include/usb/hid/usages/led.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/include/usb/hid/usages/led.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2010 Lubos Slovak
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * @brief USB HID Usage Tables - LED page.
+ */
+#ifndef LIBUSBHID_UTLED_H_
+#define LIBUSBHID_UTLED_H_
+
+typedef enum {
+	USB_HID_LED_UNDEFINED = 0,
+	USB_HID_LED_NUM_LOCK,
+	USB_HID_LED_CAPS_LOCK,
+	USB_HID_LED_SCROLL_LOCK,
+	USB_HID_LED_COMPOSE,
+	USB_HID_LED_KANA,
+	USB_HID_LED_POWER,
+	USB_HID_LED_SHIFT,
+	USB_HID_LED_DND,
+	USB_HID_LED_MUTE,
+	USB_HID_LED_TONE_ENABLE,
+	USB_HID_LED_HIGH_CUT_FILTER,
+	USB_HID_LED_LOW_CUT_FILTER,
+	USB_HID_LED_EQ_ENABLE,
+	USB_HID_LED_SOUND_FIELD_ON,
+	USB_HID_LED_SURROUND_ON,
+	USB_HID_LED_REPEAT,
+	USB_HID_LED_STEREO,
+	USB_HID_LED_SAMPLING_RATE_DETECT,
+	USB_HID_LED_SPINNING,
+	USB_HID_LED_CAV,
+	USB_HID_LED_CLV,
+	USB_HID_LED_RECORDING_FORMAT_DETECT,
+	USB_HID_LED_OFF_HOOK,
+	USB_HID_LED_RING,
+	USB_HID_LED_MESSAGE_WAITING,
+	USB_HID_LED_DATA_MODE,
+	USB_HID_LED_BATTERY_OPERATION,
+	USB_HID_LED_BATTERY_OK,
+	USB_HID_LED_BATTERY_LOW,
+	USB_HID_LED_SPEAKER,
+	USB_HID_LED_HEAD_SET,
+	USB_HID_LED_HOLD,
+	USB_HID_LED_MICRO,
+	USB_HID_LED_COVERAGE,
+	USB_HID_LED_NIGHT_MODE,
+	USB_HID_LED_SEND_CALLS,
+	USB_HID_LED_CALL_PICKUP,
+	USB_HID_LED_CONFERENCE,
+	USB_HID_LED_STAND_BY,
+	USB_HID_LED_CAMERA_ON,
+	USB_HID_LED_CAMERA_OFF,
+	USB_HID_LED_ON_LINE,
+	USB_HID_LED_OFF_LINE,
+	USB_HID_LED_BUSY,
+	USB_HID_LED_READY,
+	USB_HID_LED_PAPER_OUT,
+	USB_HID_LED_PAPER_JAM,
+	USB_HID_LED_REMOTE,
+	USB_HID_LED_FORWARD,
+	USB_HID_LED_REVERSE,
+	USB_HID_LED_STOP,
+	USB_HID_LED_REWIND,
+	USB_HID_LED_FAST_FORWARD,
+	USB_HID_LED_PLAY,
+	USB_HID_LED_PAUSE,
+	USB_HID_LED_RECORD,
+	USB_HID_LED_ERROR,
+	USB_HID_LED_USAGE_SELECTED_IND,
+	USB_HID_LED_USAGE_IN_USE_IND,
+	USB_HID_LED_USAGE_MULTI_MODE_IND,
+	USB_HID_LED_IND_ON,
+	USB_HID_LED_IND_FLASH,
+	USB_HID_LED_IND_SLOW_BLINK,
+	USB_HID_LED_IND_FAST_BLINK,
+	USB_HID_LED_IND_OFF,
+	USB_HID_LED_FLASH_ON_TIME,
+	USB_HID_LED_SLOW_BLINK_ON_TIME,
+	USB_HID_LED_SLOW_BLINK_OFF_TIME,
+	USB_HID_LED_FAST_BLINK_ON_TIME,
+	USB_HID_LED_FAST_BLINK_OFF_TIME,
+	USB_HID_LED_USAGE_IND_COLOR,
+	USB_HID_LED_IND_RED,
+	USB_HID_LED_IND_GREEN,
+	USB_HID_LED_IND_AMBER,
+	USB_HID_LED_GENERIC_IND,
+	USB_HID_LED_SYSTEM_SUSPEND,
+	USB_HID_LED_EXTERNAL_POWER
+} usb_hid_usage_led_t;
+
+#endif /* LIBUSB_UTLED_H_ */
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/consumer.c
===================================================================
--- uspace/lib/usbhid/src/consumer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/src/consumer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,732 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * UUSB multimedia key usage, to string mapping.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <usb/hid/usages/consumer.h>
+
+static const char *usbhid_consumer_usage_str[0x29d] = {
+	[0x01] = "Consumer Control",
+	[0x02] = "Numeric Key Pad",
+	[0x03] = "Programmable Buttons",
+	[0x04] = "Microphone",
+	[0x05] = "Headphone",
+	[0x06] = "Graphic Equalizer",
+	[0x07] = "Reserved",
+	[0x08] = "Reserved",
+	[0x09] = "Reserved",
+	[0x0a] = "Reserved",
+	[0x0b] = "Reserved",
+	[0x0c] = "Reserved",
+	[0x0d] = "Reserved",
+	[0x0e] = "Reserved",
+	[0x0f] = "Reserved",
+	[0x10] = "Reserved",
+	[0x11] = "Reserved",
+	[0x12] = "Reserved",
+	[0x13] = "Reserved",
+	[0x14] = "Reserved",
+	[0x15] = "Reserved",
+	[0x16] = "Reserved",
+	[0x17] = "Reserved",
+	[0x18] = "Reserved",
+	[0x19] = "Reserved",
+	[0x1a] = "Reserved",
+	[0x1b] = "Reserved",
+	[0x1c] = "Reserved",
+	[0x1d] = "Reserved",
+	[0x1e] = "Reserved",
+	[0x1f] = "Reserved",
+	[0x20] = "+10",
+	[0x21] = "+100",
+	[0x22] = "AM/PM",
+	[0x23] = "Reserved",
+	[0x24] = "Reserved",
+	[0x25] = "Reserved",
+	[0x26] = "Reserved",
+	[0x27] = "Reserved",
+	[0x28] = "Reserved",
+	[0x29] = "Reserved",
+	[0x2a] = "Reserved",
+	[0x2b] = "Reserved",
+	[0x2c] = "Reserved",
+	[0x2d] = "Reserved",
+	[0x2e] = "Reserved",
+	[0x2f] = "Reserved",
+	[0x30] = "Reserved",
+	[0x31] = "Reserved",
+	[0x32] = "Reserved",
+	[0x33] = "Reserved",
+	[0x34] = "Reserved",
+	[0x35] = "Reserved",
+	[0x36] = "Reserved",
+	[0x37] = "Reserved",
+	[0x38] = "Reserved",
+	[0x39] = "Reserved",
+	[0x3a] = "Reserved",
+	[0x3b] = "Reserved",
+	[0x3c] = "Reserved",
+	[0x3d] = "Reserved",
+	[0x3e] = "Reserved",
+	[0x3f] = "Reserved",
+	[0x40] = "Menu",
+	[0x41] = "Menu Pick",
+	[0x42] = "Menu Up",
+	[0x43] = "Menu Down",
+	[0x44] = "Menu Left",
+	[0x45] = "Menu Right",
+	[0x46] = "Menu Escape",
+	[0x47] = "Menu Value Increase",
+	[0x48] = "Menu Value Decrease",
+	[0x49] = "Reserved",
+	[0x4a] = "Reserved",
+	[0x4b] = "Reserved",
+	[0x4c] = "Reserved",
+	[0x4d] = "Reserved",
+	[0x4e] = "Reserved",
+	[0x4f] = "Reserved",
+	[0x50] = "Reserved",
+	[0x51] = "Reserved",
+	[0x52] = "Reserved",
+	[0x53] = "Reserved",
+	[0x54] = "Reserved",
+	[0x55] = "Reserved",
+	[0x56] = "Reserved",
+	[0x57] = "Reserved",
+	[0x58] = "Reserved",
+	[0x59] = "Reserved",
+	[0x5a] = "Reserved",
+	[0x5b] = "Reserved",
+	[0x5c] = "Reserved",
+	[0x5d] = "Reserved",
+	[0x5e] = "Reserved",
+	[0x5f] = "Reserved",
+	[0x60] = "Data On Screen",
+	[0x61] = "Closed Caption",
+	[0x62] = "Closed Caption Select",
+	[0x63] = "VCR/TV",
+	[0x64] = "Broadcast Mode",
+	[0x65] = "Snapshot",
+	[0x66] = "Still",
+	[0x67] = "Reserved",
+	[0x68] = "Reserved",
+	[0x69] = "Reserved",
+	[0x6a] = "Reserved",
+	[0x6b] = "Reserved",
+	[0x6c] = "Reserved",
+	[0x6d] = "Reserved",
+	[0x6e] = "Reserved",
+	[0x6f] = "Reserved",
+	[0x70] = "Reserved",
+	[0x71] = "Reserved",
+	[0x72] = "Reserved",
+	[0x73] = "Reserved",
+	[0x74] = "Reserved",
+	[0x75] = "Reserved",
+	[0x76] = "Reserved",
+	[0x77] = "Reserved",
+	[0x78] = "Reserved",
+	[0x79] = "Reserved",
+	[0x7a] = "Reserved",
+	[0x7b] = "Reserved",
+	[0x7c] = "Reserved",
+	[0x7d] = "Reserved",
+	[0x7e] = "Reserved",
+	[0x7f] = "Reserved",
+	[0x80] = "Selection",
+	[0x81] = "Assign Selection",
+	[0x82] = "Mode Step",
+	[0x83] = "Recall Last",
+	[0x84] = "Enter Channel",
+	[0x85] = "Order Movie",
+	[0x86] = "Channel",
+	[0x87] = "Media Selection",
+	[0x88] = "Media Select Computer",
+	[0x89] = "Media Select TV",
+	[0x8a] = "Media Select WWW",
+	[0x8b] = "Media Select DVD",
+	[0x8c] = "Media Select Telephone",
+	[0x8d] = "Media Select Program Guide",
+	[0x8e] = "Media Select Video Phone",
+	[0x8f] = "Media Select Games",
+	[0x90] = "Media Select Messages",
+	[0x91] = "Media Select CD",
+	[0x92] = "Media Select VCR",
+	[0x93] = "Media Select Tuner",
+	[0x94] = "Quit",
+	[0x95] = "Help",
+	[0x96] = "Media Select Tape",
+	[0x97] = "Media Select Cable",
+	[0x98] = "Media Select Satellite",
+	[0x99] = "Media Select Security",
+	[0x9a] = "Media Select Home",
+	[0x9b] = "Media Select Call",
+	[0x9c] = "Channel Increment",
+	[0x9d] = "Channel Decrement",
+	[0x9e] = "Media Select SAP",
+	[0x9f] = "Reserved",
+	[0xa0] = "VCR Plus",
+	[0xa1] = "Once",
+	[0xa2] = "Daily",
+	[0xa3] = "Weekly",
+	[0xa4] = "Monthly",
+	[0xa5] = "Reserved",
+	[0xa6] = "Reserved",
+	[0xa7] = "Reserved",
+	[0xa8] = "Reserved",
+	[0xa9] = "Reserved",
+	[0xaa] = "Reserved",
+	[0xab] = "Reserved",
+	[0xac] = "Reserved",
+	[0xad] = "Reserved",
+	[0xae] = "Reserved",
+	[0xaf] = "Reserved",
+	[0xb0] = "Play",
+	[0xb1] = "Pause",
+	[0xb2] = "Record",
+	[0xb3] = "Fast Forward",
+	[0xb4] = "Rewind",
+	[0xb5] = "Scan Next Track",
+	[0xb6] = "Scan Previous Trac",
+	[0xb7] = "Stop",
+	[0xb8] = "Eject",
+	[0xb9] = "Random Play",
+	[0xba] = "Select Disc",
+	[0xbb] = "Enter Disc",
+	[0xbc] = "Repeat",
+	[0xbd] = "Tracking",
+	[0xbe] = "Track Normal",
+	[0xbf] = "Slow Tracking",
+	[0xc0] = "Frame Forward",
+	[0xc1] = "Frame Back",
+	[0xc2] = "Mark",
+	[0xc3] = "Clear Mark",
+	[0xc4] = "Repeat From Mark",
+	[0xc5] = "Return to Mark",
+	[0xc6] = "Search Mark Forward",
+	[0xc7] = "Search Mark Backwards",
+	[0xc8] = "Counter Reset",
+	[0xc9] = "Show Counter",
+	[0xca] = "Tracking Increment",
+	[0xcb] = "Tracking Decrement",
+	[0xcc] = "Stop/Eject",
+	[0xcd] = "Play/Pause",
+	[0xce] = "Play/Skip",
+	[0xcf] = "Reserved",
+	[0xd0] = "Reserved",
+	[0xd1] = "Reserved",
+	[0xd2] = "Reserved",
+	[0xd3] = "Reserved",
+	[0xd4] = "Reserved",
+	[0xd5] = "Reserved",
+	[0xd6] = "Reserved",
+	[0xd7] = "Reserved",
+	[0xd8] = "Reserved",
+	[0xd9] = "Reserved",
+	[0xda] = "Reserved",
+	[0xdb] = "Reserved",
+	[0xdc] = "Reserved",
+	[0xdd] = "Reserved",
+	[0xde] = "Reserved",
+	[0xdf] = "Reserved",
+	[0xe0] = "Volume",
+	[0xe1] = "Balance",
+	[0xe2] = "Mute",
+	[0xe3] = "Bass",
+	[0xe4] = "Treble",
+	[0xe5] = "Bass Boost",
+	[0xe6] = "Surround Mode",
+	[0xe7] = "Loudness",
+	[0xe8] = "MPX",
+	[0xe9] = "Volume Increment",
+	[0xea] = "Volume Decrement",
+	[0xeb] = "Reserved",
+	[0xec] = "Reserved",
+	[0xed] = "Reserved",
+	[0xee] = "Reserved",
+	[0xef] = "Reserved",
+	[0xf0] = "Speed Select",
+	[0xf1] = "Playback Speed",
+	[0xf2] = "Standard Play",
+	[0xf3] = "Long Play",
+	[0xf4] = "Extended Play",
+	[0xf5] = "Slow",
+	[0xf6] = "Reserved",
+	[0xf7] = "Reserved",
+	[0xf8] = "Reserved",
+	[0xf9] = "Reserved",
+	[0xfa] = "Reserved",
+	[0xfb] = "Reserved",
+	[0xfc] = "Reserved",
+	[0xfd] = "Reserved",
+	[0xfe] = "Reserved",
+	[0xff] = "Reserved",
+	[0x100] = "Fan Enable",
+	[0x101] = "Fan Speed",
+	[0x102] = "Light Enable",
+	[0x103] = "Light Illumination Level",
+	[0x104] = "Climate Control Enable",
+	[0x105] = "Room Temperature",
+	[0x106] = "Security Enable",
+	[0x107] = "Fire Alarm",
+	[0x108] = "Police Alarm",
+	[0x109] = "Proximity",
+	[0x10a] = "Motion",
+	[0x10b] = "Duress Alarm",
+	[0x10c] = "Holdup Alarm",
+	[0x10d] = "Medical Alarm",
+	[0x10e] = "Reserved",
+	[0x10f] = "Reserved",
+	[0x110] = "Reserved",
+	[0x111] = "Reserved",
+	[0x112] = "Reserved",
+	[0x113] = "Reserved",
+	[0x114] = "Reserved",
+	[0x115] = "Reserved",
+	[0x116] = "Reserved",
+	[0x117] = "Reserved",
+	[0x118] = "Reserved",
+	[0x119] = "Reserved",
+	[0x11a] = "Reserved",
+	[0x11b] = "Reserved",
+	[0x11c] = "Reserved",
+	[0x11d] = "Reserved",
+	[0x11e] = "Reserved",
+	[0x11f] = "Reserved",
+	[0x120] = "Reserved", 
+	[0x121] = "Reserved",
+	[0x122] = "Reserved",
+	[0x123] = "Reserved",
+	[0x124] = "Reserved",
+	[0x125] = "Reserved",
+	[0x126] = "Reserved",
+	[0x127] = "Reserved",
+	[0x128] = "Reserved",
+	[0x129] = "Reserved",
+	[0x12a] = "Reserved",
+	[0x12b] = "Reserved",
+	[0x12c] = "Reserved",
+	[0x12d] = "Reserved",
+	[0x12e] = "Reserved",
+	[0x12f] = "Reserved",
+	[0x130] = "Reserved", 
+	[0x131] = "Reserved",
+	[0x132] = "Reserved",
+	[0x133] = "Reserved",
+	[0x134] = "Reserved",
+	[0x135] = "Reserved",
+	[0x136] = "Reserved",
+	[0x137] = "Reserved",
+	[0x138] = "Reserved",
+	[0x139] = "Reserved",
+	[0x13a] = "Reserved",
+	[0x13b] = "Reserved",
+	[0x13c] = "Reserved",
+	[0x13d] = "Reserved",
+	[0x13e] = "Reserved",
+	[0x13f] = "Reserved",
+	[0x140] = "Reserved", 
+	[0x141] = "Reserved",
+	[0x142] = "Reserved",
+	[0x143] = "Reserved",
+	[0x144] = "Reserved",
+	[0x145] = "Reserved",
+	[0x146] = "Reserved",
+	[0x147] = "Reserved",
+	[0x148] = "Reserved",
+	[0x149] = "Reserved",
+	[0x14a] = "Reserved",
+	[0x14b] = "Reserved",
+	[0x14c] = "Reserved",
+	[0x14d] = "Reserved",
+	[0x14e] = "Reserved",
+	[0x14f] = "Reserved",
+	[0x150] = "Balance Right",
+	[0x151] = "Balance Left",
+	[0x152] = "Bass Increment",
+	[0x153] = "Bass Decrement",
+	[0x154] = "Treble Increment",
+	[0x155] = "Treble Decrement",
+	[0x156] = "Reserved",
+	[0x157] = "Reserved",
+	[0x158] = "Reserved",
+	[0x159] = "Reserved",
+	[0x15a] = "Reserved",
+	[0x15b] = "Reserved",
+	[0x15c] = "Reserved",
+	[0x15d] = "Reserved",
+	[0x15e] = "Reserved",
+	[0x15f] = "Reserved",
+	[0x160] = "Speaker System",
+	[0x161] = "Channel Left",
+	[0x162] = "Channel Right",
+	[0x163] = "Channel Center",
+	[0x164] = "Channel Front",
+	[0x165] = "Channel Center Front",
+	[0x166] = "Channel Side",
+	[0x167] = "Channel Surround",
+	[0x168] = "Channel Low Frequency Enhancement",
+	[0x169] = "Channel Top",
+	[0x16a] = "Channel Unknown",
+	[0x16b] = "Reserved",
+	[0x16c] = "Reserved",
+	[0x16d] = "Reserved",
+	[0x16e] = "Reserved",
+	[0x16f] = "Reserved",
+	[0x170] = "Sub-channel",
+	[0x171] = "Sub-channel Increment",
+	[0x172] = "Sub-channel Decrement",
+	[0x173] = "Alternate Audio Increment",
+	[0x174] = "Alternate Audio Decrement",
+	[0x175] = "Reserved",
+	[0x176] = "Reserved",
+	[0x177] = "Reserved",
+	[0x178] = "Reserved",
+	[0x179] = "Reserved",
+	[0x17a] = "Reserved",
+	[0x17b] = "Reserved",
+	[0x17c] = "Reserved",
+	[0x17d] = "Reserved",
+	[0x17e] = "Reserved",
+	[0x17f] = "Reserved",
+	[0x180] = "Application Launch Buttons",
+	[0x181] = "AL Launch Buttion Configuration Tool",
+	[0x182] = "AL Programmable Button Configuration",
+	[0x183] = "AL Consumer Control Configuration",
+	[0x184] = "AL Word Processor",
+	[0x185] = "AL Text Editor",
+	[0x186] = "AL Spreadsheet",
+	[0x187] = "AL Graphics Editor",
+	[0x188] = "AL Presentation App",
+	[0x189] = "AL Database App",
+	[0x18a] = "AL Email Reader",
+	[0x18b] = "AL Newsreader",
+	[0x18c] = "AL Voicemail",
+	[0x18d] = "AL Contacts/Address Book",
+	[0x18e] = "AL Calendar/Schedule",
+	[0x18f] = "AL Task/Project Manager",
+	[0x190] = "AL Log/Journal/Timecard",
+	[0x191] = "AL Checkbook/Finance",
+	[0x192] = "AL Calculator",
+	[0x193] = "AL A/V Capture/Playback",
+	[0x194] = "AL Local Machine Browser",
+	[0x195] = "AL LAN/WAN Browser",
+	[0x196] = "AL Internet Browser",
+	[0x197] = "AL Remote Networking/ISP Connect",
+	[0x198] = "AL Network Conference",
+	[0x199] = "AL Network Chat",
+	[0x19a] = "AL Telephony/Dialer",
+	[0x19b] = "AL Logon",
+	[0x19c] = "AL Logoff",
+	[0x19d] = "AL Logon/Logoff",
+	[0x19e] = "AL Terminal Lock/Screensaver",
+	[0x19f] = "AL Control Panel",
+	[0x1a0] = "AL Command Line Processor/Run",
+	[0x1a1] = "AL Process/Task Manager",
+	[0x1a2] = "AL Select Task/Application",
+	[0x1a3] = "AL Next Task/Application",
+	[0x1a4] = "AL Previous Task/Application",
+	[0x1a5] = "AL Preemptive Halt Task/Application",
+	[0x1a6] = "AL Integrated Help Center",
+	[0x1a7] = "AL Documents",
+	[0x1a8] = "AL Thesaurus",
+	[0x1a9] = "AL Dictionary",
+	[0x1aa] = "AL Desktop",
+	[0x1ab] = "AL Spell Check",
+	[0x1ac] = "AL Grammar Check",
+	[0x1ad] = "AL Wireless Status",
+	[0x1ae] = "AL Keyboard Layout",
+	[0x1af] = "AL Virus Protection",
+	[0x1b0] = "AL Encryption",
+	[0x1b1] = "AL Screen Saver",
+	[0x1b2] = "AL Alarms",
+	[0x1b3] = "AL Clock",
+	[0x1b4] = "AL File Browser",
+	[0x1b5] = "AL Power Status",
+	[0x1b6] = "AL Image Browser",
+	[0x1b7] = "AL Audio Browser",
+	[0x1b8] = "AL Movie Browser",
+	[0x1b9] = "AL Digital Rights Manager",
+	[0x1ba] = "AL Digital Wallet",
+	[0x1bb] = "Reserved",
+	[0x1bc] = "AL Instant Messaging",
+	[0x1bd] = "AL OEM Features Tips/Tutorial Browser",
+	[0x1be] = "AL OEM Help",
+	[0x1bf] = "AL Online Community",
+	[0x1c0] = "AL Entertainment Content Browser",
+	[0x1c1] = "AL Online Shopping Browser",
+	[0x1c2] = "AL SmartCard Information/Help",
+	[0x1c3] = "AL Market Monitor/Finance Browser",
+	[0x1c4] = "AL Customized Corporate News Browser",
+	[0x1c5] = "AL Online Activity Browser",
+	[0x1c6] = "AL Research/Search Browser",
+	[0x1c7] = "AL Audio Player",
+	[0x1c8] = "Reserved",
+	[0x1c9] = "Reserved",
+	[0x1ca] = "Reserved",
+	[0x1cb] = "Reserved",
+	[0x1cc] = "Reserved",
+	[0x1cd] = "Reserved",
+	[0x1ce] = "Reserved",
+	[0x1cf] = "Reserved",
+	[0x1d0] = "Reserved",
+	[0x1d1] = "Reserved",
+	[0x1d2] = "Reserved",
+	[0x1d3] = "Reserved",
+	[0x1d4] = "Reserved",
+	[0x1d5] = "Reserved",
+	[0x1d6] = "Reserved",
+	[0x1d7] = "Reserved",
+	[0x1d8] = "Reserved",
+	[0x1d9] = "Reserved",
+	[0x1da] = "Reserved",
+	[0x1db] = "Reserved",
+	[0x1dc] = "Reserved",
+	[0x1dd] = "Reserved",
+	[0x1de] = "Reserved",
+	[0x1df] = "Reserved",
+	[0x1e0] = "Reserved",
+	[0x1e1] = "Reserved",
+	[0x1e2] = "Reserved",
+	[0x1e3] = "Reserved",
+	[0x1e4] = "Reserved",
+	[0x1e5] = "Reserved",
+	[0x1e6] = "Reserved",
+	[0x1e7] = "Reserved",
+	[0x1e8] = "Reserved",
+	[0x1e9] = "Reserved",
+	[0x1ea] = "Reserved",
+	[0x1eb] = "Reserved",
+	[0x1ec] = "Reserved",
+	[0x1ed] = "Reserved",
+	[0x1ee] = "Reserved",
+	[0x1ef] = "Reserved",
+	[0x1f0] = "Reserved",
+	[0x1f1] = "Reserved",
+	[0x1f2] = "Reserved",
+	[0x1f3] = "Reserved",
+	[0x1f4] = "Reserved",
+	[0x1f5] = "Reserved",
+	[0x1f6] = "Reserved",
+	[0x1f7] = "Reserved",
+	[0x1f8] = "Reserved",
+	[0x1f9] = "Reserved",
+	[0x1fa] = "Reserved",
+	[0x1fb] = "Reserved",
+	[0x1fc] = "Reserved",
+	[0x1fd] = "Reserved",
+	[0x1fe] = "Reserved",
+	[0x1ff] = "Reserved",
+	[0x200] = "Generic GUI Application Controls",
+	[0x201] = "AC New",
+	[0x202] = "AC Open",
+	[0x203] = "AC Close",
+	[0x204] = "AC Exit",
+	[0x205] = "AC Maximize",
+	[0x206] = "AC Minimize",
+	[0x207] = "AC Save",
+	[0x208] = "AC Print",
+	[0x209] = "AC Properties",
+	[0x20a] = "",
+	[0x20b] = "",
+	[0x20c] = "",
+	[0x20d] = "",
+	[0x20e] = "",
+	[0x20f] = "",
+	[0x210] = "",
+	[0x211] = "",
+	[0x212] = "",
+	[0x213] = "",
+	[0x214] = "",
+	[0x215] = "",
+	[0x216] = "",
+	[0x217] = "",
+	[0x218] = "",
+	[0x219] = "",
+	[0x21a] = "AC Undo",
+	[0x21b] = "AC Copy",
+	[0x21c] = "AC Cut",
+	[0x21d] = "AC Paste",
+	[0x21e] = "AC Select All",
+	[0x21f] = "AC Find",
+	[0x220] = "AC Find and Replace",
+	[0x221] = "AC Search",
+	[0x222] = "AC Go To",
+	[0x223] = "AC Home",
+	[0x224] = "AC Back",
+	[0x225] = "AC Forward",
+	[0x226] = "AC Stop",
+	[0x227] = "AC Refresh",
+	[0x228] = "AC Previous Link",
+	[0x229] = "AC Next Link",
+	[0x22a] = "AC Bookmarks",
+	[0x22b] = "AC History",
+	[0x22c] = "AC Subscriptions",
+	[0x22d] = "AC Zoom In",
+	[0x22e] = "AC Zoom Out",
+	[0x22f] = "AC Zoom",
+	[0x230] = "AC Full Screen View",
+	[0x231] = "AC Normal View",
+	[0x232] = "AC View Toggle",
+	[0x233] = "AC Scroll Up",
+	[0x234] = "AC Scroll Down",
+	[0x235] = "AC Scroll",
+	[0x236] = "AC Pan Left",
+	[0x237] = "AC Pan Right",
+	[0x238] = "AC Pan",
+	[0x239] = "AC New Window",
+	[0x23a] = "AC Tile Horizontally",
+	[0x23b] = "AC Tile Vertically",
+	[0x23c] = "AC Format",
+	[0x23d] = "AC Edit",
+	[0x23e] = "AC Bold",
+	[0x23f] = "AC Italics",
+	[0x240] = "AC Undeline",
+	[0x241] = "AC Strikethrough",
+	[0x242] = "AC Subscript",
+	[0x243] = "AC Superscript",
+	[0x244] = "AC All Caps",
+	[0x245] = "AC Rotate",
+	[0x246] = "AC Resize",
+	[0x247] = "AC Flip Horizontal",
+	[0x248] = "AC Flip Vertical",
+	[0x249] = "AC Mirror Horizontal",
+	[0x24a] = "AC Mirror Vertical",
+	[0x24b] = "AC Font Select",
+	[0x24c] = "AC Font Color",
+	[0x24d] = "AC Font Size",
+	[0x24e] = "AC Justify Left",
+	[0x24f] = "AC Justify Center H",
+	[0x250] = "AC Justify Right",
+	[0x251] = "AC Justify Block H",
+	[0x252] = "AC Justify Top",
+	[0x253] = "AC Justify Center V",
+	[0x254] = "AC Justify Bottom",
+	[0x255] = "AC Justify Block V",
+	[0x256] = "AC Indent Decrease",
+	[0x257] = "AC Indent Increase",
+	[0x258] = "AC Numbered List",
+	[0x259] = "AC Restart Numbering",
+	[0x25a] = "AC Bulleted List",
+	[0x25b] = "AC Promote",
+	[0x25c] = "AC Demote",
+	[0x25d] = "AC Yes",
+	[0x25e] = "AC No",
+	[0x25f] = "AC Cancel",
+	[0x260] = "AC Catalog",
+	[0x261] = "AC Buy/Checkout",
+	[0x262] = "AC Add to Cart",
+	[0x263] = "AC Expand",
+	[0x264] = "AC Expand All",
+	[0x265] = "AC Collapse",
+	[0x266] = "AC Collapse All",
+	[0x267] = "AC Print Preview",
+	[0x268] = "AC Paste Special",
+	[0x269] = "AC Insert Mode",
+	[0x26a] = "AC Delete",
+	[0x26b] = "AC Lock",
+	[0x26c] = "AC Unlock",
+	[0x26d] = "AC Protect",
+	[0x26e] = "AC Unprotect",
+	[0x26f] = "AC Attach Comment",
+	[0x270] = "AC Delete Comment",
+	[0x271] = "AC View Comment",
+	[0x272] = "AC Select Word",
+	[0x273] = "AC Select Sentence",
+	[0x274] = "AC Select Paragraph",
+	[0x275] = "AC Select Column",
+	[0x276] = "AC Select Row",
+	[0x277] = "AC Select Table",
+	[0x278] = "AC Select Object",
+	[0x279] = "AC Redo/Repeat",
+	[0x27a] = "AC Sort",
+	[0x27b] = "AC Sort Ascending",
+	[0x27c] = "AC Sort Descending",
+	[0x27d] = "AC Filter",
+	[0x27e] = "AC Set Clock",
+	[0x27f] = "AC View Clock",
+	[0x280] = "AC Select Time Zone",
+	[0x281] = "AC Edit Time Zones",
+	[0x282] = "AC Set Alarm",
+	[0x283] = "AC Clear Alarm",
+	[0x284] = "AC Snooze Alarm",
+	[0x285] = "AC Reset Alarm",
+	[0x286] = "AC Synchronize",
+	[0x287] = "AC Send/Receive",
+	[0x288] = "AC Send To",
+	[0x289] = "AC Reply",
+	[0x28a] = "AC Reply All",
+	[0x28b] = "AC Forward Msg",
+	[0x28c] = "AC Send",
+	[0x28d] = "AC Attach File",
+	[0x28e] = "AC Upload",
+	[0x28f] = "AC Download (Save Target As)",
+	[0x290] = "AC Set Borders",
+	[0x291] = "AC Insert Row",
+	[0x292] = "AC Insert Column",
+	[0x293] = "AC Insert File",
+	[0x294] = "AC Insert Picture",
+	[0x295] = "AC Insert Object",
+	[0x296] = "AC Insert Symbol",
+	[0x297] = "AC Save and Close",
+	[0x298] = "AC Rename",
+	[0x299] = "AC Merge",
+	[0x29a] = "AC Split",
+	[0x29b] = "AC Distrubute Horizontally",
+	[0x29c] = "AC Distrubute Vertically"
+};
+
+/**
+ * Translates USB HID Usages from the Consumer Page into their string 
+ * representation.
+ *
+ * @param usage USB HID Consumer Page Usage number.
+ * 
+ * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
+ */
+const char *usbhid_multimedia_usage_to_str(int usage)
+{
+	size_t map_length = sizeof(usbhid_consumer_usage_str) / sizeof(char *);
+
+	if ((usage < 0) || ((size_t)usage >= map_length))
+		return "Unknown usage";
+
+	/*! @todo What if the usage is not in the table? */
+	return usbhid_consumer_usage_str[usage];
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/hiddescriptor.c
===================================================================
--- uspace/lib/usbhid/src/hiddescriptor.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/src/hiddescriptor.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1064 @@
+/*
+ * Copyright (c) 2011 Matej Klonfar
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * HID report descriptor and report data parser implementation.
+ */
+#include <usb/hid/hidparser.h>
+#include <errno.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <mem.h>
+#include <usb/debug.h>
+#include <assert.h>
+
+/*---------------------------------------------------------------------------*/
+/*
+ * Constants defining current parsing mode for correct parsing of the set of
+ * local tags (usage) enclosed in delimter tags.
+ */
+/**
+ * Second delimiter tag was read. The set of local items (usage) ended.
+ */
+#define OUTSIDE_DELIMITER_SET	0
+
+/**
+ * First delimiter tag was read. The set of local items (usage) started.
+ */
+#define START_DELIMITER_SET	1
+
+/**
+ * Parser is in the set of local items.
+ */
+#define INSIDE_DELIMITER_SET	2
+
+/*---------------------------------------------------------------------------*/
+	
+/** The new report item flag. Used to determine when the item is completly
+ * configured and should be added to the report structure
+ */
+#define USB_HID_NEW_REPORT_ITEM 1
+
+/** No special action after the report descriptor tag is processed should be
+ * done
+ */
+#define USB_HID_NO_ACTION	2
+
+#define USB_HID_RESET_OFFSET	3
+
+/** Unknown tag was founded in report descriptor data*/
+#define USB_HID_UNKNOWN_TAG		-99
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Checks if given collection path is already present in report structure and
+ * inserts it if not.
+ *
+ * @param report Report structure 
+ * @param cmp_path The collection path 
+ * @return Pointer to the result collection path in report structure.
+ * @retval NULL If some error occurs
+ */
+usb_hid_report_path_t *usb_hid_report_path_try_insert(usb_hid_report_t *report,
+    usb_hid_report_path_t *cmp_path)
+{
+	link_t *path_it = report->collection_paths.head.next;
+	usb_hid_report_path_t *path = NULL;
+	
+	if((report == NULL) || (cmp_path == NULL)) {
+		return NULL;
+	}
+	
+	while(path_it != &report->collection_paths.head) {
+		path = list_get_instance(path_it, usb_hid_report_path_t,
+				cpath_link);
+		
+		if(usb_hid_report_compare_usage_path(path, cmp_path,
+					USB_HID_PATH_COMPARE_STRICT) == EOK){
+			break;
+		}
+		path_it = path_it->next;
+	}
+	if(path_it == &report->collection_paths.head) {
+		path = usb_hid_report_path_clone(cmp_path);
+		if(path == NULL) {
+			return NULL;
+		}
+		list_append(&path->cpath_link, &report->collection_paths);
+		report->collection_paths_count++;
+
+		return path;
+	}
+	else {
+		return list_get_instance(path_it, usb_hid_report_path_t,
+				cpath_link); 
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Initialize the report descriptor parser structure
+ *
+ * @param parser Report descriptor parser structure
+ * @return Error code
+ * @retval EINVAL If no report structure was given
+ * @retval EOK If report structure was successfully initialized
+ */
+int usb_hid_report_init(usb_hid_report_t *report)
+{
+	if(report == NULL) {
+		return EINVAL;
+	}
+
+	memset(report, 0, sizeof(usb_hid_report_t));
+	list_initialize(&report->reports);
+	list_initialize(&report->collection_paths);
+
+	report->use_report_ids = 0;
+    return EOK;   
+}
+
+/*---------------------------------------------------------------------------*/
+
+/**
+ *
+ *
+ * @param report Report structure in which the new report items should be
+ * 		 stored
+ * @param report_item Current report descriptor's parsing state table 
+ * @return Error code
+ * @retval EOK If all fields were successfully append to report
+ * @retval EINVAL If invalid parameters (NULL) was given
+ * @retval ENOMEM If there is no memmory to store new report description
+ *
+ */
+int usb_hid_report_append_fields(usb_hid_report_t *report,
+		usb_hid_report_item_t *report_item) {
+
+	usb_hid_report_field_t *field;
+	int i;
+
+	uint32_t *usages;
+	int usages_used=0;
+
+	if((report == NULL) || (report_item == NULL)) {
+		return EINVAL;
+	}
+
+	if(report_item->usages_count > 0){
+		usages = malloc(sizeof(int32_t) * report_item->usages_count);
+		memcpy(usages, report_item->usages, sizeof(int32_t) *
+				report_item->usages_count); 
+	}
+	else {
+		usages = NULL;
+	}
+	
+	usb_hid_report_path_t *path = report_item->usage_path;	
+	for(i=0; i<report_item->count; i++){
+
+		field = malloc(sizeof(usb_hid_report_field_t));
+		if(field == NULL) {
+			return ENOMEM;
+		}
+
+		memset(field, 0, sizeof(usb_hid_report_field_t));
+		link_initialize(&field->ritems_link);
+
+		/* fill the attributes */		
+		field->logical_minimum = report_item->logical_minimum;
+		field->logical_maximum = report_item->logical_maximum;
+		field->physical_minimum = report_item->physical_minimum;
+		field->physical_maximum = report_item->physical_maximum;
+
+		if(USB_HID_ITEM_FLAG_VARIABLE(report_item->item_flags) == 0){
+			/* 
+			Store usage array. The Correct Usage Page and Usage is
+			depending on data in report and will be filled later
+			*/
+			field->usage = 0;
+			field->usage_page = 0; //report_item->usage_page;
+
+			field->usages_count = report_item->usages_count;
+			field->usages = usages;
+			usages_used = 1;
+		}
+		else {
+
+			/* Fill the correct Usage and Usage Page */
+			int32_t usage;
+			if(i < report_item->usages_count) {
+				usage = report_item->usages[i];
+			}
+			else {
+				usage = report_item->usages[
+					report_item->usages_count- 1]; 
+			}
+
+			if(USB_HID_IS_EXTENDED_USAGE(usage)){
+				field->usage = USB_HID_EXTENDED_USAGE(usage);
+				field->usage_page = 
+					USB_HID_EXTENDED_USAGE_PAGE(usage);
+			}
+			else {
+				// should not occur
+				field->usage = usage;
+				field->usage_page = report_item->usage_page;
+			}
+		}
+		
+		usb_hid_report_set_last_item(path, USB_HID_TAG_CLASS_GLOBAL,
+				field->usage_page);
+		usb_hid_report_set_last_item(path, USB_HID_TAG_CLASS_LOCAL,
+				field->usage);
+
+		field->collection_path =
+			usb_hid_report_path_try_insert(report, path);
+
+		field->size = report_item->size;
+
+		if(report_item->type == USB_HID_REPORT_TYPE_INPUT) {
+			int offset = report_item->offset + report_item->size * i;
+			int field_offset = (offset/8)*8 + (offset/8 + 1) * 8 - 
+				offset - report_item->size;
+			if(field_offset < 0) {
+				field->offset = 0;
+			}
+			else {
+				field->offset = field_offset;
+			}
+		}
+		else {
+			field->offset = report_item->offset + (i * report_item->size);
+		}
+
+
+		if(report->use_report_ids != 0) {
+			field->offset += 8;
+			report->use_report_ids = 1;
+		}
+
+		field->item_flags = report_item->item_flags;
+
+		/* find the right report list*/
+		usb_hid_report_description_t *report_des;
+		report_des = usb_hid_report_find_description(report,
+			report_item->id, report_item->type);
+		
+		if(report_des == NULL){
+			report_des = malloc(
+				sizeof(usb_hid_report_description_t));
+			if(report_des == NULL) {
+				return ENOMEM;
+			}
+
+			memset(report_des, 0,
+				sizeof(usb_hid_report_description_t));
+
+			report_des->type = report_item->type;
+			report_des->report_id = report_item->id;
+			if(report_des->report_id != 0) {
+				/* set up the bit length by report_id field */
+				report_des->bit_length = 8;
+			}
+
+			link_initialize (&report_des->reports_link);
+			list_initialize (&report_des->report_items);
+
+			list_append(&report_des->reports_link, &report->reports);
+			report->report_count++;
+		}
+
+		/* append this field to the end of founded report list */
+		list_append(&field->ritems_link, &report_des->report_items);
+		
+		/* update the sizes */
+		report_des->bit_length += field->size;
+		report_des->item_length++;
+
+	}
+
+	// free only when not used!!!
+	if(usages && usages_used == 0) {
+		free(usages);
+	}
+
+	return EOK;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Finds description of report with given report_id and of given type in
+ * opaque report structure.
+ *
+ * @param report Opaque structure containing the parsed report descriptor
+ * @param report_id ReportId of report we are searching
+ * @param type Type of report we are searching
+ * @return Pointer to the particular report description
+ * @retval NULL If no description is founded
+ */
+usb_hid_report_description_t * usb_hid_report_find_description(
+		const usb_hid_report_t *report, uint8_t report_id,
+		usb_hid_report_type_t type) {
+
+	if(report == NULL) {
+		return NULL;
+	}
+
+	usb_hid_report_description_t *report_des = NULL;
+	
+	list_foreach(report->reports, report_it) {
+		report_des = list_get_instance(report_it,
+				usb_hid_report_description_t, reports_link);
+
+		// if report id not set, return the first of the type
+		if(((report_des->report_id == report_id) || (report_id == 0)) && 
+		   (report_des->type == type)) { 
+			return report_des;
+		}
+	}
+
+	return NULL;
+}
+/*---------------------------------------------------------------------------*/
+
+/** Parse HID report descriptor.
+ *
+ * @param parser Opaque HID report parser structure.
+ * @param data Data describing the report.
+ * @return Error code.
+ * @retval ENOMEM If no more memmory is available
+ * @retval EINVAL If invalid data are founded
+ * @retval EOK If report descriptor is successfully parsed
+ */
+int usb_hid_parse_report_descriptor(usb_hid_report_t *report, 
+    const uint8_t *data, size_t size)
+{
+	size_t i=0;
+	uint8_t tag=0;
+	uint8_t item_size=0;
+	int class=0;
+	int ret;
+	usb_hid_report_item_t *report_item=0;
+	usb_hid_report_item_t *new_report_item;	
+	usb_hid_report_path_t *usage_path;
+
+	size_t offset_input=0;
+	size_t offset_output=0;
+	size_t offset_feature=0;
+	
+	link_t *item_link;
+
+	list_t stack;
+	list_initialize(&stack);
+
+	/* parser structure initialization*/
+	if(usb_hid_report_init(report) != EOK) {
+		return EINVAL;
+	}
+	
+	/*report item initialization*/
+	if(!(report_item=malloc(sizeof(usb_hid_report_item_t)))){
+		return ENOMEM;
+	}
+	memset(report_item, 0, sizeof(usb_hid_report_item_t));
+	link_initialize(&(report_item->link));
+
+	/* usage path context initialization */
+	if(!(usage_path=usb_hid_report_path())){
+		return ENOMEM;
+	}
+	usb_hid_report_path_append_item(usage_path, 0, 0);	
+	
+	while(i<size){	
+		if(!USB_HID_ITEM_IS_LONG(data[i])){
+
+			if((i+USB_HID_ITEM_SIZE(data[i]))>= size){
+				return EINVAL;
+			}
+			
+			tag = USB_HID_ITEM_TAG(data[i]);
+			item_size = USB_HID_ITEM_SIZE(data[i]);
+			class = USB_HID_ITEM_TAG_CLASS(data[i]);
+			
+			ret = usb_hid_report_parse_tag(tag,class,data+i+1,
+				item_size,report_item, usage_path);
+
+			switch(ret){
+			case USB_HID_NEW_REPORT_ITEM:
+				/* store report item to report and create the
+				 * new one store current collection path
+				 */
+				report_item->usage_path = usage_path;
+					
+				usb_hid_report_path_set_report_id(
+				     report_item->usage_path, report_item->id);
+				
+				if(report_item->id != 0){
+					report->use_report_ids = 1;
+				}
+					
+				switch(tag) {
+				case USB_HID_REPORT_TAG_INPUT:
+					report_item->type = 
+					    USB_HID_REPORT_TYPE_INPUT;
+
+					report_item->offset = offset_input;
+					offset_input += report_item->count * 
+					    report_item->size;
+					break;
+	
+				case USB_HID_REPORT_TAG_OUTPUT:
+					report_item->type = 
+					    USB_HID_REPORT_TYPE_OUTPUT;
+					
+					report_item->offset = offset_output;
+					offset_output += report_item->count * 
+					    report_item->size;
+					break;
+	
+				case USB_HID_REPORT_TAG_FEATURE:
+					report_item->type = 
+					    USB_HID_REPORT_TYPE_FEATURE;
+
+					report_item->offset = offset_feature;
+					offset_feature += report_item->count * 
+						report_item->size;
+					break;
+	
+				default:
+					usb_log_debug2(
+					    "\tjump over - tag %X\n", tag);
+				    	break;
+				}
+					
+				/* 
+				 * append new fields to the report structure 					 
+				 */
+				usb_hid_report_append_fields(report, 
+				    report_item);
+
+				/* reset local items */
+				usb_hid_report_reset_local_items (report_item);
+				break;
+
+			case USB_HID_RESET_OFFSET:
+				offset_input = 0;
+				offset_output = 0;
+				offset_feature = 0;
+				usb_hid_report_path_set_report_id (usage_path, 
+				    report_item->id);
+				break;
+
+			case USB_HID_REPORT_TAG_PUSH:
+				// push current state to stack
+				new_report_item = usb_hid_report_item_clone(
+				    report_item);
+				
+				usb_hid_report_path_t *tmp_path = 
+				    usb_hid_report_path_clone(usage_path);
+
+				new_report_item->usage_path = tmp_path; 
+
+				list_prepend (&new_report_item->link, &stack);
+				break;
+			case USB_HID_REPORT_TAG_POP:
+				// restore current state from stack
+				item_link = list_first(&stack);
+				if (item_link == NULL) {
+					return EINVAL;
+				}
+				free(report_item);
+				
+				report_item = list_get_instance(item_link,
+				    usb_hid_report_item_t, link);
+				
+				usb_hid_report_usage_path_t *tmp_usage_path;
+				tmp_usage_path = list_get_instance(
+				    report_item->usage_path->cpath_link.prev,
+				    usb_hid_report_usage_path_t, rpath_items_link);
+				
+				usb_hid_report_set_last_item(usage_path, 
+				    USB_HID_TAG_CLASS_GLOBAL, tmp_usage_path->usage_page);
+				
+				usb_hid_report_set_last_item(usage_path, 
+				    USB_HID_TAG_CLASS_LOCAL, tmp_usage_path->usage);
+
+				usb_hid_report_path_free(report_item->usage_path);
+				list_remove (item_link);
+					
+				break;
+					
+			default:
+				// nothing special to do					
+				break;
+			}
+
+			/* jump over the processed block */
+			i += 1 + USB_HID_ITEM_SIZE(data[i]);
+		}
+		else{
+			// TBD
+			i += 3 + USB_HID_ITEM_SIZE(data[i+1]);
+		}
+		
+
+	}
+	
+	return EOK;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Parse one tag of the report descriptor
+ *
+ * @param Tag to parse
+ * @param Report descriptor buffer
+ * @param Size of data belongs to this tag
+ * @param Current report item structe
+ * @return Code of action to be done next
+ */
+int usb_hid_report_parse_tag(uint8_t tag, uint8_t class, const uint8_t *data,
+	size_t item_size, usb_hid_report_item_t *report_item,
+	usb_hid_report_path_t *usage_path) {	
+	
+	int ret;
+	
+	switch(class){
+	case USB_HID_TAG_CLASS_MAIN:
+
+		if((ret=usb_hid_report_parse_main_tag(tag, data, item_size,
+			report_item, usage_path)) == EOK) {
+
+			return USB_HID_NEW_REPORT_ITEM;
+		}
+		else {
+			return ret;
+		}
+		break;
+
+	case USB_HID_TAG_CLASS_GLOBAL:	
+		return usb_hid_report_parse_global_tag(tag, data, item_size,
+			report_item, usage_path);
+		break;
+
+	case USB_HID_TAG_CLASS_LOCAL:			
+		return usb_hid_report_parse_local_tag(tag, data, item_size,
+			report_item, usage_path);
+		break;
+	
+	default:
+		return USB_HID_NO_ACTION;
+	}
+}
+
+/**
+ * Parse main tags of report descriptor
+ *
+ * @param Tag identifier
+ * @param Data buffer
+ * @param Length of data buffer
+ * @param Current state table
+ * @return Error code
+ */
+
+int usb_hid_report_parse_main_tag(uint8_t tag, const uint8_t *data, 
+	size_t item_size, usb_hid_report_item_t *report_item,
+	usb_hid_report_path_t *usage_path)
+{
+	usb_hid_report_usage_path_t *path_item;
+	
+	switch(tag)
+	{
+	case USB_HID_REPORT_TAG_INPUT:
+	case USB_HID_REPORT_TAG_OUTPUT:
+	case USB_HID_REPORT_TAG_FEATURE:
+		report_item->item_flags = *data;			
+		return EOK;			
+		break;
+			
+	case USB_HID_REPORT_TAG_COLLECTION:
+
+		/* store collection atributes */
+		path_item = list_get_instance(list_first(&usage_path->items),
+			usb_hid_report_usage_path_t, rpath_items_link);
+		path_item->flags = *data;
+			
+		/* set last item */
+		usb_hid_report_set_last_item(usage_path, 
+			USB_HID_TAG_CLASS_GLOBAL, 
+			USB_HID_EXTENDED_USAGE_PAGE(report_item->usages[
+				report_item->usages_count-1]));
+
+		usb_hid_report_set_last_item(usage_path, 
+			USB_HID_TAG_CLASS_LOCAL, 
+			USB_HID_EXTENDED_USAGE(report_item->usages[
+				report_item->usages_count-1]));
+			
+		/* append the new one which will be set by common usage/usage
+		 * page */
+		usb_hid_report_path_append_item(usage_path, 
+			report_item->usage_page, 
+			report_item->usages[report_item->usages_count-1]);
+
+		usb_hid_report_reset_local_items (report_item);
+		return USB_HID_NO_ACTION;
+		break;
+			
+	case USB_HID_REPORT_TAG_END_COLLECTION:
+		usb_hid_report_remove_last_item(usage_path);
+		return USB_HID_NO_ACTION;
+		break;
+
+	default:
+		return USB_HID_NO_ACTION;
+	}
+
+	return EOK;
+}
+
+/**
+ * Parse global tags of report descriptor
+ *
+ * @param Tag identifier
+ * @param Data buffer
+ * @param Length of data buffer
+ * @param Current state table
+ * @return Error code
+ */
+int usb_hid_report_parse_global_tag(uint8_t tag, const uint8_t *data, 
+	size_t item_size, usb_hid_report_item_t *report_item, 
+	usb_hid_report_path_t *usage_path) { 
+	
+	switch(tag)
+	{
+	case USB_HID_REPORT_TAG_USAGE_PAGE:
+		report_item->usage_page = 
+			usb_hid_report_tag_data_uint32(data, item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_LOGICAL_MINIMUM:
+		report_item->logical_minimum = USB_HID_UINT32_TO_INT32(
+			usb_hid_report_tag_data_uint32(data,item_size),
+		       	item_size * 8);
+		break;
+
+	case USB_HID_REPORT_TAG_LOGICAL_MAXIMUM:
+		report_item->logical_maximum = USB_HID_UINT32_TO_INT32(
+			usb_hid_report_tag_data_uint32(data,item_size), 
+			item_size * 8);
+		break;
+
+	case USB_HID_REPORT_TAG_PHYSICAL_MINIMUM:
+		report_item->physical_minimum = USB_HID_UINT32_TO_INT32(
+			usb_hid_report_tag_data_uint32(data,item_size), 
+			item_size * 8);
+		break;			
+
+	case USB_HID_REPORT_TAG_PHYSICAL_MAXIMUM:
+		report_item->physical_maximum = USB_HID_UINT32_TO_INT32(
+			usb_hid_report_tag_data_uint32(data,item_size), 
+			item_size * 8);
+		break;
+
+	case USB_HID_REPORT_TAG_UNIT_EXPONENT:
+		report_item->unit_exponent = usb_hid_report_tag_data_uint32(
+			data,item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_UNIT:
+		report_item->unit = usb_hid_report_tag_data_uint32(
+			data,item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_REPORT_SIZE:
+		report_item->size = usb_hid_report_tag_data_uint32(
+			data,item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_REPORT_COUNT:
+		report_item->count = usb_hid_report_tag_data_uint32(
+			data,item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_REPORT_ID:
+		report_item->id = usb_hid_report_tag_data_uint32(data, 
+			item_size);
+		return USB_HID_RESET_OFFSET;
+		break;
+	
+	case USB_HID_REPORT_TAG_PUSH:
+	case USB_HID_REPORT_TAG_POP:
+		/* 
+		 * stack operations are done in top level parsing
+		 * function
+		 */
+		return tag;
+		break;
+			
+	default:
+		return USB_HID_NO_ACTION;
+	}
+
+	return EOK;
+}
+
+/**
+ * Parse local tags of report descriptor
+ *
+ * @param Tag identifier
+ * @param Data buffer
+ * @param Length of data buffer
+ * @param Current state table
+ * @return Error code
+ */
+int usb_hid_report_parse_local_tag(uint8_t tag, const uint8_t *data, 
+	size_t item_size, usb_hid_report_item_t *report_item, 
+	usb_hid_report_path_t *usage_path)
+{
+	int32_t extended_usage;
+	
+	switch(tag) {
+	case USB_HID_REPORT_TAG_USAGE:
+		switch(report_item->in_delimiter) {
+		case INSIDE_DELIMITER_SET:
+			/* nothing to do
+			 * we catch only the first one
+			 */
+			break;
+	
+		case START_DELIMITER_SET:
+			report_item->in_delimiter = INSIDE_DELIMITER_SET;
+		case OUTSIDE_DELIMITER_SET:
+			extended_usage = ((report_item->usage_page) << 16);
+			extended_usage += usb_hid_report_tag_data_uint32(
+				data,item_size);
+
+			report_item->usages[report_item->usages_count] = 
+				extended_usage;
+
+			report_item->usages_count++;
+			break;
+		}
+		break;
+		
+	case USB_HID_REPORT_TAG_USAGE_MINIMUM:			
+		if (item_size == 3) {
+			// usage extended usages
+			report_item->extended_usage_page = 
+			    USB_HID_EXTENDED_USAGE_PAGE(
+			    usb_hid_report_tag_data_uint32(data,item_size));
+			   
+
+			report_item->usage_minimum = 
+			    USB_HID_EXTENDED_USAGE(
+			    usb_hid_report_tag_data_uint32(data,item_size));
+		}
+		else {
+			report_item->usage_minimum = 
+			    usb_hid_report_tag_data_uint32(data,item_size);
+		}
+		break;
+	
+	case USB_HID_REPORT_TAG_USAGE_MAXIMUM:
+		if (item_size == 3) {
+			if(report_item->extended_usage_page != 
+			    USB_HID_EXTENDED_USAGE_PAGE(	
+			    usb_hid_report_tag_data_uint32(data,item_size))) {
+				
+				return EINVAL;
+			}
+				
+			// usage extended usages
+			report_item->extended_usage_page = 
+				USB_HID_EXTENDED_USAGE_PAGE(
+				usb_hid_report_tag_data_uint32(data,item_size));
+
+			report_item->usage_maximum = 
+				USB_HID_EXTENDED_USAGE(
+				usb_hid_report_tag_data_uint32(data,item_size));
+		}
+		else {
+			report_item->usage_maximum = 
+				usb_hid_report_tag_data_uint32(data,item_size);
+		}
+
+		// vlozit zaznamy do pole usages
+		int32_t i;
+		for(i = report_item->usage_minimum; 
+		    i <= report_item->usage_maximum; i++) {
+
+			if(report_item->extended_usage_page) {
+			    report_item->usages[report_item->usages_count++] = 
+				(report_item->extended_usage_page << 16) + i;
+			}
+			else {			
+			    report_item->usages[report_item->usages_count++] = 
+				(report_item->usage_page << 16) + i;
+			}
+		}
+		report_item->extended_usage_page = 0;
+			
+		break;
+		
+	case USB_HID_REPORT_TAG_DESIGNATOR_INDEX:
+		report_item->designator_index = 
+			usb_hid_report_tag_data_uint32(data,item_size);
+		break;
+	
+	case USB_HID_REPORT_TAG_DESIGNATOR_MINIMUM:
+		report_item->designator_minimum = 
+			usb_hid_report_tag_data_uint32(data,item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_DESIGNATOR_MAXIMUM:
+		report_item->designator_maximum = 
+			usb_hid_report_tag_data_uint32(data,item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_STRING_INDEX:
+		report_item->string_index = 
+			usb_hid_report_tag_data_uint32(data,item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_STRING_MINIMUM:
+		report_item->string_minimum = 
+			usb_hid_report_tag_data_uint32(data,item_size);
+		break;
+
+	case USB_HID_REPORT_TAG_STRING_MAXIMUM:
+		report_item->string_maximum = 
+			usb_hid_report_tag_data_uint32(data,item_size);
+		break;			
+
+	case USB_HID_REPORT_TAG_DELIMITER:
+		report_item->in_delimiter = 
+			usb_hid_report_tag_data_uint32(data,item_size);
+		break;
+
+	default:
+		return USB_HID_NO_ACTION;
+	}
+
+	return EOK;
+}
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Converts raw data to uint32 (thats the maximum length of short item data)
+ *
+ * @param Data buffer
+ * @param Size of buffer
+ * @return Converted int32 number
+ */
+uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size)
+{
+	unsigned int i;
+	uint32_t result;
+
+	result = 0;
+	for(i=0; i<size; i++) {
+		result = (result | (data[i]) << (i*8));
+	}
+
+	return result;
+}
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Prints content of given list of report items.
+ *
+ * @param List of report items (usb_hid_report_item_t)
+ * @return void
+ */
+void usb_hid_descriptor_print_list(list_t *list)
+{
+	usb_hid_report_field_t *report_item;
+
+	if(list == NULL || list_empty(list)) {
+	    usb_log_debug("\tempty\n");
+	    return;
+	}
+
+        list_foreach(*list, item) {
+		report_item = list_get_instance(item, usb_hid_report_field_t,
+				ritems_link);
+
+		usb_log_debug("\t\tOFFSET: %X\n", report_item->offset);
+		usb_log_debug("\t\tSIZE: %zu\n", report_item->size);
+		usb_log_debug("\t\tLOGMIN: %d\n",
+			report_item->logical_minimum);
+		usb_log_debug("\t\tLOGMAX: %d\n",
+			report_item->logical_maximum);
+		usb_log_debug("\t\tPHYMIN: %d\n",
+			report_item->physical_minimum);
+		usb_log_debug("\t\tPHYMAX: %d\n",
+			report_item->physical_maximum);
+		usb_log_debug("\t\ttUSAGEMIN: %X\n",
+			report_item->usage_minimum);
+		usb_log_debug("\t\tUSAGEMAX: %X\n",
+			       report_item->usage_maximum);
+		usb_log_debug("\t\tUSAGES COUNT: %zu\n",
+			report_item->usages_count);
+
+		usb_log_debug("\t\tVALUE: %X\n", report_item->value);
+		usb_log_debug("\t\ttUSAGE: %X\n", report_item->usage);
+		usb_log_debug("\t\tUSAGE PAGE: %X\n", report_item->usage_page);
+
+		usb_hid_print_usage_path(report_item->collection_path);
+
+		usb_log_debug("\n");
+
+	}
+
+}
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Prints content of given report descriptor in human readable format.
+ *
+ * @param parser Parsed descriptor to print
+ * @return void
+ */
+void usb_hid_descriptor_print(usb_hid_report_t *report)
+{
+	if(report == NULL) {
+		return;
+	}
+
+	usb_hid_report_description_t *report_des;
+
+	list_foreach(report->reports, report_it) {
+		report_des = list_get_instance(report_it,
+			usb_hid_report_description_t, reports_link);
+		usb_log_debug("Report ID: %d\n", report_des->report_id);
+		usb_log_debug("\tType: %d\n", report_des->type);
+		usb_log_debug("\tLength: %zu\n", report_des->bit_length);
+		usb_log_debug("\tB Size: %zu\n",
+			usb_hid_report_byte_size(report,
+				report_des->report_id,
+				report_des->type));
+		usb_log_debug("\tItems: %zu\n", report_des->item_length);
+
+		usb_hid_descriptor_print_list(&report_des->report_items);
+	}
+}
+/*---------------------------------------------------------------------------*/
+
+/**
+ * Releases whole linked list of report items
+ *
+ * @param list List of report descriptor items (usb_hid_report_item_t)
+ * @return void
+ */
+void usb_hid_free_report_list(list_t *list)
+{
+	return; /* XXX What's this? */
+	
+/*	usb_hid_report_item_t *report_item;
+	link_t *next;
+	
+	if(list == NULL || list_empty(list)) {
+	    return;
+	}
+	
+	next = list->head.next;
+	while (next != &list->head) {
+		report_item = list_get_instance(next, usb_hid_report_item_t,
+		    rpath_items_link);
+
+		while(!list_empty(&report_item->usage_path->link)) {
+			usb_hid_report_remove_last_item(report_item->usage_path);
+		}
+
+		
+	    next = next->next;
+	    
+	    free(report_item);
+	}
+	
+	return;
+	*/
+}
+/*---------------------------------------------------------------------------*/
+
+/** Frees the HID report descriptor parser structure 
+ *
+ * @param parser Opaque HID report parser structure
+ * @return void
+ */
+void usb_hid_free_report(usb_hid_report_t *report)
+{
+	if(report == NULL){
+		return;
+	}
+
+	// free collection paths
+	link_t *path_link;
+	usb_hid_report_path_t *path;
+	while(!list_empty(&report->collection_paths)) {
+		path_link = list_first(&report->collection_paths);
+		path = list_get_instance(path_link,
+		    usb_hid_report_path_t, cpath_link);
+
+		list_remove(path_link);
+		usb_hid_report_path_free(path);
+	}
+	
+	// free report items
+	usb_hid_report_description_t *report_des;
+	usb_hid_report_field_t *field;
+	while(!list_empty(&report->reports)) {
+		report_des = list_get_instance(list_first(&report->reports),
+				usb_hid_report_description_t, reports_link);
+
+		list_remove(&report_des->reports_link);
+		
+		while(!list_empty(&report_des->report_items)) {
+			field = list_get_instance(
+			    list_first(&report_des->report_items),
+			    usb_hid_report_field_t, ritems_link);
+
+			list_remove(&field->ritems_link);
+
+			free(field);
+		}
+		
+		free(report_des);
+	}
+	
+	return;
+}
+/*---------------------------------------------------------------------------*/
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/hidiface.c
===================================================================
--- uspace/lib/usbhid/src/hidiface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/src/hidiface.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2011 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 libusbhid
+ * @{
+ */
+/** @file
+ * Client functions for accessing USB HID interface (implementation).
+ */
+#include <dev_iface.h>
+#include <usbhid_iface.h>
+#include <usb/hid/iface.h>
+#include <errno.h>
+#include <str_error.h>
+#include <async.h>
+#include <assert.h>
+
+/** Ask for event array length.
+ *
+ * @param dev_sess Session to DDF device providing USB HID interface.
+ *
+ * @return Number of usages returned or negative error code.
+ *
+ */
+int usbhid_dev_get_event_length(async_sess_t *dev_sess, size_t *size)
+{
+	if (!dev_sess)
+		return EINVAL;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	sysarg_t len;
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(USBHID_DEV_IFACE),
+	    IPC_M_USBHID_GET_EVENT_LENGTH, &len);
+	
+	async_exchange_end(exch);
+	
+	if (rc == EOK) {
+		if (size != NULL)
+			*size = (size_t) len;
+	}
+	
+	return rc;
+}
+
+/** Request for next event from HID device.
+ *
+ * @param[in]  dev_sess    Session to DDF device providing USB HID interface.
+ * @param[out] usage_pages Where to store usage pages.
+ * @param[out] usages      Where to store usages (actual data).
+ * @param[in]  usage_count Length of @p usage_pages and @p usages buffer
+ *                         (in items, not bytes).
+ * @param[out] actual_usage_count Number of usages actually returned by the
+ *                                device driver.
+ * @param[in] flags        Flags (see USBHID_IFACE_FLAG_*).
+ *
+ * @return Error code.
+ *
+ */
+int usbhid_dev_get_event(async_sess_t *dev_sess, uint8_t *buf,
+    size_t size, size_t *actual_size, int *event_nr, unsigned int flags)
+{
+	if (!dev_sess)
+		return EINVAL;
+	
+	if ((buf == NULL))
+		return ENOMEM;
+	
+	if (size == 0)
+		return EINVAL;
+	
+	size_t buffer_size =  size;
+	uint8_t *buffer = malloc(buffer_size);
+	if (buffer == NULL)
+		return ENOMEM;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	ipc_call_t opening_request_call;
+	aid_t opening_request = async_send_2(exch,
+	    DEV_IFACE_ID(USBHID_DEV_IFACE), IPC_M_USBHID_GET_EVENT,
+	    flags, &opening_request_call);
+	
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		free(buffer);
+		return ENOMEM;
+	}
+	
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(exch, buffer, buffer_size,
+	    &data_request_call);
+	
+	async_exchange_end(exch);
+	
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		free(buffer);
+		return ENOMEM;
+	}
+	
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	if (data_request_rc != EOK) {
+		/* Prefer return code of the opening request. */
+		if (opening_request_rc != EOK)
+			return (int) opening_request_rc;
+		else
+			return (int) data_request_rc;
+	}
+	
+	if (opening_request_rc != EOK)
+		return (int) opening_request_rc;
+	
+	size_t act_size = IPC_GET_ARG2(data_request_call);
+	
+	/* Copy the individual items. */
+	memcpy(buf, buffer, act_size);
+	
+	if (actual_size != NULL)
+		*actual_size = act_size;
+	
+	if (event_nr != NULL)
+		*event_nr = IPC_GET_ARG1(opening_request_call);
+	
+	return EOK;
+}
+
+int usbhid_dev_get_report_descriptor_length(async_sess_t *dev_sess,
+    size_t *size)
+{
+	if (!dev_sess)
+		return EINVAL;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	sysarg_t arg_size;
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(USBHID_DEV_IFACE),
+	    IPC_M_USBHID_GET_REPORT_DESCRIPTOR_LENGTH, &arg_size);
+	
+	async_exchange_end(exch);
+	
+	if (rc == EOK) {
+		if (size != NULL)
+			*size = (size_t) arg_size;
+	}
+	
+	return rc;
+}
+
+int usbhid_dev_get_report_descriptor(async_sess_t *dev_sess, uint8_t *buf,
+    size_t size, size_t *actual_size)
+{
+	if (!dev_sess)
+		return EINVAL;
+	
+	if ((buf == NULL))
+		return ENOMEM;
+	
+	if (size == 0)
+		return EINVAL;
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	
+	aid_t opening_request = async_send_1(exch,
+	    DEV_IFACE_ID(USBHID_DEV_IFACE), IPC_M_USBHID_GET_REPORT_DESCRIPTOR,
+	    NULL);
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		return ENOMEM;
+	}
+	
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(exch, buf, size,
+	    &data_request_call);
+	
+	async_exchange_end(exch);
+	
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+	
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	if (data_request_rc != EOK) {
+		/* Prefer return code of the opening request. */
+		if (opening_request_rc != EOK)
+			return (int) opening_request_rc;
+		else
+			return (int) data_request_rc;
+	}
+	
+	if (opening_request_rc != EOK)
+		return (int) opening_request_rc;
+	
+	size_t act_size = IPC_GET_ARG2(data_request_call);
+	
+	if (actual_size != NULL)
+		*actual_size = act_size;
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/hidparser.c
===================================================================
--- uspace/lib/usbhid/src/hidparser.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/src/hidparser.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 2011 Matej Klonfar
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * USB HID report data parser implementation.
+ */
+#include <usb/hid/hidparser.h>
+#include <errno.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <mem.h>
+#include <usb/debug.h>
+#include <assert.h>
+
+/*---------------------------------------------------------------------------*/
+/*
+ * Data translation private functions
+ */
+uint32_t usb_hid_report_tag_data_uint32(const uint8_t *data, size_t size);
+
+int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data);
+
+uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 
+	int32_t value);
+
+int usb_pow(int a, int b);
+
+/*---------------------------------------------------------------------------*/
+
+// TODO: tohle ma bejt asi jinde
+int usb_pow(int a, int b)
+{
+	switch(b) {
+	case 0:
+		return 1;
+		break;
+	case 1:
+		return a;
+		break;
+	default:
+		return a * usb_pow(a, b-1);
+		break;
+	}
+}
+/*---------------------------------------------------------------------------*/
+
+/** Returns size of report of specified report id and type in items
+ *
+ * @param parser Opaque report parser structure
+ * @param report_id 
+ * @param type
+ * @return Number of items in specified report
+ */
+size_t usb_hid_report_size(usb_hid_report_t *report, uint8_t report_id, 
+                           usb_hid_report_type_t type)
+{
+	usb_hid_report_description_t *report_des;
+
+	if(report == NULL) {
+		return 0;
+	}
+
+	report_des = usb_hid_report_find_description (report, report_id, type);
+	if(report_des == NULL){
+		return 0;
+	}
+	else {
+		return report_des->item_length;
+	}
+}
+
+/** Returns size of report of specified report id and type in bytes
+ *
+ * @param parser Opaque report parser structure
+ * @param report_id 
+ * @param type
+ * @return Number of items in specified report
+ */
+size_t usb_hid_report_byte_size(usb_hid_report_t *report, uint8_t report_id, 
+                           usb_hid_report_type_t type)
+{
+	usb_hid_report_description_t *report_des;
+
+	if(report == NULL) {
+		return 0;
+	}
+
+	report_des = usb_hid_report_find_description (report, report_id, type);
+	if(report_des == NULL){
+		return 0;
+	}
+	else {
+		return ((report_des->bit_length + 7) / 8) ;
+	}
+}
+/*---------------------------------------------------------------------------*/
+
+/** Parse and act upon a HID report.
+ *
+ * @see usb_hid_parse_report_descriptor
+ *
+ * @param parser Opaque HID report parser structure.
+ * @param data Data for the report.
+ * @return Error code.
+ */ 
+int usb_hid_parse_report(const usb_hid_report_t *report, const uint8_t *data, 
+	size_t size, uint8_t *report_id)
+{
+	usb_hid_report_field_t *item;
+
+	usb_hid_report_description_t *report_des;
+	usb_hid_report_type_t type = USB_HID_REPORT_TYPE_INPUT;
+	
+	if(report == NULL) {
+		return EINVAL;
+	}
+
+	if(report->use_report_ids != 0) {
+		*report_id = data[0];
+	}	
+	else {
+		*report_id = 0;
+	}
+
+
+	report_des = usb_hid_report_find_description(report, *report_id, 
+		type);
+
+	if(report_des == NULL) {
+		return EINVAL;
+	}
+
+	/* read data */
+	list_foreach(report_des->report_items, list_item) {
+		item = list_get_instance(list_item, usb_hid_report_field_t, 
+				ritems_link);
+
+		if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags) == 0) {
+			
+			if(USB_HID_ITEM_FLAG_VARIABLE(item->item_flags) == 0){
+
+				// array
+				item->value = 
+					usb_hid_translate_data(item, data);
+		
+				item->usage = USB_HID_EXTENDED_USAGE(
+				    item->usages[
+				    item->value - item->physical_minimum]);
+
+				item->usage_page = 
+				    USB_HID_EXTENDED_USAGE_PAGE(
+				    item->usages[
+				    item->value - item->physical_minimum]);
+
+				usb_hid_report_set_last_item (
+				    item->collection_path, 
+				    USB_HID_TAG_CLASS_GLOBAL, 
+				    item->usage_page);
+
+				usb_hid_report_set_last_item (
+				    item->collection_path, 
+				    USB_HID_TAG_CLASS_LOCAL, item->usage);
+				
+			}
+			else {
+				// variable item
+				item->value = usb_hid_translate_data(item, 
+				    data);				
+			}			
+		}
+	}
+	
+	return EOK;
+	
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Translate data from the report as specified in report descriptor item
+ *
+ * @param item Report descriptor item with definition of translation
+ * @param data Data to translate
+ * @return Translated data
+ */
+int usb_hid_translate_data(usb_hid_report_field_t *item, const uint8_t *data)
+{
+	int resolution;
+	int offset;
+	int part_size;
+	
+	int32_t value=0;
+	int32_t mask=0;
+	const uint8_t *foo=0;
+
+	// now only shot tags are allowed
+	if(item->size > 32) {
+		return 0;
+	}
+
+	if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
+		item->physical_minimum = item->logical_minimum;
+		item->physical_maximum = item->logical_maximum;			
+	}
+	
+
+	if(item->physical_maximum == item->physical_minimum){
+	    resolution = 1;
+	}
+	else {
+	    resolution = (item->logical_maximum - item->logical_minimum) / 
+		((item->physical_maximum - item->physical_minimum) * 
+		(usb_pow(10,(item->unit_exponent))));
+	}
+
+	offset = item->offset;
+	// FIXME
+	if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
+		
+		part_size = 0;
+
+		size_t i=0;
+		for(i=(size_t)(offset/8); i<=(size_t)(offset+item->size-1)/8; i++){
+			if(i == (size_t)(offset/8)) {
+				// the higher one
+				part_size = 8 - (offset % 8);
+				foo = data + i;
+				mask =  ((1 << (item->size-part_size))-1);
+				value = (*foo & mask);
+			}
+			else if(i == ((offset+item->size-1)/8)){
+				// the lower one
+				foo = data + i;
+				mask = ((1 << (item->size - part_size)) - 1) 
+					<< (8 - (item->size - part_size));
+
+				value = (((*foo & mask) >> (8 - 
+				    (item->size - part_size))) << part_size ) 
+				    + value;
+			}
+			else {
+				value = (*(data + 1) << (part_size + 8)) + value;
+				part_size += 8;
+			}
+		}
+	}
+	else {		
+		foo = data+(offset/8);
+		mask =  ((1 << item->size)-1) << (8-((offset%8)+item->size));
+		value = (*foo & mask) >> (8-((offset%8)+item->size));
+	}
+
+	if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
+		value = USB_HID_UINT32_TO_INT32(value, item->size);
+	}
+
+	return (int)(((value - item->logical_minimum) / resolution) + 
+		item->physical_minimum);
+	
+}
+
+/*---------------------------------------------------------------------------*/
+/* OUTPUT API */
+
+/** 
+ * Allocates output report buffer for output report
+ *
+ * @param parser Report parsed structure
+ * @param size Size of returned buffer
+ * @param report_id Report id of created output report
+ * @return Returns allocated output buffer for specified output
+ */
+uint8_t *usb_hid_report_output(usb_hid_report_t *report, size_t *size, 
+	uint8_t report_id)
+{
+	if(report == NULL) {
+		*size = 0;
+		return NULL;
+	}
+
+	usb_hid_report_description_t *report_des = NULL;
+
+	list_foreach(report->reports, report_it) {
+		report_des = list_get_instance(report_it,
+			usb_hid_report_description_t, reports_link);
+		
+		if((report_des->report_id == report_id) &&
+			(report_des->type == USB_HID_REPORT_TYPE_OUTPUT)){
+			break;
+		}
+	}
+
+	if(report_des == NULL){
+		*size = 0;
+		return NULL;
+	}
+	else {
+		*size = (report_des->bit_length + (8 - 1))/8;
+		uint8_t *ret = malloc((*size) * sizeof(uint8_t));
+		memset(ret, 0, (*size) * sizeof(uint8_t));
+		return ret;
+	}
+}
+
+
+/** Frees output report buffer
+ *
+ * @param output Output report buffer
+ * @return void
+ */
+void usb_hid_report_output_free(uint8_t *output)
+
+{
+	if(output != NULL) {
+		free (output);
+	}
+}
+
+/** Makes the output report buffer for data given in the report structure
+ *
+ * @param parser Opaque report parser structure
+ * @param path Usage path specifing which parts of output will be set
+ * @param flags Usage path structure comparison flags
+ * @param buffer Output buffer
+ * @param size Size of output buffer
+ * @return Error code
+ */
+int usb_hid_report_output_translate(usb_hid_report_t *report, 
+	uint8_t report_id, uint8_t *buffer, size_t size)
+{
+	int32_t value=0;
+	int offset;
+	int length;
+	int32_t tmp_value;
+	
+	if(report == NULL) {
+		return EINVAL;
+	}
+
+	if(report->use_report_ids != 0) {
+		buffer[0] = report_id;		
+	}
+
+	usb_hid_report_description_t *report_des;
+	report_des = usb_hid_report_find_description (report, report_id, 
+		USB_HID_REPORT_TYPE_OUTPUT);
+	
+	if(report_des == NULL){
+		return EINVAL;
+	}
+
+	usb_hid_report_field_t *report_item;
+
+	list_foreach(report_des->report_items, item) {
+		report_item = list_get_instance(item, usb_hid_report_field_t,
+		    ritems_link);
+
+		value = usb_hid_translate_data_reverse(report_item, 
+			report_item->value);
+
+		offset = report_des->bit_length - report_item->offset - 1;
+		length = report_item->size;
+		
+		usb_log_debug("\ttranslated value: %x\n", value);
+
+		if((offset/8) == ((offset+length-1)/8)) {
+			// je to v jednom bytu
+			if(((size_t)(offset/8) >= size) || 
+				((size_t)(offset+length-1)/8) >= size) {
+				break; // TODO ErrorCode
+			}
+			size_t shift = 8 - offset%8 - length;
+			value = value << shift;							
+			value = value & (((1 << length)-1) << shift);
+				
+			uint8_t mask = 0;
+			mask = 0xff - (((1 << length) - 1) << shift);
+			buffer[offset/8] = (buffer[offset/8] & mask) | value;
+		}
+		else {
+			int i = 0;
+			uint8_t mask = 0;
+			for(i = (offset/8); i <= ((offset+length-1)/8); i++) {
+				if(i == (offset/8)) {
+					tmp_value = value;
+					tmp_value = tmp_value & 
+						((1 << (8-(offset%8)))-1);
+
+					tmp_value = tmp_value << (offset%8);
+	
+					mask = ~(((1 << (8-(offset%8)))-1) << 
+							(offset%8));
+
+					buffer[i] = (buffer[i] & mask) | 
+						tmp_value;
+				}
+				else if (i == ((offset + length -1)/8)) {
+					
+					value = value >> (length - 
+						((offset + length) % 8));
+
+					value = value & ((1 << (length - 
+						((offset + length) % 8))) - 1);
+				
+					mask = (1 << (length - 
+						((offset + length) % 8))) - 1;
+
+					buffer[i] = (buffer[i] & mask) | value;
+				}
+				else {
+					buffer[i] = value & (0xFF << i);
+				}
+			}
+		}
+
+		// reset value
+		report_item->value = 0;
+	}
+	
+	return EOK;
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Translate given data for putting them into the outoput report
+ * @param item Report item structure
+ * @param value Value to translate
+ * @return ranslated value
+ */
+uint32_t usb_hid_translate_data_reverse(usb_hid_report_field_t *item, 
+	int value)
+{
+	int ret=0;
+	int resolution;
+
+	if(USB_HID_ITEM_FLAG_CONSTANT(item->item_flags)) {
+		ret = item->logical_minimum;
+	}
+
+	if((item->physical_minimum == 0) && (item->physical_maximum == 0)){
+		item->physical_minimum = item->logical_minimum;
+		item->physical_maximum = item->logical_maximum;			
+	}
+	
+	// variable item
+	if(item->physical_maximum == item->physical_minimum){
+	    resolution = 1;
+	}
+	else {
+	    resolution = (item->logical_maximum - item->logical_minimum) /
+		((item->physical_maximum - item->physical_minimum) *
+		(usb_pow(10,(item->unit_exponent))));
+	}
+
+	ret = ((value - item->physical_minimum) * resolution) + 
+		item->logical_minimum;
+
+	usb_log_debug("\tvalue(%x), resolution(%x), phymin(%x) logmin(%x), \
+		ret(%x)\n", value, resolution, item->physical_minimum, 
+		item->logical_minimum, ret);
+	
+	if((item->logical_minimum < 0) || (item->logical_maximum < 0)){
+		return USB_HID_INT32_TO_UINT32(ret, item->size);
+	}
+	return (int32_t)0 + ret;
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Clones given state table
+ *
+ * @param item State table to clone
+ * @return Pointer to the cloned item
+ */
+usb_hid_report_item_t *usb_hid_report_item_clone(
+	const usb_hid_report_item_t *item)
+{
+	usb_hid_report_item_t *new_report_item;
+	
+	if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
+		return NULL;
+	}					
+	memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));
+	link_initialize(&(new_report_item->link));
+
+	return new_report_item;
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Function for sequence walking through the report. Returns next field in the
+ * report or the first one when no field is given.
+ *
+ * @param report Searched report structure
+ * @param field Current field. If NULL is given, the first one in the report
+ * is returned. Otherwise the next one i nthe list is returned.
+ * @param path Usage path specifying which fields wa are interested in. 
+ * @param flags Flags defining mode of usage paths comparison
+ * @param type Type of report we search.
+ * @retval NULL if no field is founded
+ * @retval Pointer to the founded report structure when founded
+ */
+usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, 
+	usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, 
+	usb_hid_report_type_t type)
+{
+	usb_hid_report_description_t *report_des = 
+		usb_hid_report_find_description(report, path->report_id, type);
+
+	link_t *field_it;
+	
+	if(report_des == NULL){
+		return NULL;
+	}
+
+	if(field == NULL){
+		field_it = report_des->report_items.head.next;
+	}
+	else {
+		field_it = field->ritems_link.next;
+	}
+
+	while(field_it != &report_des->report_items.head) {
+		field = list_get_instance(field_it, usb_hid_report_field_t, 
+			ritems_link);
+
+		if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0) {
+			usb_hid_report_path_append_item (
+				field->collection_path, field->usage_page, 
+				field->usage);
+
+			if(usb_hid_report_compare_usage_path(
+				field->collection_path, path, flags) == EOK){
+
+				usb_hid_report_remove_last_item(
+					field->collection_path);
+
+				return field;
+			}
+			usb_hid_report_remove_last_item (
+				field->collection_path);
+		}
+		field_it = field_it->next;
+	}
+
+	return NULL;
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Returns next report_id of report of specified type. If zero is given than
+ * first report_id of specified type is returned (0 is not legal value for
+ * repotr_id)
+ *
+ * @param report_id Current report_id, 0 if there is no current report_id
+ * @param type Type of searched report
+ * @param report Report structure inwhich we search
+ * @retval 0 if report structure is null or there is no specified report
+ * @retval report_id otherwise
+ */
+uint8_t usb_hid_get_next_report_id(usb_hid_report_t *report, 
+	uint8_t report_id, usb_hid_report_type_t type)
+{
+	if(report == NULL){
+		return 0;
+	}
+
+	usb_hid_report_description_t *report_des;
+	link_t *report_it;
+	
+	if(report_id > 0) {
+		report_des = usb_hid_report_find_description(report, report_id, 
+			type);
+		if(report_des == NULL) {
+			return 0;
+		}
+		else {
+			report_it = report_des->reports_link.next;
+		}	
+	}
+	else {
+		report_it = report->reports.head.next;
+	}
+
+	while(report_it != &report->reports.head) {
+		report_des = list_get_instance(report_it, 
+			usb_hid_report_description_t, reports_link);
+
+		if(report_des->type == type){
+			return report_des->report_id;
+		}
+
+		report_it = report_it->next;
+	}
+
+	return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Reset all local items in given state table
+ *
+ * @param report_item State table containing current state of report
+ * descriptor parsing
+ *
+ * @return void
+ */
+void usb_hid_report_reset_local_items(usb_hid_report_item_t *report_item)
+{
+	if(report_item == NULL)	{
+		return;
+	}
+	
+	report_item->usages_count = 0;
+	memset(report_item->usages, 0, USB_HID_MAX_USAGES);
+	
+	report_item->extended_usage_page = 0;
+	report_item->usage_minimum = 0;
+	report_item->usage_maximum = 0;
+	report_item->designator_index = 0;
+	report_item->designator_minimum = 0;
+	report_item->designator_maximum = 0;
+	report_item->string_index = 0;
+	report_item->string_minimum = 0;
+	report_item->string_maximum = 0;
+
+	return;
+}
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/hidpath.c
===================================================================
--- uspace/lib/usbhid/src/hidpath.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/src/hidpath.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2011 Matej Klonfar
+ * 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 libusbhid
+ * @{
+ */
+/** @file
+ * HID report descriptor and report data parser implementation.
+ */
+#include <usb/hid/hidparser.h>
+#include <errno.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <mem.h>
+#include <usb/debug.h>
+#include <assert.h>
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Compares two usages if they are same or not or one of the usages is not
+ * set.
+ *
+ * @param usage1
+ * @param usage2
+ * @return boolean
+ */
+#define USB_HID_SAME_USAGE(usage1, usage2)		\
+	((usage1 == usage2) || (usage1 == 0) || (usage2 == 0))
+
+/**
+ * Compares two usage pages if they are same or not or one of them is not set.
+ *
+ * @param page1
+ * @param page2
+ * @return boolean
+ */
+#define USB_HID_SAME_USAGE_PAGE(page1, page2)	\
+	((page1 == page2) || (page1 == 0) || (page2 == 0))
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Appends one item (couple of usage_path and usage) into the usage path
+ * structure
+ *
+ * @param usage_path Usage path structure
+ * @param usage_page Usage page constant
+ * @param usage Usage constant
+ * @return Error code
+ */
+int usb_hid_report_path_append_item(usb_hid_report_path_t *usage_path, 
+                                    int32_t usage_page, int32_t usage)
+{	
+	usb_hid_report_usage_path_t *item;
+
+	if(!(item=malloc(sizeof(usb_hid_report_usage_path_t)))) {
+		return ENOMEM;
+	}
+	link_initialize(&item->rpath_items_link);
+
+	item->usage = usage;
+	item->usage_page = usage_page;
+	item->flags = 0;
+	
+	list_append (&item->rpath_items_link, &usage_path->items);
+	usage_path->depth++;
+	return EOK;
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Removes last item from the usage path structure
+ * @param usage_path 
+ * @return void
+ */
+void usb_hid_report_remove_last_item(usb_hid_report_path_t *usage_path)
+{
+	link_t *item_link;
+	usb_hid_report_usage_path_t *item;
+	
+	if(!list_empty(&usage_path->items)){
+		item_link = list_last(&usage_path->items);
+		item = list_get_instance(item_link,
+		    usb_hid_report_usage_path_t, rpath_items_link);
+		list_remove(item_link);
+		usage_path->depth--;
+		free(item);
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Nulls last item of the usage path structure.
+ *
+ * @param usage_path
+ * @return void
+ */
+void usb_hid_report_null_last_item(usb_hid_report_path_t *usage_path)
+{
+	usb_hid_report_usage_path_t *item;
+	
+	if(!list_empty(&usage_path->items)){
+		item = list_get_instance(list_last(&usage_path->items),
+			usb_hid_report_usage_path_t, rpath_items_link);
+
+		memset(item, 0, sizeof(usb_hid_report_usage_path_t));
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Modifies last item of usage path structure by given usage page or usage
+ *
+ * @param usage_path Opaque usage path structure
+ * @param tag Class of currently processed tag (Usage page tag falls into Global
+ * class but Usage tag into the Local)
+ * @param data Value of the processed tag
+ * @return void
+ */
+void usb_hid_report_set_last_item(usb_hid_report_path_t *usage_path, 
+                                  int32_t tag, int32_t data)
+{
+	usb_hid_report_usage_path_t *item;
+	
+	if(!list_empty(&usage_path->items)){
+		item = list_get_instance(list_last(&usage_path->items),
+		     usb_hid_report_usage_path_t, rpath_items_link);
+
+		switch(tag) {
+			case USB_HID_TAG_CLASS_GLOBAL:
+				item->usage_page = data;
+				break;
+			case USB_HID_TAG_CLASS_LOCAL:
+				item->usage = data;
+				break;
+		}
+	}
+	
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ *
+ *
+ *
+ *
+ */
+void usb_hid_print_usage_path(usb_hid_report_path_t *path)
+{
+	usb_log_debug("USAGE_PATH FOR RId(%d):\n", path->report_id);
+	usb_log_debug("\tLENGTH: %d\n", path->depth);
+
+	usb_hid_report_usage_path_t *path_item;
+
+	list_foreach(path->items, item) {
+		path_item = list_get_instance(item, usb_hid_report_usage_path_t,
+			rpath_items_link);
+
+		usb_log_debug("\tUSAGE_PAGE: %X\n", path_item->usage_page);
+		usb_log_debug("\tUSAGE: %X\n", path_item->usage);
+		usb_log_debug("\tFLAGS: %d\n", path_item->flags);
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Compares two usage paths structures
+ *
+ *
+ * @param report_path usage path structure to compare with @path 
+ * @param path usage patrh structure to compare
+ * @param flags Flags determining the mode of comparison
+ * @return EOK if both paths are identical, non zero number otherwise
+ */
+int usb_hid_report_compare_usage_path(usb_hid_report_path_t *report_path, 
+                                      usb_hid_report_path_t *path,
+                                      int flags)
+{
+	usb_hid_report_usage_path_t *report_item;
+	usb_hid_report_usage_path_t *path_item;
+
+	link_t *report_link;
+	link_t *path_link;
+
+	int only_page;
+
+	if(report_path->report_id != path->report_id) {
+		if(path->report_id != 0) {
+			return 1;
+		}
+	}
+
+	// Empty path match all others
+	if(path->depth == 0){
+		return EOK;
+	}
+
+
+	if((only_page = flags & USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY) != 0){
+		flags -= USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY;
+	}
+	
+	switch(flags){
+	/* path is somewhere in report_path */
+	case USB_HID_PATH_COMPARE_ANYWHERE:
+		if(path->depth != 1){
+			return 1;
+		}
+
+		path_link = list_first(&path->items);
+		path_item = list_get_instance(path_link,
+			usb_hid_report_usage_path_t, rpath_items_link);
+
+		list_foreach(report_path->items, report_link) {
+			report_item = list_get_instance(report_link,
+				usb_hid_report_usage_path_t, rpath_items_link);
+				
+			if(USB_HID_SAME_USAGE_PAGE(report_item->usage_page,
+				path_item->usage_page)){
+					
+				if(only_page == 0){
+					if(USB_HID_SAME_USAGE(
+						report_item->usage,
+						path_item->usage)) {
+							
+						return EOK;
+					}
+				}
+				else {
+					return EOK;
+				}
+			}
+		}
+
+		return 1;
+		break;
+
+	/* the paths must be identical */
+	case USB_HID_PATH_COMPARE_STRICT:
+		if(report_path->depth != path->depth){
+			return 1;
+		}
+		
+	/* path is prefix of the report_path */
+	case USB_HID_PATH_COMPARE_BEGIN:
+	
+		report_link = report_path->items.head.next;
+		path_link = path->items.head.next;
+			
+		while((report_link != &report_path->items.head) && 
+		      (path_link != &path->items.head)) {
+					  
+			report_item = list_get_instance(report_link, 
+				usb_hid_report_usage_path_t, rpath_items_link);
+					  
+			path_item = list_get_instance(path_link,
+       				usb_hid_report_usage_path_t, rpath_items_link);
+
+			if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page, 
+				path_item->usage_page) || ((only_page == 0) && 
+			    !USB_HID_SAME_USAGE(report_item->usage, 
+				path_item->usage))) {
+			
+				return 1;
+			} 
+			else {
+				report_link = report_link->next;
+				path_link = path_link->next;			
+			}
+			
+		}
+
+		if((((flags & USB_HID_PATH_COMPARE_BEGIN) != 0) && 
+			(path_link == &path->items.head)) || 
+		   ((report_link == &report_path->items.head) && 
+			(path_link == &path->items.head))) {
+				
+			return EOK;
+		}
+		else {
+			return 1;
+		}						
+		break;
+
+	/* path is suffix of report_path */
+	case USB_HID_PATH_COMPARE_END:
+
+		report_link = report_path->items.head.prev;
+		path_link = path->items.head.prev;
+
+		if(list_empty(&path->items)){
+			return EOK;
+		}
+			
+		while((report_link != &report_path->items.head) && 
+		      (path_link != &path->items.head)) {
+						  
+			report_item = list_get_instance(report_link,
+				usb_hid_report_usage_path_t, rpath_items_link);
+
+			path_item = list_get_instance(path_link, 
+				usb_hid_report_usage_path_t, rpath_items_link);
+						  
+			if(!USB_HID_SAME_USAGE_PAGE(report_item->usage_page, 
+				path_item->usage_page) || ((only_page == 0) && 
+			    !USB_HID_SAME_USAGE(report_item->usage, 
+				path_item->usage))) {
+						
+					return 1;
+			} else {
+				report_link = report_link->prev;
+				path_link = path_link->prev;			
+			}
+
+		}
+
+		if(path_link == &path->items.head) {
+			return EOK;
+		}
+		else {
+			return 1;
+		}						
+			
+		break;
+
+	default:
+		return EINVAL;
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Allocates and initializes new usage path structure.
+ *
+ * @return Initialized usage path structure
+ */
+usb_hid_report_path_t *usb_hid_report_path(void)
+{
+	usb_hid_report_path_t *path;
+	path = malloc(sizeof(usb_hid_report_path_t));
+	if(path == NULL){
+		return NULL;
+	}
+	else {
+		path->depth = 0;
+		path->report_id = 0;
+		link_initialize(&path->cpath_link);
+		list_initialize(&path->items);
+		return path;
+	}
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Releases given usage path structure.
+ *
+ * @param path usage path structure to release
+ * @return void
+ */
+void usb_hid_report_path_free(usb_hid_report_path_t *path)
+{
+	while(!list_empty(&path->items)){
+		usb_hid_report_remove_last_item(path);
+	}
+
+	assert_link_not_used(&path->cpath_link);
+	free(path);
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Clone content of given usage path to the new one
+ *
+ * @param usage_path Usage path structure to clone
+ * @return New copy of given usage path structure
+ */
+usb_hid_report_path_t *usb_hid_report_path_clone(
+	usb_hid_report_path_t *usage_path)
+{
+	usb_hid_report_usage_path_t *path_item;
+	usb_hid_report_usage_path_t *new_path_item;
+	usb_hid_report_path_t *new_usage_path = usb_hid_report_path ();
+
+	if(new_usage_path == NULL){
+		return NULL;
+	}
+
+	new_usage_path->report_id = usage_path->report_id;
+	
+	if(list_empty(&usage_path->items)){
+		return new_usage_path;
+	}
+
+	list_foreach(usage_path->items, path_link) {
+		path_item = list_get_instance(path_link,
+			usb_hid_report_usage_path_t, rpath_items_link);
+
+		new_path_item = malloc(sizeof(usb_hid_report_usage_path_t));
+		if(new_path_item == NULL) {
+			return NULL;
+		}
+		
+		link_initialize(&new_path_item->rpath_items_link);
+		new_path_item->usage_page = path_item->usage_page;
+		new_path_item->usage = path_item->usage;		
+		new_path_item->flags = path_item->flags;		
+		
+		list_append(&new_path_item->rpath_items_link,
+		    &new_usage_path->items);
+		new_usage_path->depth++;
+	}
+
+	return new_usage_path;
+}
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Sets report id in usage path structure
+ *
+ * @param path Usage path structure
+ * @param report_id Report id to set
+ * @return Error code
+ */
+int usb_hid_report_path_set_report_id(usb_hid_report_path_t *path, 
+	uint8_t report_id)
+{
+	if(path == NULL){
+		return EINVAL;
+	}
+
+	path->report_id = report_id;
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/hidreport.c
===================================================================
--- uspace/lib/usbhid/src/hidreport.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/src/hidreport.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 libusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB HID keyboard device structure and API.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/debug.h>
+#include <usb/hid/hidparser.h>
+#include <usb/dev/dp.h>
+#include <usb/dev/driver.h>
+#include <usb/dev/pipes.h>
+#include <usb/hid/hid.h>
+#include <usb/descriptor.h>
+#include <usb/dev/request.h>
+
+#include <usb/hid/hidreport.h>
+
+static int usb_hid_get_report_descriptor(usb_device_t *dev, 
+    uint8_t **report_desc, size_t *size)
+{
+	assert(report_desc != NULL);
+	assert(size != NULL);
+	
+	usb_dp_parser_t parser =  {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+	
+	usb_dp_parser_data_t parser_data = {
+		.data = dev->descriptors.configuration,
+		.size = dev->descriptors.configuration_size,
+		.arg = NULL
+	};
+	
+	/*
+	 * First nested descriptor of the configuration descriptor.
+	 */
+	uint8_t *d = 
+	    usb_dp_get_nested_descriptor(&parser, &parser_data, 
+	    dev->descriptors.configuration);
+	
+	/*
+	 * Find the interface descriptor corresponding to our interface number.
+	 */
+	int i = 0;
+	while (d != NULL && i < dev->interface_no) {
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		    dev->descriptors.configuration, d);
+		++i;
+	}
+	
+	if (d == NULL) {
+		usb_log_error("The %d. interface descriptor not found!\n",
+		    dev->interface_no);
+		return ENOENT;
+	}
+	
+	/*
+	 * First nested descriptor of the interface descriptor.
+	 */
+	uint8_t *iface_desc = d;
+	d = usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc);
+	
+	/*
+	 * Search through siblings until the HID descriptor is found.
+	 */
+	while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) {
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		    iface_desc, d);
+	}
+	
+	if (d == NULL) {
+		usb_log_fatal("No HID descriptor found!\n");
+		return ENOENT;
+	}
+	
+	if (*d != sizeof(usb_standard_hid_descriptor_t)) {
+		usb_log_error("HID descriptor has wrong size (%u, expected %zu"
+		    ")\n", *d, sizeof(usb_standard_hid_descriptor_t));
+		return EINVAL;
+	}
+	
+	usb_standard_hid_descriptor_t *hid_desc = 
+	    (usb_standard_hid_descriptor_t *)d;
+	
+	uint16_t length =  hid_desc->report_desc_info.length;
+	size_t actual_size = 0;
+
+	/*
+	 * Allocate space for the report descriptor.
+	 */
+	*report_desc = (uint8_t *)malloc(length);
+	if (*report_desc == NULL) {
+		usb_log_error("Failed to allocate space for Report descriptor."
+		    "\n");
+		return ENOMEM;
+	}
+	
+	usb_log_debug("Getting Report descriptor, expected size: %u\n", length);
+	
+	/*
+	 * Get the descriptor from the device.
+	 */
+	int rc = usb_request_get_descriptor(&dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DESCTYPE_HID_REPORT, 0, dev->interface_no,
+	    *report_desc, length, &actual_size);
+
+	if (rc != EOK) {
+		free(*report_desc);
+		*report_desc = NULL;
+		return rc;
+	}
+
+	if (actual_size != length) {
+		free(*report_desc);
+		*report_desc = NULL;
+		usb_log_error("Report descriptor has wrong size (%zu, expected "
+		    "%u)\n", actual_size, length);
+		return EINVAL;
+	}
+	
+	*size = length;
+	
+	usb_log_debug("Done.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int usb_hid_process_report_descriptor(usb_device_t *dev, 
+    usb_hid_report_t *report, uint8_t **report_desc, size_t *report_size)
+{
+	if (dev == NULL || report == NULL) {
+		usb_log_error("Failed to process Report descriptor: wrong "
+		    "parameters given.\n");
+		return EINVAL;
+	}
+	
+//	uint8_t *report_desc = NULL;
+//	size_t report_size;
+	
+	int rc = usb_hid_get_report_descriptor(dev, report_desc, report_size);
+	
+	if (rc != EOK) {
+		usb_log_error("Problem with getting Report descriptor: %s.\n",
+		    str_error(rc));
+		if (*report_desc != NULL) {
+			free(*report_desc);
+			*report_desc = NULL;
+		}
+		return rc;
+	}
+	
+	assert(*report_desc != NULL);
+	
+	rc = usb_hid_parse_report_descriptor(report, *report_desc, *report_size);
+	if (rc != EOK) {
+		usb_log_error("Problem parsing Report descriptor: %s.\n",
+		    str_error(rc));
+		free(*report_desc);
+		*report_desc = NULL;
+		return rc;
+	}
+	
+	usb_hid_descriptor_print(report);
+	
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhid/src/hidreq.c
===================================================================
--- uspace/lib/usbhid/src/hidreq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhid/src/hidreq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * 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 drvusbhid
+ * @{
+ */
+/** @file
+ * HID class-specific requests.
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/hid/hid.h>
+#include <usb/debug.h>
+#include <usb/dev/request.h>
+#include <usb/dev/pipes.h>
+
+#include <usb/hid/request.h>
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Set Report request to the HID device.
+ *
+ * @param hid_dev HID device to send the request to.
+ * @param type Type of the report.
+ * @param buffer Report data.
+ * @param buf_size Report data size (in bytes).
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from function usb_control_request_set().
+ */
+int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc;
+	
+	uint16_t value = 0;
+	value |= (type << 8);
+
+	usb_log_debug("Sending Set Report request to the device.\n");
+	
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending Set Report request to the "
+		    "device: %s.\n", str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Set Protocol request to the HID device.
+ *
+ * @param hid_dev HID device to send the request to.
+ * @param protocol Protocol to set.
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from function usb_control_request_set().
+ */
+int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
+    usb_hid_protocol_t protocol)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc;
+
+	usb_log_debug("Sending Set Protocol request to the device ("
+	    "protocol: %d, iface: %d).\n", protocol, iface_no);
+	
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending Set Protocol request to the "
+		    "device: %s.\n", str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Set Idle request to the HID device.
+ *
+ * @param hid_dev HID device to send the request to.
+ * @param duration Duration value (is multiplicated by 4 by the device to
+ *                 get real duration in miliseconds).
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from function usb_control_request_set().
+ */
+int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc;
+
+	usb_log_debug("Sending Set Idle request to the device ("
+	    "duration: %u, iface: %d).\n", duration, iface_no);
+	
+	uint16_t value = duration << 8;
+	
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending Set Idle request to the device: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Get Report request to the HID device.
+ *
+ * @param[in] hid_dev HID device to send the request to.
+ * @param[in] type Type of the report.
+ * @param[in][out] buffer Buffer for the report data.
+ * @param[in] buf_size Size of the buffer (in bytes).
+ * @param[out] actual_size Actual size of report received from the device 
+ *                         (in bytes).
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from function usb_control_request_set().
+ */
+int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size, 
+    size_t *actual_size)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc;
+
+	uint16_t value = 0;
+	value |= (type << 8);
+	
+	usb_log_debug("Sending Get Report request to the device.\n");
+	
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_REPORT, value, iface_no, buffer, buf_size,
+	    actual_size);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending Get Report request to the device: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Get Protocol request to the HID device.
+ *
+ * @param[in] hid_dev HID device to send the request to.
+ * @param[out] protocol Current protocol of the device.
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from function usb_control_request_set().
+ */
+int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t *protocol)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc;	
+
+	usb_log_debug("Sending Get Protocol request to the device ("
+	    "iface: %d).\n", iface_no);
+	
+	uint8_t buffer[1];
+	size_t actual_size = 0;
+	
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending Get Protocol request to the "
+		    "device: %s.\n", str_error(rc));
+		return rc;
+	}
+	
+	if (actual_size != 1) {
+		usb_log_warning("Wrong data size: %zu, expected: 1.\n",
+			actual_size);
+		return ELIMIT;
+	}
+	
+	*protocol = buffer[0];
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Send Get Idle request to the HID device.
+ *
+ * @param[in] hid_dev HID device to send the request to.
+ * @param[out] duration Duration value (multiplicate by 4 to get real duration
+ *                      in miliseconds).
+ *
+ * @retval EOK if successful.
+ * @retval EINVAL if no HID device is given.
+ * @return Other value inherited from one of functions 
+ *         usb_pipe_start_session(), usb_pipe_end_session(),
+ *         usb_control_request_set().
+ */
+int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc;
+
+	usb_log_debug("Sending Get Idle request to the device ("
+	    "iface: %d).\n", iface_no);
+	
+	uint16_t value = 0;
+	uint8_t buffer[1];
+	size_t actual_size = 0;
+	
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_IDLE, value, iface_no, buffer, 1, 
+	    &actual_size);
+
+	if (rc != EOK) {
+		usb_log_warning("Error sending Get Idle request to the device: "
+		    "%s.\n", str_error(rc));
+		return rc;
+	}
+	
+	if (actual_size != 1) {
+		usb_log_warning("Wrong data size: %zu, expected: 1.\n",
+			actual_size);
+		return ELIMIT;
+	}
+	
+	*duration = buffer[0];
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/Makefile
===================================================================
--- uspace/lib/usbhost/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+LIBRARY = libusbhost
+EXTRA_CFLAGS += \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include \
+	-Iinclude
+
+SOURCES = \
+	src/batch.c \
+	src/device_keeper.c \
+	src/endpoint.c \
+	src/usb_endpoint_manager.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usbhost/include/usb/host/batch.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/batch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/include/usb/host/batch.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,115 @@
+/*
+ * 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 libusbhost
+ * @{
+ */
+/** @file
+ * USB transfer transaction structures.
+ */
+#ifndef LIBUSBHOST_HOST_BATCH_H
+#define LIBUSBHOST_HOST_BATCH_H
+
+#include <adt/list.h>
+
+#include <usbhc_iface.h>
+#include <usb/usb.h>
+#include <usb/host/endpoint.h>
+
+typedef struct usb_transfer_batch usb_transfer_batch_t;
+struct usb_transfer_batch {
+	endpoint_t *ep;
+	link_t link;
+	usbhc_iface_transfer_in_callback_t callback_in;
+	usbhc_iface_transfer_out_callback_t callback_out;
+	void *arg;
+	char *buffer;
+	char *data_buffer;
+	size_t buffer_size;
+	char *setup_buffer;
+	size_t setup_size;
+	size_t transfered_size;
+	void (*next_step)(usb_transfer_batch_t *);
+	int error;
+	ddf_fun_t *fun;
+	void *private_data;
+	void (*private_data_dtor)(void *p_data);
+};
+
+/** Printf formatting string for dumping usb_transfer_batch_t. */
+#define USB_TRANSFER_BATCH_FMT "[%d:%d %s %s-%s %zuB/%zu]"
+
+/** Printf arguments for dumping usb_transfer_batch_t.
+ * @param batch USB transfer batch to be dumped.
+ */
+#define USB_TRANSFER_BATCH_ARGS(batch) \
+	(batch).ep->address, (batch).ep->endpoint, \
+	usb_str_speed((batch).ep->speed), \
+	usb_str_transfer_type_short((batch).ep->transfer_type), \
+	usb_str_direction((batch).ep->direction), \
+	(batch).buffer_size, (batch).ep->max_packet_size
+
+
+void usb_transfer_batch_init(
+    usb_transfer_batch_t *instance,
+    endpoint_t *ep,
+    char *buffer,
+    char *data_buffer,
+    size_t buffer_size,
+    char *setup_buffer,
+    size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out,
+    void *arg,
+    ddf_fun_t *fun,
+    void *private_data,
+    void (*private_data_dtor)(void *p_data)
+);
+
+void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance);
+void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance);
+void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
+void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
+
+static inline void usb_transfer_batch_finish_error(
+    usb_transfer_batch_t *instance, int error)
+{
+	assert(instance);
+	instance->error = error;
+	usb_transfer_batch_finish(instance);
+}
+
+static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
+{
+	assert(l);
+	return list_get_instance(l, usb_transfer_batch_t, link);
+}
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/device_keeper.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/include/usb/host/device_keeper.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,90 @@
+/*
+ * 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 libusbhost
+ * @{
+ */
+/** @file
+ * Device keeper structure and functions.
+ *
+ * Typical USB host controller needs to keep track of various settings for
+ * each device that is connected to it.
+ * State of toggle bit, device speed etc. etc.
+ * This structure shall simplify the management.
+ */
+#ifndef LIBUSBHOST_HOST_DEVICE_KEEPER_H
+#define LIBUSBHOST_HOST_DEVICE_KEEPER_H
+
+#include <adt/list.h>
+#include <devman.h>
+#include <fibril_synch.h>
+#include <usb/usb.h>
+#include <usb/host/endpoint.h>
+
+/** Number of USB address for array dimensions. */
+#define USB_ADDRESS_COUNT (USB11_ADDRESS_MAX + 1)
+
+/** Information about attached USB device. */
+struct usb_device_info {
+	usb_speed_t speed;
+	bool occupied;
+	devman_handle_t handle;
+};
+
+/** Host controller device keeper.
+ * You shall not access members directly but only using functions below.
+ */
+typedef struct {
+	struct usb_device_info devices[USB_ADDRESS_COUNT];
+	fibril_mutex_t guard;
+	usb_address_t last_address;
+} usb_device_keeper_t;
+
+void usb_device_keeper_init(usb_device_keeper_t *instance);
+
+usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
+    usb_speed_t speed);
+
+void usb_device_keeper_bind(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t handle);
+
+void usb_device_keeper_release(usb_device_keeper_t *instance,
+    usb_address_t address);
+
+usb_address_t usb_device_keeper_find(usb_device_keeper_t *instance,
+    devman_handle_t handle);
+
+bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t *handle);
+
+usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
+    usb_address_t address);
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/endpoint.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/include/usb/host/endpoint.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,86 @@
+/*
+ * 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 libusbhost
+ * @{
+ */
+/** @file
+ *
+ */
+#ifndef LIBUSBHOST_HOST_ENDPOINT_H
+#define LIBUSBHOST_HOST_ENDPOINT_H
+
+#include <assert.h>
+#include <bool.h>
+#include <adt/list.h>
+#include <fibril_synch.h>
+
+#include <usb/usb.h>
+
+typedef struct endpoint {
+	usb_address_t address;
+	usb_endpoint_t endpoint;
+	usb_direction_t direction;
+	usb_transfer_type_t transfer_type;
+	usb_speed_t speed;
+	size_t max_packet_size;
+	unsigned toggle:1;
+	fibril_mutex_t guard;
+	fibril_condvar_t avail;
+	volatile bool active;
+	struct {
+		void *data;
+		int (*toggle_get)(void *);
+		void (*toggle_set)(void *, int);
+	} hc_data;
+} endpoint_t;
+
+endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,
+    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
+    size_t max_packet_size);
+
+void endpoint_destroy(endpoint_t *instance);
+
+void endpoint_set_hc_data(endpoint_t *instance,
+    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
+
+void endpoint_clear_hc_data(endpoint_t *instance);
+
+void endpoint_use(endpoint_t *instance);
+
+void endpoint_release(endpoint_t *instance);
+
+int endpoint_toggle_get(endpoint_t *instance);
+
+void endpoint_toggle_set(endpoint_t *instance, int toggle);
+
+void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,100 @@
+/*
+ * 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 libusbhost
+ * @{
+ */
+/** @file
+ * Device keeper structure and functions.
+ *
+ * Typical USB host controller needs to keep track of various settings for
+ * each device that is connected to it.
+ * State of toggle bit, device speed etc. etc.
+ * This structure shall simplify the management.
+ */
+#ifndef LIBUSBHOST_HOST_USB_ENDPOINT_MANAGER_H
+#define LIBUSBHOST_HOST_YSB_ENDPOINT_MANAGER_H
+
+#include <stdlib.h>
+#include <adt/hash_table.h>
+#include <fibril_synch.h>
+#include <usb/usb.h>
+#include <usb/host/endpoint.h>
+
+#define BANDWIDTH_TOTAL_USB11 12000000
+#define BANDWIDTH_AVAILABLE_USB11 ((BANDWIDTH_TOTAL_USB11 / 10) * 9)
+
+typedef struct usb_endpoint_manager {
+	hash_table_t ep_table;
+	fibril_mutex_t guard;
+	fibril_condvar_t change;
+	size_t free_bw;
+} usb_endpoint_manager_t;
+
+size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type,
+    size_t size, size_t max_packet_size);
+
+int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
+    size_t available_bandwidth);
+
+void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance);
+
+int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
+    endpoint_t *ep, size_t data_size);
+
+int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction);
+
+endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,
+    size_t *bw);
+
+void usb_endpoint_manager_reset_if_need(
+    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
+
+static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
+    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
+    size_t data_size)
+{
+	endpoint_t *ep = endpoint_get(
+	    address, endpoint, direction, type, speed, max_packet_size);
+	if (!ep)
+		return ENOMEM;
+
+	const int ret =
+	    usb_endpoint_manager_register_ep(instance, ep, data_size);
+	if (ret != EOK) {
+		endpoint_destroy(ep);
+	}
+	return ret;
+}
+#endif
+/**
+ * @}
+ */
+
Index: uspace/lib/usbhost/src/batch.c
===================================================================
--- uspace/lib/usbhost/src/batch.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/src/batch.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,173 @@
+/*
+ * 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 libusbhost
+ * @{
+ */
+/** @file
+ * USB transfer transaction structures (implementation).
+ */
+#include <errno.h>
+#include <str_error.h>
+
+#include <usb/usb.h>
+#include <usb/debug.h>
+#include <usb/host/batch.h>
+
+void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
+void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
+
+void usb_transfer_batch_init(
+    usb_transfer_batch_t *instance,
+    endpoint_t *ep,
+    char *buffer,
+    char *data_buffer,
+    size_t buffer_size,
+    char *setup_buffer,
+    size_t setup_size,
+    usbhc_iface_transfer_in_callback_t func_in,
+    usbhc_iface_transfer_out_callback_t func_out,
+    void *arg,
+    ddf_fun_t *fun,
+    void *private_data,
+    void (*private_data_dtor)(void *p_data)
+    )
+{
+	assert(instance);
+	link_initialize(&instance->link);
+	instance->ep = ep;
+	instance->callback_in = func_in;
+	instance->callback_out = func_out;
+	instance->arg = arg;
+	instance->buffer = buffer;
+	instance->data_buffer = data_buffer;
+	instance->buffer_size = buffer_size;
+	instance->setup_buffer = setup_buffer;
+	instance->setup_size = setup_size;
+	instance->fun = fun;
+	instance->private_data = private_data;
+	instance->private_data_dtor = private_data_dtor;
+	instance->transfered_size = 0;
+	instance->next_step = NULL;
+	instance->error = EOK;
+	endpoint_use(instance->ep);
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function, calls callback and correctly destroys batch structure.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_transfer_batch_call_in(instance);
+	usb_transfer_batch_dispose(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Helper function calls callback and correctly destroys batch structure.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_transfer_batch_call_out(instance);
+	usb_transfer_batch_dispose(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Mark batch as finished and continue with next step.
+ *
+ * @param[in] instance Batch structure to use.
+ *
+ */
+void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	assert(instance->ep);
+	assert(instance->next_step);
+	endpoint_release(instance->ep);
+	instance->next_step(instance);
+}
+/*----------------------------------------------------------------------------*/
+/** Prepare data, get error status and call callback in.
+ *
+ * @param[in] instance Batch structure to use.
+ * Copies data from transport buffer, and calls callback with appropriate
+ * parameters.
+ */
+void usb_transfer_batch_call_in(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_in);
+	assert(instance->ep);
+
+	/* We are data in, we need data */
+	memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
+
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
+	    instance, USB_TRANSFER_BATCH_ARGS(*instance),
+	    instance->transfered_size, str_error(instance->error));
+
+	instance->callback_in(instance->fun, instance->error,
+	    instance->transfered_size, instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+/** Get error status and call callback out.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_call_out(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	assert(instance->callback_out);
+
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n",
+	    instance, USB_TRANSFER_BATCH_ARGS(*instance),
+	    str_error(instance->error));
+
+	instance->callback_out(instance->fun,
+	    instance->error, instance->arg);
+}
+/*----------------------------------------------------------------------------*/
+/** Correctly dispose all used data structures.
+ *
+ * @param[in] instance Batch structure to use.
+ */
+void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
+{
+	assert(instance);
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
+	    instance, USB_TRANSFER_BATCH_ARGS(*instance));
+	if (instance->private_data) {
+		assert(instance->private_data_dtor);
+		instance->private_data_dtor(instance->private_data);
+	}
+	free(instance);
+}
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/src/device_keeper.c
===================================================================
--- uspace/lib/usbhost/src/device_keeper.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/src/device_keeper.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,208 @@
+/*
+ * 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 libusbhost
+ * @{
+ */
+/** @file
+ * Device keeper structure and functions (implementation).
+ */
+#include <assert.h>
+#include <errno.h>
+#include <usb/debug.h>
+#include <usb/host/device_keeper.h>
+
+/*----------------------------------------------------------------------------*/
+/** Initialize device keeper structure.
+ *
+ * @param[in] instance Memory place to initialize.
+ *
+ * Set all values to false/0.
+ */
+void usb_device_keeper_init(usb_device_keeper_t *instance)
+{
+	assert(instance);
+	unsigned i = 0;
+	for (; i < USB_ADDRESS_COUNT; ++i) {
+		instance->devices[i].occupied = false;
+		instance->devices[i].handle = 0;
+		instance->devices[i].speed = USB_SPEED_MAX;
+	}
+	// TODO: is this hack enough?
+	// (it is needed to allow smooth registration at default address)
+	instance->devices[0].occupied = true;
+	instance->last_address = 0;
+	fibril_mutex_initialize(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Get a free USB address
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] speed Speed of the device requiring address.
+ * @return Free address, or error code.
+ */
+usb_address_t device_keeper_get_free_address(
+    usb_device_keeper_t *instance, usb_speed_t speed)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+
+	usb_address_t new_address = instance->last_address;
+	do {
+		++new_address;
+		if (new_address > USB11_ADDRESS_MAX)
+			new_address = 1;
+		if (new_address == instance->last_address) {
+			fibril_mutex_unlock(&instance->guard);
+			return ENOSPC;
+		}
+	} while (instance->devices[new_address].occupied);
+
+	assert(new_address != USB_ADDRESS_DEFAULT);
+	assert(instance->devices[new_address].occupied == false);
+
+	instance->devices[new_address].occupied = true;
+	instance->devices[new_address].speed = speed;
+	instance->last_address = new_address;
+
+	fibril_mutex_unlock(&instance->guard);
+	return new_address;
+}
+/*----------------------------------------------------------------------------*/
+/** Bind USB address to devman handle.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Device address
+ * @param[in] handle Devman handle of the device.
+ */
+void usb_device_keeper_bind(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+
+	assert(address > 0);
+	assert(address <= USB11_ADDRESS_MAX);
+	assert(instance->devices[address].occupied);
+
+	instance->devices[address].handle = handle;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Release used USB address.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Device address
+ */
+void usb_device_keeper_release(
+    usb_device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address > 0);
+	assert(address <= USB11_ADDRESS_MAX);
+
+	fibril_mutex_lock(&instance->guard);
+	assert(instance->devices[address].occupied);
+
+	instance->devices[address].occupied = false;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+/** Find USB address associated with the device
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] handle Devman handle of the device seeking its address.
+ * @return USB Address, or error code.
+ */
+usb_address_t usb_device_keeper_find(
+    usb_device_keeper_t *instance, devman_handle_t handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	usb_address_t address = 1;
+	while (address <= USB11_ADDRESS_MAX) {
+		if (instance->devices[address].handle == handle) {
+			assert(instance->devices[address].occupied);
+			fibril_mutex_unlock(&instance->guard);
+			return address;
+		}
+		++address;
+	}
+	fibril_mutex_unlock(&instance->guard);
+	return ENOENT;
+}
+
+/** Find devman handle assigned to USB address.
+ * Intentionally refuse to find handle of default address.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Address the caller wants to find.
+ * @param[out] handle Where to store found handle.
+ * @return Whether such address is currently occupied.
+ */
+bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t *handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
+		fibril_mutex_unlock(&instance->guard);
+		return false;
+	}
+	if (!instance->devices[address].occupied) {
+		fibril_mutex_unlock(&instance->guard);
+		return false;
+	}
+
+	if (handle != NULL) {
+		*handle = instance->devices[address].handle;
+	}
+
+	fibril_mutex_unlock(&instance->guard);
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+/** Get speed associated with the address
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Address of the device.
+ * @return USB speed.
+ */
+usb_speed_t usb_device_keeper_get_speed(
+    usb_device_keeper_t *instance, usb_address_t address)
+{
+	assert(instance);
+	assert(address >= 0);
+	assert(address <= USB11_ADDRESS_MAX);
+
+	return instance->devices[address].speed;
+}
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/src/endpoint.c
===================================================================
--- uspace/lib/usbhost/src/endpoint.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/src/endpoint.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,132 @@
+/*
+ * 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 drvusbuhcihc
+ * @{
+ */
+/** @file
+ * @brief UHCI host controller driver structure
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <usb/host/endpoint.h>
+
+endpoint_t * endpoint_get(usb_address_t address, usb_endpoint_t endpoint,
+    usb_direction_t direction, usb_transfer_type_t type, usb_speed_t speed,
+    size_t max_packet_size)
+{
+	endpoint_t *instance = malloc(sizeof(endpoint_t));
+	if (instance) {
+		instance->address = address;
+		instance->endpoint = endpoint;
+		instance->direction = direction;
+		instance->transfer_type = type;
+		instance->speed = speed;
+		instance->max_packet_size = max_packet_size;
+		instance->toggle = 0;
+		instance->active = false;
+		fibril_mutex_initialize(&instance->guard);
+		fibril_condvar_initialize(&instance->avail);
+		endpoint_clear_hc_data(instance);
+	}
+	return instance;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_destroy(endpoint_t *instance)
+{
+	assert(instance);
+	assert(!instance->active);
+	free(instance);
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_set_hc_data(endpoint_t *instance,
+    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
+{
+	assert(instance);
+	instance->hc_data.data = data;
+	instance->hc_data.toggle_get = toggle_get;
+	instance->hc_data.toggle_set = toggle_set;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_clear_hc_data(endpoint_t *instance)
+{
+	assert(instance);
+	instance->hc_data.data = NULL;
+	instance->hc_data.toggle_get = NULL;
+	instance->hc_data.toggle_set = NULL;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_use(endpoint_t *instance)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	while (instance->active)
+		fibril_condvar_wait(&instance->avail, &instance->guard);
+	instance->active = true;
+	fibril_mutex_unlock(&instance->guard);
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_release(endpoint_t *instance)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	instance->active = false;
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_signal(&instance->avail);
+}
+/*----------------------------------------------------------------------------*/
+int endpoint_toggle_get(endpoint_t *instance)
+{
+	assert(instance);
+	if (instance->hc_data.toggle_get)
+		instance->toggle =
+		    instance->hc_data.toggle_get(instance->hc_data.data);
+	return (int)instance->toggle;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_toggle_set(endpoint_t *instance, int toggle)
+{
+	assert(instance);
+	assert(toggle == 0 || toggle == 1);
+	if (instance->hc_data.toggle_set)
+		instance->hc_data.toggle_set(instance->hc_data.data, toggle);
+	instance->toggle = toggle;
+}
+/*----------------------------------------------------------------------------*/
+void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
+{
+	assert(instance);
+	if (instance->address == target.address &&
+	    (instance->endpoint == target.endpoint || target.endpoint == 0))
+		endpoint_toggle_set(instance, 0);
+}
+/**
+ * @}
+ */
Index: uspace/lib/usbhost/src/usb_endpoint_manager.c
===================================================================
--- uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbhost/src/usb_endpoint_manager.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2011 Jan Vesely
+ * All rights eps.
+ *
+ * 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 <bool.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <usb/debug.h>
+#include <usb/host/usb_endpoint_manager.h>
+
+#define BUCKET_COUNT 7
+
+#define MAX_KEYS (3)
+typedef struct {
+	link_t link;
+	size_t bw;
+	endpoint_t *ep;
+} node_t;
+/*----------------------------------------------------------------------------*/
+static hash_index_t node_hash(unsigned long key[])
+{
+	hash_index_t hash = 0;
+	unsigned i = 0;
+	for (;i < MAX_KEYS; ++i) {
+		hash ^= key[i];
+	}
+	hash %= BUCKET_COUNT;
+	return hash;
+}
+/*----------------------------------------------------------------------------*/
+static int node_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	assert(item);
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	assert(node);
+	assert(node->ep);
+	bool match = true;
+	switch (keys) {
+	case 3:
+		match = match && (key[2] == node->ep->direction);
+	case 2:
+		match = match && (key[1] == (unsigned long)node->ep->endpoint);
+	case 1:
+		match = match && (key[0] == (unsigned long)node->ep->address);
+		break;
+	default:
+		match = false;
+	}
+	return match;
+}
+/*----------------------------------------------------------------------------*/
+static void node_remove(link_t *item)
+{
+	assert(item);
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	endpoint_destroy(node->ep);
+	free(node);
+}
+/*----------------------------------------------------------------------------*/
+static void node_toggle_reset_filtered(link_t *item, void *arg)
+{
+	assert(item);
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	usb_target_t *target = arg;
+	endpoint_toggle_reset_filtered(node->ep, *target);
+}
+/*----------------------------------------------------------------------------*/
+static hash_table_operations_t op = {
+	.hash = node_hash,
+	.compare = node_compare,
+	.remove_callback = node_remove,
+};
+/*----------------------------------------------------------------------------*/
+size_t bandwidth_count_usb11(usb_speed_t speed, usb_transfer_type_t type,
+    size_t size, size_t max_packet_size)
+{
+	/* We care about bandwidth only for interrupt and isochronous. */
+	if ((type != USB_TRANSFER_INTERRUPT)
+	    && (type != USB_TRANSFER_ISOCHRONOUS)) {
+		return 0;
+	}
+
+	const unsigned packet_count =
+	    (size + max_packet_size - 1) / max_packet_size;
+	/* TODO: It may be that ISO and INT transfers use only one data packet
+	 * per transaction, but I did not find text in UB spec that confirms
+	 * this */
+	/* NOTE: All data packets will be considered to be max_packet_size */
+	switch (speed)
+	{
+	case USB_SPEED_LOW:
+		assert(type == USB_TRANSFER_INTERRUPT);
+		/* Protocol overhead 13B
+		 * (3 SYNC bytes, 3 PID bytes, 2 Endpoint + CRC bytes, 2
+		 * CRC bytes, and a 3-byte interpacket delay)
+		 * see USB spec page 45-46. */
+		/* Speed penalty 8: low speed is 8-times slower*/
+		return packet_count * (13 + max_packet_size) * 8;
+	case USB_SPEED_FULL:
+		/* Interrupt transfer overhead see above
+		 * or page 45 of USB spec */
+		if (type == USB_TRANSFER_INTERRUPT)
+			return packet_count * (13 + max_packet_size);
+
+		assert(type == USB_TRANSFER_ISOCHRONOUS);
+		/* Protocol overhead 9B
+		 * (2 SYNC bytes, 2 PID bytes, 2 Endpoint + CRC bytes, 2 CRC
+		 * bytes, and a 1-byte interpacket delay)
+		 * see USB spec page 42 */
+		return packet_count * (9 + max_packet_size);
+	default:
+		return 0;
+	}
+}
+/*----------------------------------------------------------------------------*/
+int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
+    size_t available_bandwidth)
+{
+	assert(instance);
+	fibril_mutex_initialize(&instance->guard);
+	fibril_condvar_initialize(&instance->change);
+	instance->free_bw = available_bandwidth;
+	bool ht =
+	    hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op);
+	return ht ? EOK : ENOMEM;
+}
+/*----------------------------------------------------------------------------*/
+void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance)
+{
+	hash_table_destroy(&instance->ep_table);
+}
+/*----------------------------------------------------------------------------*/
+int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
+    endpoint_t *ep, size_t data_size)
+{
+	assert(ep);
+	size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
+	    data_size, ep->max_packet_size);
+	assert(instance);
+
+	unsigned long key[MAX_KEYS] =
+	    {ep->address, ep->endpoint, ep->direction};
+	fibril_mutex_lock(&instance->guard);
+
+	link_t *item =
+	    hash_table_find(&instance->ep_table, key);
+	if (item != NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return EEXISTS;
+	}
+
+	if (bw > instance->free_bw) {
+		fibril_mutex_unlock(&instance->guard);
+		return ENOSPC;
+	}
+
+	node_t *node = malloc(sizeof(node_t));
+	if (node == NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return ENOMEM;
+	}
+
+	node->bw = bw;
+	node->ep = ep;
+	link_initialize(&node->link);
+
+	hash_table_insert(&instance->ep_table, key, &node->link);
+	instance->free_bw -= bw;
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_broadcast(&instance->change);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
+{
+	assert(instance);
+	unsigned long key[MAX_KEYS] = {address, endpoint, direction};
+
+	fibril_mutex_lock(&instance->guard);
+	link_t *item = hash_table_find(&instance->ep_table, key);
+	if (item == NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return EINVAL;
+	}
+
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	if (node->ep->active)
+		return EBUSY;
+
+	instance->free_bw += node->bw;
+	hash_table_remove(&instance->ep_table, key, MAX_KEYS);
+
+	fibril_mutex_unlock(&instance->guard);
+	fibril_condvar_broadcast(&instance->change);
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance,
+    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
+    size_t *bw)
+{
+	assert(instance);
+	unsigned long key[MAX_KEYS] = {address, endpoint, direction};
+
+	fibril_mutex_lock(&instance->guard);
+	link_t *item = hash_table_find(&instance->ep_table, key);
+	if (item == NULL) {
+		fibril_mutex_unlock(&instance->guard);
+		return NULL;
+	}
+	node_t *node = hash_table_get_instance(item, node_t, link);
+	if (bw)
+		*bw = node->bw;
+
+	fibril_mutex_unlock(&instance->guard);
+	return node->ep;
+}
+/*----------------------------------------------------------------------------*/
+/** Check setup packet data for signs of toggle reset.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] target Device to receive setup packet.
+ * @param[in] data Setup packet data.
+ *
+ * Really ugly one.
+ */
+void usb_endpoint_manager_reset_if_need(
+    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)
+{
+	assert(instance);
+	if (target.endpoint > 15 || target.endpoint < 0
+	    || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
+		usb_log_error("Invalid data when checking for toggle reset.\n");
+		return;
+	}
+
+	switch (data[1])
+	{
+	case 0x01: /*clear feature*/
+		/* recipient is endpoint, value is zero (ENDPOINT_STALL) */
+		if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
+			/* endpoint number is < 16, thus first byte is enough */
+			usb_target_t reset_target =
+			    { .address = target.address, data[4] };
+			fibril_mutex_lock(&instance->guard);
+			hash_table_apply(&instance->ep_table,
+			    node_toggle_reset_filtered, &reset_target);
+			fibril_mutex_unlock(&instance->guard);
+		}
+	break;
+
+	case 0x9: /* set configuration */
+	case 0x11: /* set interface */
+		/* target must be device */
+		if ((data[0] & 0xf) == 0) {
+			usb_target_t reset_target =
+			    { .address = target.address, 0 };
+			fibril_mutex_lock(&instance->guard);
+			hash_table_apply(&instance->ep_table,
+			    node_toggle_reset_filtered, &reset_target);
+			fibril_mutex_unlock(&instance->guard);
+		}
+	break;
+	}
+}
Index: uspace/lib/usbvirt/Makefile
===================================================================
--- uspace/lib/usbvirt/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2011 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.
+#
+
+USPACE_PREFIX = ../..
+LIBRARY = libusbvirt
+
+EXTRA_CFLAGS = \
+	-I$(LIBDRV_PREFIX)/include \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-Iinclude
+
+SOURCES = \
+	src/ctrltransfer.c \
+	src/device.c \
+	src/ipc_dev.c \
+	src/ipc_hc.c \
+	src/stdreq.c \
+	src/transfer.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usbvirt/include/usbvirt/device.h
===================================================================
--- uspace/lib/usbvirt/include/usbvirt/device.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/include/usbvirt/device.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * Virtual USB device.
+ */
+
+#ifndef LIBUSBVIRT_DEVICE_H_
+#define LIBUSBVIRT_DEVICE_H_
+
+#include <usb/usb.h>
+#include <usb/dev/request.h>
+#include <async.h>
+
+/** Maximum number of endpoints supported by virtual USB. */
+#define USBVIRT_ENDPOINT_MAX 16
+
+typedef struct usbvirt_device usbvirt_device_t;
+
+/** Callback for data to device (OUT transaction).
+ *
+ * @param dev Virtual device to which the transaction belongs.
+ * @param endpoint Target endpoint number.
+ * @param transfer_type Transfer type.
+ * @param buffer Data buffer.
+ * @param buffer_size Size of the buffer in bytes.
+ * @return Error code.
+ */
+typedef int (*usbvirt_on_data_to_device_t)(usbvirt_device_t *dev,
+    usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
+    void *buffer, size_t buffer_size);
+
+/** Callback for data from device (IN transaction).
+ *
+ * @param dev Virtual device to which the transaction belongs.
+ * @param endpoint Target endpoint number.
+ * @param transfer_type Transfer type.
+ * @param buffer Data buffer to write answer to.
+ * @param buffer_size Size of the buffer in bytes.
+ * @param act_buffer_size Write here how many bytes were actually written.
+ * @return Error code.
+ */
+typedef int (*usbvirt_on_data_from_device_t)(usbvirt_device_t *dev,
+    usb_endpoint_t endpoint, usb_transfer_type_t transfer_type,
+    void *buffer, size_t buffer_size, size_t *act_buffer_size);
+
+/** Callback for control transfer on endpoint zero.
+ *
+ * Notice that size of the data buffer is expected to be read from the
+ * setup packet.
+ *
+ * @param dev Virtual device to which the transaction belongs.
+ * @param setup_packet Standard setup packet.
+ * @param data Data (might be NULL).
+ * @param act_data_size Size of returned data in bytes.
+ * @return Error code.
+ */
+typedef int (*usbvirt_on_control_t)(usbvirt_device_t *dev,
+    const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_data_size);
+
+/** Callback for control request on a virtual USB device.
+ *
+ * See usbvirt_control_reply_helper() for simple way of answering
+ * control read requests.
+ */
+typedef struct {
+	/** Request direction (in or out). */
+	usb_direction_t req_direction;
+	/** Request recipient (device, interface or endpoint). */
+	usb_request_recipient_t req_recipient;
+	/** Request type (standard, class or vendor). */
+	usb_request_type_t req_type;
+	/** Actual request code. */
+	uint8_t request;
+	/** Request handler name for debugging purposes. */
+	const char *name;
+	/** Callback to be executed on matching request. */
+	usbvirt_on_control_t callback;
+} usbvirt_control_request_handler_t;
+
+/** Extra configuration data for GET_CONFIGURATION request. */
+typedef struct {
+	/** Actual data. */
+	uint8_t *data;
+	/** Data length. */
+	size_t length;
+} usbvirt_device_configuration_extras_t;
+
+/** Single device configuration. */
+typedef struct {
+	/** Standard configuration descriptor. */
+	usb_standard_configuration_descriptor_t *descriptor;
+	/** Array of extra data. */
+	usbvirt_device_configuration_extras_t *extra;
+	/** Length of @c extra array. */
+	size_t extra_count;
+} usbvirt_device_configuration_t;
+
+/** Standard USB descriptors for virtual device. */
+typedef struct {
+	/** Standard device descriptor.
+	 * There is always only one such descriptor for the device.
+	 */
+	usb_standard_device_descriptor_t *device;
+
+	/** Configurations. */
+	usbvirt_device_configuration_t *configuration;
+	/** Number of configurations. */
+	size_t configuration_count;
+} usbvirt_descriptors_t;
+
+/** Possible states of virtual USB device.
+ * Notice that these are not 1:1 mappings to those in USB specification.
+ */
+typedef enum {
+	/** Default state, device listens at default address. */
+	USBVIRT_STATE_DEFAULT,
+	/** Device has non-default address assigned. */
+	USBVIRT_STATE_ADDRESS,
+	/** Device is configured. */
+	USBVIRT_STATE_CONFIGURED
+} usbvirt_device_state_t;
+
+/** Ops structure for virtual USB device. */
+typedef struct {
+	/** Callbacks for data to device.
+	 * Index zero is ignored.
+	 */
+	usbvirt_on_data_to_device_t data_out[USBVIRT_ENDPOINT_MAX];
+	/** Callbacks for data from device.
+	 * Index zero is ignored.
+	 */
+	usbvirt_on_data_from_device_t data_in[USBVIRT_ENDPOINT_MAX];
+	/** Array of control handlers.
+	 * Last handler is expected to have the @c callback field set to NULL
+	 */
+	usbvirt_control_request_handler_t *control;
+	/** Callback when device changes state.
+	 *
+	 * The value of @c state attribute of @p dev device is not
+	 * defined during call of this function.
+	 *
+	 * @param dev The virtual USB device.
+	 * @param old_state Old device state.
+	 * @param new_state New device state.
+	 */
+	void (*state_changed)(usbvirt_device_t *dev,
+	    usbvirt_device_state_t old_state, usbvirt_device_state_t new_state);
+} usbvirt_device_ops_t;
+
+/** Virtual USB device. */
+struct usbvirt_device {
+	/** Name for debugging purposes. */
+	const char *name;
+	/** Custom device data. */
+	void *device_data;
+	/** Device ops. */
+	usbvirt_device_ops_t *ops;
+	/** Device descriptors. */
+	usbvirt_descriptors_t *descriptors;
+	/** Current device address.
+	 * You shall treat this field as read only in your code.
+	 */
+	usb_address_t address;
+	/** Current device state.
+	 * You shall treat this field as read only in your code.
+	 */
+	usbvirt_device_state_t state;
+	/** Session to the host controller.
+	 * You shall treat this field as read only in your code.
+	 */
+	async_sess_t *vhc_sess;
+};
+
+int usbvirt_device_plug(usbvirt_device_t *, const char *);
+void usbvirt_device_unplug(usbvirt_device_t *);
+
+void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *,
+    uint8_t *, size_t *, void *, size_t);
+
+int usbvirt_control_write(usbvirt_device_t *, void *, size_t, void *, size_t);
+int usbvirt_control_read(usbvirt_device_t *, void *, size_t, void *, size_t, size_t *);
+int usbvirt_data_out(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t,
+    void *, size_t);
+int usbvirt_data_in(usbvirt_device_t *, usb_transfer_type_t, usb_endpoint_t,
+    void *, size_t, size_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/include/usbvirt/ipc.h
===================================================================
--- uspace/lib/usbvirt/include/usbvirt/ipc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/include/usbvirt/ipc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * IPC wrappers for virtual USB.
+ */
+
+#ifndef LIBUSBVIRT_IPC_H_
+#define LIBUSBVIRT_IPC_H_
+
+#include <ipc/common.h>
+#include <usb/usb.h>
+#include <bool.h>
+#include <usbvirt/device.h>
+#include <async.h>
+
+/** IPC methods communication between host controller and virtual device. */
+typedef enum {
+	IPC_M_USBVIRT_GET_NAME = IPC_FIRST_USER_METHOD + 80,
+	IPC_M_USBVIRT_CONTROL_READ,
+	IPC_M_USBVIRT_CONTROL_WRITE,
+	IPC_M_USBVIRT_INTERRUPT_IN,
+	IPC_M_USBVIRT_INTERRUPT_OUT,
+	IPC_M_USBVIRT_BULK_IN,
+	IPC_M_USBVIRT_BULK_OUT
+} usbvirt_hc_to_device_method_t;
+
+extern int usbvirt_ipc_send_control_read(async_sess_t *, void *, size_t,
+    void *, size_t, size_t *);
+extern int usbvirt_ipc_send_control_write(async_sess_t *, void *, size_t,
+    void *, size_t);
+extern int usbvirt_ipc_send_data_in(async_sess_t *, usb_endpoint_t,
+    usb_transfer_type_t, void *, size_t, size_t *);
+extern int usbvirt_ipc_send_data_out(async_sess_t *, usb_endpoint_t,
+    usb_transfer_type_t, void *, size_t);
+
+extern bool usbvirt_is_usbvirt_method(sysarg_t);
+extern bool usbvirt_ipc_handle_call(usbvirt_device_t *, ipc_callid_t,
+    ipc_call_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/ctrltransfer.c
===================================================================
--- uspace/lib/usbvirt/src/ctrltransfer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/src/ctrltransfer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * Control transfer handling.
+ */
+#include "private.h"
+#include <usb/dev/request.h>
+#include <usb/debug.h>
+#include <assert.h>
+#include <errno.h>
+
+/** Find and execute control transfer handler for virtual USB device.
+ *
+ * @param dev Target virtual device.
+ * @param control_handlers Array of control request handlers.
+ * @param setup Setup packet.
+ * @param data Extra data.
+ * @param data_sent_size Size of extra data in bytes.
+ * @return Error code.
+ * @retval EFORWARD No suitable handler found.
+ */
+int process_control_transfer(usbvirt_device_t *dev,
+    usbvirt_control_request_handler_t *control_handlers,
+    usb_device_request_setup_packet_t *setup,
+    uint8_t *data, size_t *data_sent_size)
+{
+	assert(dev);
+	assert(setup);
+
+	if (control_handlers == NULL) {
+		return EFORWARD;
+	}
+
+	usb_direction_t direction = setup->request_type & 128 ?
+	    USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	usb_request_recipient_t req_recipient = setup->request_type & 31;
+	usb_request_type_t req_type = (setup->request_type >> 5) & 3;
+
+	usbvirt_control_request_handler_t *handler = control_handlers;
+	while (handler->callback != NULL) {
+		if (handler->req_direction != direction) {
+			goto next;
+		}
+		if (handler->req_recipient != req_recipient) {
+			goto next;
+		}
+		if (handler->req_type != req_type) {
+			goto next;
+		}
+		if (handler->request != setup->request) {
+			goto next;
+		}
+
+		usb_log_debug("Control transfer: %s(%s)\n", handler->name,
+		    usb_debug_str_buffer((uint8_t*) setup, sizeof(*setup), 0));
+		int rc = handler->callback(dev, setup, data, data_sent_size);
+		if (rc == EFORWARD) {
+			goto next;
+		}
+
+		return rc;
+
+next:
+		handler++;
+	}
+
+	return EFORWARD;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/device.c
===================================================================
--- uspace/lib/usbvirt/src/device.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/src/device.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * Virtual USB device main routines.
+ */
+#include <errno.h>
+#include <str.h>
+#include <stdio.h>
+#include <assert.h>
+#include <async.h>
+#include <devman.h>
+#include <usbvirt/device.h>
+#include <usbvirt/ipc.h>
+
+#include <usb/debug.h>
+
+/** Current device. */
+static usbvirt_device_t *DEV = NULL;
+
+/** Main IPC call handling from virtual host controller.
+ *
+ * @param iid   Caller identification
+ * @param icall Initial incoming call
+ * @param arg   Local argument
+ */
+static void callback_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	assert(DEV != NULL);
+
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_callid_t callid;
+		ipc_call_t call;
+
+		callid = async_get_call(&call);
+		bool processed = usbvirt_ipc_handle_call(DEV, callid, &call);
+		if (!processed) {
+			if (!IPC_GET_IMETHOD(call)) {
+				async_answer_0(callid, EOK);
+				return;
+			} else
+				async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+/** Connect the device to the virtual host controller.
+ *
+ * @param dev The virtual device to be (virtually) plugged in.
+ * @param vhc_path Devman path to the virtual host controller.
+ * @return Error code.
+ */
+int usbvirt_device_plug(usbvirt_device_t *dev, const char *vhc_path)
+{
+	if (DEV != NULL)
+		return ELIMIT;
+	
+	devman_handle_t handle;
+	int rc = devman_fun_get_handle(vhc_path, &handle, 0);
+	if (rc != EOK)
+		return rc;
+	
+	async_sess_t *hcd_sess =
+	    devman_device_connect(EXCHANGE_SERIALIZE, handle, 0);
+	if (!hcd_sess)
+		return ENOMEM;
+	
+	DEV = dev;
+	dev->vhc_sess = hcd_sess;
+	
+	async_exch_t *exch = async_exchange_begin(hcd_sess);
+	rc = async_connect_to_me(exch, 0, 0, 0, callback_connection, NULL);
+	async_exchange_end(exch);
+	
+	if (rc != EOK)
+		DEV = NULL;
+	
+	return rc;
+}
+
+/** Disconnect the device from virtual host controller.
+ *
+ * @param dev Device to be disconnected.
+ */
+void usbvirt_device_unplug(usbvirt_device_t *dev)
+{
+	async_hangup(dev->vhc_sess);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/ipc_dev.c
===================================================================
--- uspace/lib/usbvirt/src/ipc_dev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/src/ipc_dev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * IPC wrappers, device side.
+ */
+#include <errno.h>
+#include <str.h>
+#include <stdio.h>
+#include <assert.h>
+#include <async.h>
+#include <devman.h>
+#include <usbvirt/device.h>
+#include <usbvirt/ipc.h>
+#include <usb/debug.h>
+
+/** Handle VHC request for device name.
+ *
+ * @param dev Target virtual device.
+ * @param iid Caller id.
+ * @param icall The call with the request.
+ */
+static void ipc_get_name(usbvirt_device_t *dev,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	if (dev->name == NULL) {
+		async_answer_0(iid, ENOENT);
+	}
+
+	size_t size = str_size(dev->name);
+
+	ipc_callid_t callid;
+	size_t accepted_size;
+	if (!async_data_read_receive(&callid, &accepted_size)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	if (accepted_size > size) {
+		accepted_size = size;
+	}
+	async_data_read_finalize(callid, dev->name, accepted_size);
+
+	async_answer_1(iid, EOK, accepted_size);
+}
+
+/** Handle VHC request for control read from the device.
+ *
+ * @param dev Target virtual device.
+ * @param iid Caller id.
+ * @param icall The call with the request.
+ */
+static void ipc_control_read(usbvirt_device_t *dev,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	int rc;
+
+	void *setup_packet = NULL;
+	size_t setup_packet_len = 0;
+	size_t data_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, 1024, 0, &setup_packet_len);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EPARTY);
+		free(setup_packet);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(iid, ENOMEM);
+		free(setup_packet);
+		return;
+	}
+
+	size_t actual_len;
+	rc = usbvirt_control_read(dev, setup_packet, setup_packet_len,
+	    buffer, data_len, &actual_len);
+
+	if (rc != EOK) {
+		async_answer_0(data_callid, rc);
+		async_answer_0(iid, rc);
+		free(setup_packet);
+		free(buffer);
+		return;
+	}
+
+	async_data_read_finalize(data_callid, buffer, actual_len);
+	async_answer_0(iid, EOK);
+
+	free(setup_packet);
+	free(buffer);
+}
+
+/** Handle VHC request for control write to the device.
+ *
+ * @param dev Target virtual device.
+ * @param iid Caller id.
+ * @param icall The call with the request.
+ */
+static void ipc_control_write(usbvirt_device_t *dev,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	size_t data_buffer_len = IPC_GET_ARG1(*icall);
+	int rc;
+
+	void *setup_packet = NULL;
+	void *data_buffer = NULL;
+	size_t setup_packet_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, 0, 0, &setup_packet_len);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	if (data_buffer_len > 0) {
+		rc = async_data_write_accept(&data_buffer, false,
+		    1, 0, 0, &data_buffer_len);
+		if (rc != EOK) {
+			async_answer_0(iid, rc);
+			free(setup_packet);
+			return;
+		}
+	}
+
+	rc = usbvirt_control_write(dev, setup_packet, setup_packet_len,
+	    data_buffer, data_buffer_len);
+
+	async_answer_0(iid, rc);
+
+	free(setup_packet);
+	if (data_buffer != NULL) {
+		free(data_buffer);
+	}
+}
+
+/** Handle VHC request for data read from the device (in transfer).
+ *
+ * @param dev Target virtual device.
+ * @param iid Caller id.
+ * @param icall The call with the request.
+ */
+static void ipc_data_in(usbvirt_device_t *dev,
+    usb_transfer_type_t transfer_type,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
+
+	int rc;
+
+	size_t data_len = 0;
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EPARTY);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	size_t actual_len;
+	rc = usbvirt_data_in(dev, transfer_type, endpoint,
+	    buffer, data_len, &actual_len);
+
+	if (rc != EOK) {
+		async_answer_0(data_callid, rc);
+		async_answer_0(iid, rc);
+		free(buffer);
+		return;
+	}
+
+	async_data_read_finalize(data_callid, buffer, actual_len);
+	async_answer_0(iid, EOK);
+
+	free(buffer);
+}
+
+/** Handle VHC request for data write to the device (out transfer).
+ *
+ * @param dev Target virtual device.
+ * @param iid Caller id.
+ * @param icall The call with the request.
+ */
+static void ipc_data_out(usbvirt_device_t *dev,
+    usb_transfer_type_t transfer_type,
+    ipc_callid_t iid, ipc_call_t *icall)
+{
+	usb_endpoint_t endpoint = IPC_GET_ARG1(*icall);
+
+	void *data_buffer = NULL;
+	size_t data_buffer_size = 0;
+
+	int rc = async_data_write_accept(&data_buffer, false,
+	    1, 0, 0, &data_buffer_size);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+
+	rc = usbvirt_data_out(dev, transfer_type, endpoint,
+	    data_buffer, data_buffer_size);
+
+	async_answer_0(iid, rc);
+
+	free(data_buffer);
+}
+
+/** Handle incoming IPC call for virtual USB device.
+ *
+ * @param dev Target USB device.
+ * @param callid Caller id.
+ * @param call Incoming call.
+ * @return Whether the call was handled.
+ */
+bool usbvirt_ipc_handle_call(usbvirt_device_t *dev,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	switch (IPC_GET_IMETHOD(*call)) {
+	case IPC_M_USBVIRT_GET_NAME:
+		ipc_get_name(dev, callid, call);
+		break;
+
+	case IPC_M_USBVIRT_CONTROL_READ:
+		ipc_control_read(dev, callid, call);
+		break;
+
+	case IPC_M_USBVIRT_CONTROL_WRITE:
+		ipc_control_write(dev, callid, call);
+		break;
+
+	case IPC_M_USBVIRT_INTERRUPT_IN:
+		ipc_data_in(dev, USB_TRANSFER_INTERRUPT, callid, call);
+		break;
+
+	case IPC_M_USBVIRT_BULK_IN:
+		ipc_data_in(dev, USB_TRANSFER_BULK, callid, call);
+		break;
+
+	case IPC_M_USBVIRT_INTERRUPT_OUT:
+		ipc_data_out(dev, USB_TRANSFER_INTERRUPT, callid, call);
+		break;
+
+	case IPC_M_USBVIRT_BULK_OUT:
+		ipc_data_out(dev, USB_TRANSFER_BULK, callid, call);
+		break;
+
+
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/ipc_hc.c
===================================================================
--- uspace/lib/usbvirt/src/ipc_hc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/src/ipc_hc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * IPC wrappers, host controller side.
+ */
+#include <errno.h>
+#include <str.h>
+#include <stdio.h>
+#include <assert.h>
+#include <async.h>
+#include <devman.h>
+#include <usbvirt/device.h>
+#include <usbvirt/ipc.h>
+#include <usb/debug.h>
+
+/** Send control read transfer to virtual USB device.
+ *
+ * @param sess Session to the virtual device.
+ * @param ep Target endpoint number.
+ * @param setup_buffer Setup buffer.
+ * @param setup_buffer_size Setup buffer size in bytes.
+ * @param data_buffer Data buffer (DATA stage of control transfer).
+ * @param data_buffer_size Size of data buffer in bytes.
+ * @param data_transfered_size Number of actually transferred bytes.
+ *
+ * @return Error code.
+ *
+ */
+int usbvirt_ipc_send_control_read(async_sess_t *sess, void *setup_buffer,
+    size_t setup_buffer_size, void *data_buffer, size_t data_buffer_size,
+    size_t *data_transfered_size)
+{
+	if (!sess)
+		return EINVAL;
+	
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0))
+		return EINVAL;
+	
+	if ((data_buffer == NULL) || (data_buffer_size == 0))
+		return EINVAL;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	aid_t opening_request = async_send_0(exch, IPC_M_USBVIRT_CONTROL_READ,
+	    NULL);
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		return ENOMEM;
+	}
+	
+	int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+	
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(exch, data_buffer, data_buffer_size,
+	    &data_request_call);
+	
+	async_exchange_end(exch);
+	
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+	
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	if (data_request_rc != EOK) {
+		/* Prefer the return code of the opening request. */
+		if (opening_request_rc != EOK)
+			return (int) opening_request_rc;
+		else
+			return (int) data_request_rc;
+	}
+	
+	if (opening_request_rc != EOK)
+		return (int) opening_request_rc;
+	
+	if (data_transfered_size != NULL)
+		*data_transfered_size = IPC_GET_ARG2(data_request_call);
+	
+	return EOK;
+}
+
+/** Send control write transfer to virtual USB device.
+ *
+ * @param sess Session to the virtual device.
+ * @param ep Target endpoint number.
+ * @param setup_buffer Setup buffer.
+ * @param setup_buffer_size Setup buffer size in bytes.
+ * @param data_buffer Data buffer (DATA stage of control transfer).
+ * @param data_buffer_size Size of data buffer in bytes.
+ *
+ * @return Error code.
+ *
+ */
+int usbvirt_ipc_send_control_write(async_sess_t *sess, void *setup_buffer,
+    size_t setup_buffer_size, void *data_buffer, size_t data_buffer_size)
+{
+	if (!sess)
+		return EINVAL;
+	
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0))
+		return EINVAL;
+	
+	if ((data_buffer_size > 0) && (data_buffer == NULL))
+		return EINVAL;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	aid_t opening_request = async_send_1(exch, IPC_M_USBVIRT_CONTROL_WRITE,
+	    data_buffer_size, NULL);
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		return ENOMEM;
+	}
+	
+	int rc = async_data_write_start(exch, setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+	
+	if (data_buffer_size > 0) {
+		rc = async_data_write_start(exch, data_buffer, data_buffer_size);
+		if (rc != EOK) {
+			async_exchange_end(exch);
+			async_wait_for(opening_request, NULL);
+			return rc;
+		}
+	}
+	
+	async_exchange_end(exch);
+	
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	return (int) opening_request_rc;
+}
+
+/** Request data transfer from virtual USB device.
+ *
+ * @param sess Session to the virtual device.
+ * @param ep Target endpoint number.
+ * @param tr_type Transfer type (interrupt or bulk).
+ * @param data Data buffer.
+ * @param data_size Size of the data buffer in bytes.
+ * @param act_size Number of actually returned bytes.
+ *
+ * @return Error code.
+ *
+ */
+int usbvirt_ipc_send_data_in(async_sess_t *sess, usb_endpoint_t ep,
+    usb_transfer_type_t tr_type, void *data, size_t data_size, size_t *act_size)
+{
+	if (!sess)
+		return EINVAL;
+	
+	usbvirt_hc_to_device_method_t method;
+	
+	switch (tr_type) {
+	case USB_TRANSFER_INTERRUPT:
+		method = IPC_M_USBVIRT_INTERRUPT_IN;
+		break;
+	case USB_TRANSFER_BULK:
+		method = IPC_M_USBVIRT_BULK_IN;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	if ((ep <= 0) || (ep >= USBVIRT_ENDPOINT_MAX))
+		return EINVAL;
+	
+	if ((data == NULL) || (data_size == 0))
+		return EINVAL;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	aid_t opening_request = async_send_2(exch, method, ep, tr_type, NULL);
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		return ENOMEM;
+	}
+	
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(exch, data, data_size,
+	    &data_request_call);
+	
+	async_exchange_end(exch);
+	
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		return ENOMEM;
+	}
+	
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	if (data_request_rc != EOK) {
+		/* Prefer the return code of the opening request. */
+		if (opening_request_rc != EOK)
+			return (int) opening_request_rc;
+		else
+			return (int) data_request_rc;
+	}
+	
+	if (opening_request_rc != EOK)
+		return (int) opening_request_rc;
+	
+	if (act_size != NULL)
+		*act_size = IPC_GET_ARG2(data_request_call);
+	
+	return EOK;
+}
+
+/** Send data to virtual USB device.
+ *
+ * @param sess Session to the virtual device.
+ * @param ep Target endpoint number.
+ * @param tr_type Transfer type (interrupt or bulk).
+ * @param data Data buffer.
+ * @param data_size Size of the data buffer in bytes.
+ *
+ * @return Error code.
+ *
+ */
+int usbvirt_ipc_send_data_out(async_sess_t *sess, usb_endpoint_t ep,
+    usb_transfer_type_t tr_type, void *data, size_t data_size)
+{
+	if (!sess)
+		return EINVAL;
+	
+	usbvirt_hc_to_device_method_t method;
+	
+	switch (tr_type) {
+	case USB_TRANSFER_INTERRUPT:
+		method = IPC_M_USBVIRT_INTERRUPT_OUT;
+		break;
+	case USB_TRANSFER_BULK:
+		method = IPC_M_USBVIRT_BULK_OUT;
+		break;
+	default:
+		return EINVAL;
+	}
+	
+	if ((ep <= 0) || (ep >= USBVIRT_ENDPOINT_MAX))
+		return EINVAL;
+	
+	if ((data == NULL) || (data_size == 0))
+		return EINVAL;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	aid_t opening_request = async_send_1(exch, method, ep, NULL);
+	if (opening_request == 0) {
+		async_exchange_end(exch);
+		return ENOMEM;
+	}
+	
+	int rc = async_data_write_start(exch, data, data_size);
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+	
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+	
+	return (int) opening_request_rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/private.h
===================================================================
--- uspace/lib/usbvirt/src/private.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/src/private.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * Private definitions.
+ */
+#ifndef USBVIRT_PRIVATE_H_
+#define USBVIRT_PRIVATE_H_
+
+#include <usbvirt/device.h>
+
+int process_control_transfer(usbvirt_device_t *,
+    usbvirt_control_request_handler_t *,
+    usb_device_request_setup_packet_t *,
+    uint8_t *, size_t *);
+
+extern usbvirt_control_request_handler_t library_handlers[];
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/stdreq.c
===================================================================
--- uspace/lib/usbvirt/src/stdreq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/src/stdreq.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * Standard control request handlers.
+ */
+#include "private.h"
+#include <usb/dev/request.h>
+#include <assert.h>
+#include <errno.h>
+
+/** Helper for replying to control read transfer from virtual USB device.
+ *
+ * This function takes care of copying data to answer buffer taking care
+ * of buffer sizes properly.
+ *
+ * @param setup_packet The setup packet.
+ * @param data Data buffer to write to.
+ * @param act_size Where to write actual size of returned data.
+ * @param actual_data Data to be returned.
+ * @param actual_data_size Size of answer data (@p actual_data) in bytes.
+ */
+void usbvirt_control_reply_helper(const usb_device_request_setup_packet_t *setup_packet,
+    uint8_t *data, size_t *act_size,
+    void *actual_data, size_t actual_data_size)
+{
+	size_t expected_size = setup_packet->length;
+	if (expected_size < actual_data_size) {
+		actual_data_size = expected_size;
+	}
+
+	memcpy(data, actual_data, actual_data_size);
+
+	if (act_size != NULL) {
+		*act_size = actual_data_size;
+	}
+}
+
+/** GET_DESCRIPTOR handler. */
+static int req_get_descriptor(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
+{
+	uint8_t type = setup_packet->value_high;
+	uint8_t index = setup_packet->value_low;
+
+	/*
+	 * Standard device descriptor.
+	 */
+	if ((type == USB_DESCTYPE_DEVICE) && (index == 0)) {
+		if (device->descriptors && device->descriptors->device) {
+			usbvirt_control_reply_helper(setup_packet, data, act_size,
+			    device->descriptors->device,
+			    device->descriptors->device->length);
+			return EOK;
+		} else {
+			return EFORWARD;
+		}
+	}
+
+	/*
+	 * Configuration descriptor together with interface, endpoint and
+	 * class-specific descriptors.
+	 */
+	if (type == USB_DESCTYPE_CONFIGURATION) {
+		if (!device->descriptors) {
+			return EFORWARD;
+		}
+		if (index >= device->descriptors->configuration_count) {
+			return EFORWARD;
+		}
+		/* Copy the data. */
+		usbvirt_device_configuration_t *config = &device->descriptors
+		    ->configuration[index];
+		uint8_t *all_data = malloc(config->descriptor->total_length);
+		if (all_data == NULL) {
+			return ENOMEM;
+		}
+
+		uint8_t *ptr = all_data;
+		memcpy(ptr, config->descriptor, config->descriptor->length);
+		ptr += config->descriptor->length;
+		size_t i;
+		for (i = 0; i < config->extra_count; i++) {
+			usbvirt_device_configuration_extras_t *extra
+			    = &config->extra[i];
+			memcpy(ptr, extra->data, extra->length);
+			ptr += extra->length;
+		}
+
+		usbvirt_control_reply_helper(setup_packet, data, act_size,
+		    all_data, config->descriptor->total_length);
+
+		free(all_data);
+
+		return EOK;
+	}
+
+	return EFORWARD;
+}
+
+static int req_set_address(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
+{
+	uint16_t new_address = setup_packet->value;
+	uint16_t zero1 = setup_packet->index;
+	uint16_t zero2 = setup_packet->length;
+
+	if ((zero1 != 0) || (zero2 != 0)) {
+		return EINVAL;
+	}
+
+	if (new_address > 127) {
+		return EINVAL;
+	}
+
+	device->address = new_address;
+
+	return EOK;
+}
+
+static int req_set_configuration(usbvirt_device_t *device,
+    const usb_device_request_setup_packet_t *setup_packet, uint8_t *data, size_t *act_size)
+{
+	uint16_t configuration_value = setup_packet->value;
+	uint16_t zero1 = setup_packet->index;
+	uint16_t zero2 = setup_packet->length;
+
+	if ((zero1 != 0) || (zero2 != 0)) {
+		return EINVAL;
+	}
+
+	/*
+	 * Configuration value is 1 byte information.
+	 */
+	if (configuration_value > 255) {
+		return EINVAL;
+	}
+
+	/*
+	 * Do nothing when in default state. According to specification,
+	 * this is not specified.
+	 */
+	if (device->state == USBVIRT_STATE_DEFAULT) {
+		return EOK;
+	}
+
+	usbvirt_device_state_t new_state;
+	if (configuration_value == 0) {
+		new_state = USBVIRT_STATE_ADDRESS;
+	} else {
+		// FIXME: check that this configuration exists
+		new_state = USBVIRT_STATE_CONFIGURED;
+	}
+
+	if (device->ops && device->ops->state_changed) {
+		device->ops->state_changed(device, device->state, new_state);
+	}
+	device->state = new_state;
+
+	return EOK;
+}
+
+/** Standard request handlers. */
+usbvirt_control_request_handler_t library_handlers[] = {
+	{
+		.req_direction = USB_DIRECTION_OUT,
+		.req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
+		.req_type = USB_REQUEST_TYPE_STANDARD,
+		.request = USB_DEVREQ_SET_ADDRESS,
+		.name = "SetAddress",
+		.callback = req_set_address
+	},
+	{
+		.req_direction = USB_DIRECTION_IN,
+		.req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
+		.req_type = USB_REQUEST_TYPE_STANDARD,
+		.request = USB_DEVREQ_GET_DESCRIPTOR,
+		.name = "GetDescriptor",
+		.callback = req_get_descriptor
+	},
+	{
+		.req_direction = USB_DIRECTION_OUT,
+		.req_recipient = USB_REQUEST_RECIPIENT_DEVICE,
+		.req_type = USB_REQUEST_TYPE_STANDARD,
+		.request = USB_DEVREQ_SET_CONFIGURATION,
+		.name = "SetConfiguration",
+		.callback = req_set_configuration
+	},
+
+	{ .callback = NULL }
+};
+
+/**
+ * @}
+ */
Index: uspace/lib/usbvirt/src/transfer.c
===================================================================
--- uspace/lib/usbvirt/src/transfer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/lib/usbvirt/src/transfer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2011 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 libusbvirt
+ * @{
+ */
+/** @file
+ * Transfer handling.
+ */
+#include <usbvirt/device.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <assert.h>
+#include "private.h"
+
+/** Process a control transfer to the virtual USB device.
+ *
+ * @param dev Target device.
+ * @param setup Setup packet data.
+ * @param setup_size Size of setup packet.
+ * @param data Extra data (DATA stage).
+ * @param data_size Size of extra data in bytes.
+ * @param data_size_sent Number of actually send bytes during the transfer
+ *	(only used for READ transfers).
+ * @return Error code.
+ */
+static int usbvirt_control_transfer(usbvirt_device_t *dev,
+    void *setup, size_t setup_size,
+    void *data, size_t data_size, size_t *data_size_sent)
+{
+	assert(dev);
+	assert(dev->ops);
+
+	if (setup_size != sizeof(usb_device_request_setup_packet_t)) {
+		return ESTALL;
+	}
+	usb_device_request_setup_packet_t *setup_packet = setup;
+	if (data_size != setup_packet->length) {
+		return ESTALL;
+	}
+
+	int rc;
+
+	/* Run user handler first. */
+	rc = process_control_transfer(dev, dev->ops->control,
+	    setup_packet, data, data_size_sent);
+	if (rc != EFORWARD) {
+		return rc;
+	}
+
+	/* Run the library handlers afterwards. */
+	rc = process_control_transfer(dev, library_handlers,
+	    setup_packet, data, data_size_sent);
+
+	if (rc == EFORWARD) {
+		usb_log_warning("Control transfer {%s (%s)} not handled.\n",
+		    usb_debug_str_buffer(setup, setup_size, 10),
+		    setup_packet->request_type & 0x80
+		    ? "IN" : usb_debug_str_buffer(data, data_size, 10));
+		rc = EBADCHECKSUM;
+	}
+
+	return rc;
+}
+
+/** Issue a control write transfer to virtual USB device.
+ *
+ * @see usbvirt_control_transfer
+ *
+ * @param dev Target virtual device.
+ * @param setup Setup data.
+ * @param setup_size Size of setup packet.
+ * @param data Extra data (DATA stage).
+ * @param data_size Size of extra data buffer in bytes.
+ * @return Error code.
+ */
+int usbvirt_control_write(usbvirt_device_t *dev, void *setup, size_t setup_size,
+    void *data, size_t data_size)
+{
+	return usbvirt_control_transfer(dev, setup, setup_size,
+	    data, data_size, NULL);
+}
+
+/** Issue a control read transfer to virtual USB device.
+ *
+ * @see usbvirt_control_transfer
+ *
+ * @param dev Target virtual device.
+ * @param setup Setup data.
+ * @param setup_size Size of setup packet.
+ * @param data Extra data (DATA stage).
+ * @param data_size Size of extra data buffer in bytes.
+ * @param data_size_sent Number of actually send bytes during the transfer.
+ * @return Error code.
+ */
+int usbvirt_control_read(usbvirt_device_t *dev, void *setup, size_t setup_size,
+    void *data, size_t data_size, size_t *data_size_sent)
+{
+	return usbvirt_control_transfer(dev, setup, setup_size,
+	    data, data_size, data_size_sent);
+}
+
+/** Send data to virtual USB device.
+ *
+ * @param dev Target virtual device.
+ * @param transf_type Transfer type (interrupt, bulk).
+ * @param endpoint Endpoint number.
+ * @param data Data sent from the driver to the device.
+ * @param data_size Size of the @p data buffer in bytes.
+ * @return Error code.
+ */
+int usbvirt_data_out(usbvirt_device_t *dev, usb_transfer_type_t transf_type,
+    usb_endpoint_t endpoint, void *data, size_t data_size)
+{
+	if ((endpoint <= 0) || (endpoint >= USBVIRT_ENDPOINT_MAX)) {
+		return ERANGE;
+	}
+	if ((dev->ops == NULL) || (dev->ops->data_out[endpoint] == NULL)) {
+		return ENOTSUP;
+	}
+
+	int rc = dev->ops->data_out[endpoint](dev, endpoint, transf_type,
+	    data, data_size);
+
+	return rc;
+}
+
+/** Request data from virtual USB device.
+ *
+ * @param dev Target virtual device.
+ * @param transf_type Transfer type (interrupt, bulk).
+ * @param endpoint Endpoint number.
+ * @param data Where to stored data the device returns to the driver.
+ * @param data_size Size of the @p data buffer in bytes.
+ * @param data_size_sent Number of actually written bytes.
+ * @return Error code.
+ */
+int usbvirt_data_in(usbvirt_device_t *dev, usb_transfer_type_t transf_type,
+    usb_endpoint_t endpoint, void *data, size_t data_size, size_t *data_size_sent)
+{
+	if ((endpoint <= 0) || (endpoint >= USBVIRT_ENDPOINT_MAX)) {
+		return ERANGE;
+	}
+	if ((dev->ops == NULL) || (dev->ops->data_in[endpoint] == NULL)) {
+		return ENOTSUP;
+	}
+
+	size_t data_size_sent_tmp;
+	int rc = dev->ops->data_in[endpoint](dev, endpoint, transf_type,
+	    data, data_size, &data_size_sent_tmp);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (data_size_sent != NULL) {
+		*data_size_sent = data_size_sent_tmp;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -57,5 +57,5 @@
 #include <stdint.h>
 #include <str.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <inttypes.h>
@@ -81,7 +81,4 @@
 static const size_t identify_data_size = 512;
 
-/** Size of the communication area. */
-static size_t comm_size;
-
 /** I/O base address of the command registers. */
 static uintptr_t cmd_physical;
@@ -105,5 +102,5 @@
 static void print_syntax(void);
 static int ata_bd_init(void);
-static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
 static int ata_bd_read_blocks(int disk_id, uint64_t ba, size_t cnt,
     void *buf);
@@ -179,5 +176,5 @@
 		
 		snprintf(name, 16, "%s/ata%udisk%d", NAMESPACE, ctl_num, i);
-		rc = devmap_device_register(name, &disk[i].devmap_handle);
+		rc = loc_service_register(name, &disk[i].service_id);
 		if (rc != EOK) {
 			printf(NAME ": Unable to register device %s.\n", name);
@@ -247,5 +244,5 @@
 	int rc;
 
-	rc = devmap_driver_register(NAME, ata_bd_connection);
+	rc = loc_server_register(NAME, ata_bd_connection);
 	if (rc < 0) {
 		printf(NAME ": Unable to register driver.\n");
@@ -274,5 +271,5 @@
 
 /** Block device connection handler */
-static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	void *fs_va = NULL;
@@ -280,5 +277,6 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dsid;
+	size_t comm_size;	/**< Size of the communication area. */
 	unsigned int flags;
 	int retval;
@@ -287,11 +285,11 @@
 	int disk_id, i;
 
-	/* Get the device handle. */
-	dh = IPC_GET_ARG1(*icall);
+	/* Get the device service ID. */
+	dsid = IPC_GET_ARG1(*icall);
 
 	/* Determine which disk device is the client connecting to. */
 	disk_id = -1;
 	for (i = 0; i < MAX_DISKS; i++)
-		if (disk[i].devmap_handle == dh)
+		if (disk[i].service_id == dsid)
 			disk_id = i;
 
@@ -317,12 +315,15 @@
 	(void) async_share_out_finalize(callid, fs_va);
 
-	while (1) {
+	while (true) {
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
@@ -372,4 +373,5 @@
 	uint16_t w;
 	uint8_t c;
+	uint16_t bc;
 	size_t pos, len;
 	int rc;
@@ -387,11 +389,24 @@
 	} else if (rc == EIO) {
 		/*
-		 * There is something, but not a register device.
-		 * It could be a packet device.
+		 * There is something, but not a register device. Check to see
+		 * whether the IDENTIFY command left the packet signature in
+		 * the registers in case this is a packet device.
+		 *
+		 * According to the ATA specification, the LBA low and
+		 * interrupt reason registers should be set to 0x01. However,
+		 * there are many devices that do not follow this and only set
+		 * the byte count registers. So, only check these.
 		 */
-		rc = identify_pkt_dev(disk_id, &idata);
-		if (rc == EOK) {
-			/* We have a packet device. */
-			d->dev_type = ata_pkt_dev;
+		bc = ((uint16_t)pio_read_8(&cmd->cylinder_high) << 8) |
+		    pio_read_8(&cmd->cylinder_low);
+
+		if (bc == PDEV_SIGNATURE_BC) {
+			rc = identify_pkt_dev(disk_id, &idata);
+			if (rc == EOK) {
+				/* We have a packet device. */
+				d->dev_type = ata_pkt_dev;
+			} else {
+				return EIO;
+			}
 		} else {
 			/* Nope. Something's there, but not recognized. */
@@ -403,5 +418,4 @@
 	}
 
-	printf("device caps: 0x%04x\n", idata.caps);
 	if (d->dev_type == ata_pkt_dev) {
 		/* Packet device */
@@ -566,8 +580,9 @@
 
 	/*
-	 * This is where we would most likely expect a non-existing device to
-	 * show up by not setting SR_DRDY.
+	 * Do not wait for DRDY to be set in case this is a packet device.
+	 * We determine whether the device is present by waiting for DRQ to be
+	 * set after issuing the command.
 	 */
-	if (wait_status(SR_DRDY, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
+	if (wait_status(0, ~SR_BSY, NULL, TIMEOUT_PROBE) != EOK)
 		return ETIMEOUT;
 
@@ -577,15 +592,20 @@
 		return ETIMEOUT;
 
+	/*
+	 * If ERR is set, this may be a packet device, so return EIO to cause
+	 * the caller to check for one.
+	 */
+	if ((status & SR_ERR) != 0) {
+		return EIO;
+	}
+
+	if (wait_status(SR_DRQ, ~SR_BSY, &status, TIMEOUT_PROBE) != EOK)
+		return ETIMEOUT;
+
 	/* Read data from the disk buffer. */
 
-	if ((status & SR_DRQ) != 0) {
-		for (i = 0; i < identify_data_size / 2; i++) {
-			data = pio_read_16(&cmd->data_port);
-			((uint16_t *) buf)[i] = data;
-		}
-	}
-
-	if ((status & SR_ERR) != 0) {
-		return EIO;
+	for (i = 0; i < identify_data_size / 2; i++) {
+		data = pio_read_16(&cmd->data_port);
+		((uint16_t *) buf)[i] = data;
 	}
 
Index: uspace/srv/bd/ata_bd/ata_bd.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/ata_bd/ata_bd.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -116,5 +116,5 @@
 
 	fibril_mutex_t lock;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 } disk_t;
 
Index: uspace/srv/bd/ata_bd/ata_hw.h
===================================================================
--- uspace/srv/bd/ata_bd/ata_hw.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/ata_bd/ata_hw.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -293,4 +293,12 @@
 };
 
+enum ata_pdev_signature {
+	/**
+	 * Signature put by a packet device in byte count register
+	 * in response to Identify command.
+	 */
+	PDEV_SIGNATURE_BC	= 0xEB14
+};
+
 #endif
 
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -45,5 +45,5 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <sys/typefmt.h>
@@ -61,10 +61,10 @@
 static FILE *img;
 
-static devmap_handle_t devmap_handle;
+static service_id_t service_id;
 static fibril_mutex_t dev_lock;
 
 static void print_usage(void);
 static int file_bd_init(const char *fname);
-static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
 static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf);
 static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
@@ -117,5 +117,5 @@
 		return -1;
 
-	rc = devmap_device_register(device_name, &devmap_handle);
+	rc = loc_service_register(device_name, &service_id);
 	if (rc != EOK) {
 		printf(NAME ": Unable to register device '%s'.\n",
@@ -142,5 +142,5 @@
 	long img_size;
 
-	rc = devmap_driver_register(NAME, file_bd_connection);
+	rc = loc_server_register(NAME, file_bd_connection);
 	if (rc < 0) {
 		printf(NAME ": Unable to register driver.\n");
@@ -170,5 +170,5 @@
 }
 
-static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	void *fs_va = NULL;
@@ -198,12 +198,15 @@
 	(void) async_share_out_finalize(callid, fs_va);
 
-	while (1) {
+	while (true) {
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
Index: uspace/srv/bd/gxe_bd/gxe_bd.c
===================================================================
--- uspace/srv/bd/gxe_bd/gxe_bd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,5 +43,5 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <errno.h>
@@ -92,10 +92,10 @@
 static gxe_bd_t *dev;
 
-static devmap_handle_t devmap_handle[MAX_DISKS];
+static service_id_t service_id[MAX_DISKS];
 
 static fibril_mutex_t dev_lock[MAX_DISKS];
 
 static int gxe_bd_init(void);
-static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
 static int gxe_bd_read_blocks(int disk_id, uint64_t ba, unsigned cnt,
     void *buf);
@@ -126,5 +126,5 @@
 	char name[16];
 
-	rc = devmap_driver_register(NAME, gxe_bd_connection);
+	rc = loc_server_register(NAME, gxe_bd_connection);
 	if (rc < 0) {
 		printf(NAME ": Unable to register driver.\n");
@@ -142,5 +142,5 @@
 	for (i = 0; i < MAX_DISKS; i++) {
 		snprintf(name, 16, "%s/disk%d", NAMESPACE, i);
-		rc = devmap_device_register(name, &devmap_handle[i]);
+		rc = loc_service_register(name, &service_id[i]);
 		if (rc != EOK) {
 			printf(NAME ": Unable to register device %s.\n", name);
@@ -153,5 +153,5 @@
 }
 
-static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	void *fs_va = NULL;
@@ -159,5 +159,5 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dsid;
 	unsigned int flags;
 	int retval;
@@ -167,10 +167,10 @@
 
 	/* Get the device handle. */
-	dh = IPC_GET_ARG1(*icall);
+	dsid = IPC_GET_ARG1(*icall);
 
 	/* Determine which disk device is the client connecting to. */
 	disk_id = -1;
 	for (i = 0; i < MAX_DISKS; i++)
-		if (devmap_handle[i] == dh)
+		if (service_id[i] == dsid)
 			disk_id = i;
 
@@ -201,12 +201,15 @@
 	(void) async_share_out_finalize(callid, fs_va);
 
-	while (1) {
+	while (true) {
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
Index: uspace/srv/bd/part/guid_part/guid_part.c
===================================================================
--- uspace/srv/bd/part/guid_part/guid_part.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -51,10 +51,10 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <sys/typefmt.h>
 #include <inttypes.h>
 #include <libblock.h>
-#include <devmap.h>
+#include <loc.h>
 #include <errno.h>
 #include <bool.h>
@@ -81,6 +81,6 @@
 	/** Number of blocks */
 	aoff64_t length;
-	/** Device representing the partition (outbound device) */
-	devmap_handle_t dev;
+	/** Service representing the partition (outbound device) */
+	service_id_t dsid;
 	/** Points to next partition structure. */
 	struct part *next;
@@ -90,5 +90,5 @@
 
 /** Partitioned device (inbound device) */
-static devmap_handle_t indev_handle;
+static service_id_t indev_sid;
 
 /** List of partitions. This structure is an empty head. */
@@ -99,5 +99,5 @@
 static part_t *gpt_part_new(void);
 static void gpt_pte_to_part(const gpt_entry_t *pte, part_t *part);
-static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static int gpt_bd_read(part_t *p, aoff64_t ba, size_t cnt, void *buf);
 static int gpt_bd_write(part_t *p, aoff64_t ba, size_t cnt, const void *buf);
@@ -129,9 +129,9 @@
 	int i;
 	char *name;
-	devmap_handle_t dev;
+	service_id_t dsid;
 	uint64_t size_mb;
 	part_t *part;
 
-	rc = devmap_device_get_handle(dev_name, &indev_handle, 0);
+	rc = loc_service_get_id(dev_name, &indev_sid, 0);
 	if (rc != EOK) {
 		printf(NAME ": could not resolve device `%s'.\n", dev_name);
@@ -139,5 +139,5 @@
 	}
 
-	rc = block_init(indev_handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, indev_sid, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": could not init libblock.\n");
@@ -147,5 +147,5 @@
 	/* Determine and verify block size. */
 
-	rc = block_get_bsize(indev_handle, &block_size);
+	rc = block_get_bsize(indev_sid, &block_size);
 	if (rc != EOK) {
 		printf(NAME ": error getting block size.\n");
@@ -163,8 +163,8 @@
 		return rc;
 
-	/* Register the driver with device mapper. */
-	rc = devmap_driver_register(NAME, gpt_connection);
+	/* Register server with location service. */
+	rc = loc_server_register(NAME, gpt_connection);
 	if (rc != EOK) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return rc;
 	}
@@ -188,7 +188,7 @@
 			return ENOMEM;
 
-		rc = devmap_device_register(name, &dev);
+		rc = loc_service_register(name, &dsid);
 		if (rc != EOK) {
-			printf(NAME ": Unable to register device %s.\n", name);
+			printf(NAME ": Unable to register service %s.\n", name);
 			return rc;
 		}
@@ -199,5 +199,5 @@
 		    "%" PRIuOFF64 " MB.\n", name, part->length, size_mb);
 
-		part->dev = dev;
+		part->dsid = dsid;
 		free(name);
 
@@ -228,5 +228,5 @@
 	}
 
-	rc = block_read_direct(indev_handle, GPT_HDR_BA, 1, gpt_hdr);
+	rc = block_read_direct(indev_sid, GPT_HDR_BA, 1, gpt_hdr);
 	if (rc != EOK) {
 		printf(NAME ": Failed reading GPT header block.\n");
@@ -256,5 +256,5 @@
 	}
 
-	rc = block_read_direct(indev_handle, ba, bcnt, etable);
+	rc = block_read_direct(indev_sid, ba, bcnt, etable);
 	if (rc != EOK) {
 		printf(NAME ": Failed reading GPT entries.\n");
@@ -303,9 +303,9 @@
 	}
 
-	part->dev = 0;
+	part->dsid = 0;
 	part->next = NULL;
 }
 
-static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	size_t comm_size;
@@ -314,5 +314,5 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dh;
 	unsigned int flags;
 	int retval;
@@ -330,5 +330,5 @@
 	 */
 	part = plist_head.next;
-	while (part != NULL && part->dev != dh)
+	while (part != NULL && part->dsid != dh)
 		part = part->next;
 
@@ -356,12 +356,15 @@
 	(void) async_share_out_finalize(callid, fs_va);
 
-	while (1) {
+	while (true) {
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
@@ -407,5 +410,5 @@
 		return ELIMIT;
 
-	return block_read_direct(indev_handle, gba, cnt, buf);
+	return block_read_direct(indev_sid, gba, cnt, buf);
 }
 
@@ -418,5 +421,5 @@
 		return ELIMIT;
 
-	return block_write_direct(indev_handle, gba, cnt, buf);
+	return block_write_direct(indev_sid, gba, cnt, buf);
 }
 
Index: uspace/srv/bd/part/mbr_part/mbr_part.c
===================================================================
--- uspace/srv/bd/part/mbr_part/mbr_part.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/part/mbr_part/mbr_part.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -61,10 +61,9 @@
 #include <as.h>
 #include <fibril_synch.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sys/types.h>
 #include <sys/typefmt.h>
 #include <inttypes.h>
 #include <libblock.h>
-#include <devmap.h>
 #include <errno.h>
 #include <bool.h>
@@ -100,5 +99,5 @@
 	aoff64_t length;
 	/** Device representing the partition (outbound device) */
-	devmap_handle_t dev;
+	service_id_t dsid;
 	/** Points to next partition structure. */
 	struct part *next;
@@ -141,5 +140,5 @@
 
 /** Partitioned device (inbound device) */
-static devmap_handle_t indev_handle;
+static service_id_t indef_sid;
 
 /** List of partitions. This structure is an empty head. */
@@ -150,5 +149,5 @@
 static part_t *mbr_part_new(void);
 static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part);
-static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf);
 static int mbr_bd_write(part_t *p, uint64_t ba, size_t cnt, const void *buf);
@@ -180,9 +179,9 @@
 	int i;
 	char *name;
-	devmap_handle_t dev;
+	service_id_t dsid;
 	uint64_t size_mb;
 	part_t *part;
 
-	rc = devmap_device_get_handle(dev_name, &indev_handle, 0);
+	rc = loc_service_get_id(dev_name, &indef_sid, 0);
 	if (rc != EOK) {
 		printf(NAME ": could not resolve device `%s'.\n", dev_name);
@@ -190,5 +189,5 @@
 	}
 
-	rc = block_init(indev_handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, indef_sid, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": could not init libblock.\n");
@@ -198,5 +197,5 @@
 	/* Determine and verify block size. */
 
-	rc = block_get_bsize(indev_handle, &block_size);
+	rc = block_get_bsize(indef_sid, &block_size);
 	if (rc != EOK) {
 		printf(NAME ": error getting block size.\n");
@@ -214,8 +213,8 @@
 		return rc;
 
-	/* Register the driver with device mapper. */
-	rc = devmap_driver_register(NAME, mbr_connection);
+	/* Register server with location service. */
+	rc = loc_server_register(NAME, mbr_connection);
 	if (rc != EOK) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return rc;
 	}
@@ -239,7 +238,7 @@
 			return ENOMEM;
 
-		rc = devmap_device_register(name, &dev);
+		rc = loc_service_register(name, &dsid);
 		if (rc != EOK) {
-			printf(NAME ": Unable to register device %s.\n", name);
+			printf(NAME ": Unable to register service %s.\n", name);
 			return rc;
 		}
@@ -250,5 +249,5 @@
 		    "%" PRIu64 " MB.\n", name, part->length, size_mb);
 
-		part->dev = dev;
+		part->dsid = dsid;
 		free(name);
 
@@ -281,5 +280,5 @@
 	 */
 
-	rc = block_read_direct(indev_handle, 0, 1, brb);
+	rc = block_read_direct(indef_sid, 0, 1, brb);
 	if (rc != EOK) {
 		printf(NAME ": Failed reading MBR block.\n");
@@ -332,5 +331,5 @@
 		 */
 		ba = cp.start_addr;
-		rc = block_read_direct(indev_handle, ba, 1, brb);
+		rc = block_read_direct(indef_sid, ba, 1, brb);
 		if (rc != EOK) {
 			printf(NAME ": Failed reading EBR block at %"
@@ -381,9 +380,9 @@
 	part->present = (pte->ptype != PT_UNUSED) ? true : false;
 
-	part->dev = 0;
+	part->dsid = 0;
 	part->next = NULL;
 }
 
-static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	size_t comm_size;
@@ -392,5 +391,5 @@
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dh;
 	unsigned int flags;
 	int retval;
@@ -408,5 +407,5 @@
 	 */
 	part = plist_head.next;
-	while (part != NULL && part->dev != dh)
+	while (part != NULL && part->dsid != dh)
 		part = part->next;
 
@@ -437,9 +436,12 @@
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
@@ -485,5 +487,5 @@
 		return ELIMIT;
 
-	return block_read_direct(indev_handle, gba, cnt, buf);
+	return block_read_direct(indef_sid, gba, cnt, buf);
 }
 
@@ -496,5 +498,5 @@
 		return ELIMIT;
 
-	return block_write_direct(indev_handle, gba, cnt, buf);
+	return block_write_direct(indef_sid, gba, cnt, buf);
 }
 
Index: uspace/srv/bd/rd/Makefile
===================================================================
--- uspace/srv/bd/rd/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/rd/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../../..
 BINARY = rd
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/bd/rd/rd.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,5 +52,5 @@
 #include <fibril_synch.h>
 #include <stdio.h>
-#include <devmap.h>
+#include <loc.h>
 #include <ipc/bd.h>
 #include <macros.h>
@@ -84,5 +84,5 @@
  * @param icall Call data of the request that opened the connection.
  */
-static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void rd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -123,12 +123,15 @@
 	while (true) {
 		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!IPC_GET_IMETHOD(call)) {
 			/*
 			 * The other side has hung up.
-			 * Answer the message and exit the fibril.
+			 * Exit the fibril.
 			 */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
@@ -232,5 +235,5 @@
 	    (void *) rd_ph_addr, rd_size);
 	
-	int rc = devmap_driver_register(NAME, rd_connection);
+	int rc = loc_server_register(NAME, rd_connection);
 	if (rc < 0) {
 		printf("%s: Unable to register driver (%d)\n", NAME, rc);
@@ -238,10 +241,10 @@
 	}
 	
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register("bd/initrd", &devmap_handle) != EOK) {
-		printf("%s: Unable to register device\n", NAME);
-		return false;
-	}
-
+	service_id_t service_id;
+	if (loc_service_register("bd/initrd", &service_id) != EOK) {
+		printf("%s: Unable to register device service\n", NAME);
+		return false;
+	}
+	
 	fibril_rwlock_initialize(&rd_lock);
 	
@@ -258,5 +261,5 @@
 	printf("%s: Accepting connections\n", NAME);
 	async_manager();
-
+	
 	/* Never reached */
 	return 0;
Index: uspace/srv/clip/clip.c
===================================================================
--- uspace/srv/clip/clip.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/clip/clip.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,5 +30,5 @@
 #include <bool.h>
 #include <async.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <ipc/services.h>
 #include <ipc/clipboard.h>
@@ -148,18 +148,17 @@
 }
 
-static void clip_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void clip_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	/* Accept connection */
 	async_answer_0(iid, EOK);
 	
-	bool cont = true;
-	while (cont) {
+	while (true) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case CLIPBOARD_PUT_DATA:
 			clip_put_data(callid, &call);
@@ -179,5 +178,5 @@
 int main(int argc, char *argv[])
 {
-	printf(NAME ": HelenOS clipboard service\n");
+	printf("%s: HelenOS clipboard service\n", NAME);
 	
 	async_set_client_connection(clip_connection);
@@ -186,5 +185,6 @@
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
 	
Index: uspace/srv/devman/Makefile
===================================================================
--- uspace/srv/devman/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/devman/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../..
 BINARY = devman
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/devman/devman.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -34,8 +34,10 @@
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <io/log.h>
 #include <ipc/driver.h>
 #include <ipc/devman.h>
-#include <devmap.h>
+#include <loc.h>
 #include <str_error.h>
+#include <stdio.h>
 
 #include "devman.h"
@@ -64,19 +66,9 @@
 }
 
-static int devmap_functions_compare(unsigned long key[], hash_count_t keys,
+static int loc_functions_compare(unsigned long key[], hash_count_t keys,
     link_t *item)
 {
-	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun);
-	return (fun->devmap_handle == (devmap_handle_t) key[0]);
-}
-
-static int devmap_devices_class_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	dev_class_info_t *class_info
-	    = hash_table_get_instance(item, dev_class_info_t, devmap_link);
-	assert(class_info != NULL);
-
-	return (class_info->devmap_handle == (devmap_handle_t) key[0]);
+	fun_node_t *fun = hash_table_get_instance(item, fun_node_t, loc_fun);
+	return (fun->service_id == (service_id_t) key[0]);
 }
 
@@ -97,13 +89,7 @@
 };
 
-static hash_table_operations_t devmap_devices_ops = {
+static hash_table_operations_t loc_devices_ops = {
 	.hash = devices_hash,
-	.compare = devmap_functions_compare,
-	.remove_callback = devices_remove_callback
-};
-
-static hash_table_operations_t devmap_devices_class_ops = {
-	.hash = devices_hash,
-	.compare = devmap_devices_class_compare,
+	.compare = loc_functions_compare,
 	.remove_callback = devices_remove_callback
 };
@@ -146,6 +132,6 @@
 	fibril_mutex_unlock(&drivers_list->drivers_mutex);
 
-	printf(NAME": the '%s' driver was added to the list of available "
-	    "drivers.\n", drv->name);
+	log_msg(LVL_NOTE, "Driver `%s' was added to the list of available "
+	    "drivers.", drv->name);
 }
 
@@ -237,5 +223,5 @@
 bool read_match_ids(const char *conf_path, match_id_list_t *ids)
 {
-	printf(NAME ": read_match_ids conf_path = %s.\n", conf_path);
+	log_msg(LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path);
 	
 	bool suc = false;
@@ -247,5 +233,6 @@
 	fd = open(conf_path, O_RDONLY);
 	if (fd < 0) {
-		printf(NAME ": unable to open %s\n", conf_path);
+		log_msg(LVL_ERROR, "Unable to open `%s' for reading: %s.",
+		    conf_path, str_error(fd));
 		goto cleanup;
 	}
@@ -255,5 +242,6 @@
 	lseek(fd, 0, SEEK_SET);
 	if (len == 0) {
-		printf(NAME ": configuration file '%s' is empty.\n", conf_path);
+		log_msg(LVL_ERROR, "Configuration file '%s' is empty.",
+		    conf_path);
 		goto cleanup;
 	}
@@ -261,14 +249,16 @@
 	buf = malloc(len + 1);
 	if (buf == NULL) {
-		printf(NAME ": memory allocation failed when parsing file "
-		    "'%s'.\n", conf_path);
+		log_msg(LVL_ERROR, "Memory allocation failed when parsing file "
+		    "'%s'.", conf_path);
 		goto cleanup;
 	}
 	
-	if (read(fd, buf, len) <= 0) {
-		printf(NAME ": unable to read file '%s'.\n", conf_path);
+	ssize_t read_bytes = read_all(fd, buf, len);
+	if (read_bytes <= 0) {
+		log_msg(LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
+		    read_bytes);
 		goto cleanup;
 	}
-	buf[len] = 0;
+	buf[read_bytes] = 0;
 	
 	suc = parse_match_ids(buf, ids);
@@ -305,5 +295,5 @@
 bool get_driver_info(const char *base_path, const char *name, driver_t *drv)
 {
-	printf(NAME ": get_driver_info base_path = %s, name = %s.\n",
+	log_msg(LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")",
 	    base_path, name);
 	
@@ -337,5 +327,6 @@
 	struct stat s;
 	if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */
-		printf(NAME ": driver not found at path %s.", drv->binary_path);
+		log_msg(LVL_ERROR, "Driver not found at path `%s'.",
+		    drv->binary_path);
 		goto cleanup;
 	}
@@ -364,5 +355,5 @@
 int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path)
 {
-	printf(NAME ": lookup_available_drivers, dir = %s \n", dir_path);
+	log_msg(LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path);
 	
 	int drv_cnt = 0;
@@ -398,5 +389,5 @@
 	dev_node_t *dev;
 	
-	printf(NAME ": create_root_nodes\n");
+	log_msg(LVL_DEBUG, "create_root_nodes()");
 	
 	fibril_rwlock_write_lock(&tree->rwlock);
@@ -415,7 +406,7 @@
 	}
 	
-	insert_fun_node(tree, fun, clone_string(""), NULL);
+	insert_fun_node(tree, fun, str_dup(""), NULL);
 	match_id_t *id = create_match_id();
-	id->id = clone_string("root");
+	id->id = str_dup("root");
 	id->score = 100;
 	add_match_id(&fun->match_ids, id);
@@ -460,6 +451,5 @@
 	fibril_mutex_lock(&drivers_list->drivers_mutex);
 	
-	link_t *link = drivers_list->drivers.next;
-	while (link != &drivers_list->drivers) {
+	list_foreach(drivers_list->drivers, link) {
 		drv = list_get_instance(link, driver_t, drivers);
 		score = get_match_score(drv, node);
@@ -468,5 +458,4 @@
 			best_drv = drv;
 		}
-		link = link->next;
 	}
 	
@@ -483,6 +472,6 @@
 void attach_driver(dev_node_t *dev, driver_t *drv)
 {
-	printf(NAME ": attach_driver %s to device %s\n",
-	    drv->name, dev->pfun->pathname);
+	log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")",
+	    dev->pfun->pathname, drv->name);
 	
 	fibril_mutex_lock(&drv->driver_mutex);
@@ -506,10 +495,10 @@
 	assert(fibril_mutex_is_locked(&drv->driver_mutex));
 	
-	printf(NAME ": start_driver '%s'\n", drv->name);
+	log_msg(LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name);
 	
 	rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL);
 	if (rc != EOK) {
-		printf(NAME ": error spawning %s (%s)\n",
-		    drv->name, str_error(rc));
+		log_msg(LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.",
+		    drv->name, drv->binary_path, str_error(rc));
 		return false;
 	}
@@ -530,10 +519,8 @@
 	driver_t *res = NULL;
 	driver_t *drv = NULL;
-	link_t *link;
 	
 	fibril_mutex_lock(&drv_list->drivers_mutex);
 	
-	link = drv_list->drivers.next;
-	while (link != &drv_list->drivers) {
+	list_foreach(drv_list->drivers, link) {
 		drv = list_get_instance(link, driver_t, drivers);
 		if (str_cmp(drv->name, drv_name) == 0) {
@@ -541,6 +528,4 @@
 			break;
 		}
-
-		link = link->next;
 	}
 	
@@ -548,17 +533,4 @@
 	
 	return res;
-}
-
-/** Remember the driver's phone.
- *
- * @param driver	The driver.
- * @param phone		The phone to the driver.
- */
-void set_driver_phone(driver_t *driver, sysarg_t phone)
-{
-	fibril_mutex_lock(&driver->driver_mutex);
-	assert(driver->state == DRIVER_STARTING);
-	driver->phone = phone;
-	fibril_mutex_unlock(&driver->driver_mutex);
 }
 
@@ -571,16 +543,9 @@
 	dev_node_t *dev;
 	link_t *link;
-	int phone;
-
-	printf(NAME ": pass_devices_to_driver(`%s')\n", driver->name);
+
+	log_msg(LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")",
+	    driver->name);
 
 	fibril_mutex_lock(&driver->driver_mutex);
-
-	phone = async_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
-
-	if (phone < 0) {
-		fibril_mutex_unlock(&driver->driver_mutex);
-		return;
-	}
 
 	/*
@@ -588,6 +553,6 @@
 	 * that has not been passed to the driver.
 	 */
-	link = driver->devices.next;
-	while (link != &driver->devices) {
+	link = driver->devices.head.next;
+	while (link != &driver->devices.head) {
 		dev = list_get_instance(link, dev_node_t, driver_devices);
 		if (dev->passed_to_driver) {
@@ -608,5 +573,5 @@
 		fibril_mutex_unlock(&driver->driver_mutex);
 
-		add_device(phone, driver, dev, tree);
+		add_device(driver, dev, tree);
 
 		/*
@@ -626,8 +591,6 @@
 		 * Restart the cycle to go through all devices again.
 		 */
-		link = driver->devices.next;
-	}
-
-	async_hangup(phone);
+		link = driver->devices.head.next;
+	}
 
 	/*
@@ -640,5 +603,5 @@
 	 * immediately and possibly started here as well.
 	 */
-	printf(NAME ": driver %s goes into running state.\n", driver->name);
+	log_msg(LVL_DEBUG, "Driver `%s' enters running state.", driver->name);
 	driver->state = DRIVER_RUNNING;
 
@@ -657,5 +620,6 @@
 void initialize_running_driver(driver_t *driver, dev_tree_t *tree)
 {
-	printf(NAME ": initialize_running_driver (`%s')\n", driver->name);
+	log_msg(LVL_DEBUG, "initialize_running_driver(driver=\"%s\")",
+	    driver->name);
 	
 	/*
@@ -678,4 +642,5 @@
 	list_initialize(&drv->devices);
 	fibril_mutex_initialize(&drv->driver_mutex);
+	drv->sess = NULL;
 }
 
@@ -708,30 +673,30 @@
 }
 
-/** Create devmap path and name for the function. */
-void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
-{
-	char *devmap_pathname = NULL;
-	char *devmap_name = NULL;
-	
-	asprintf(&devmap_name, "%s", fun->pathname);
-	if (devmap_name == NULL)
+/** Create loc path and name for the function. */
+void loc_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
+{
+	char *loc_pathname = NULL;
+	char *loc_name = NULL;
+	
+	asprintf(&loc_name, "%s", fun->pathname);
+	if (loc_name == NULL)
 		return;
 	
-	replace_char(devmap_name, '/', DEVMAP_SEPARATOR);
-	
-	asprintf(&devmap_pathname, "%s/%s", DEVMAP_DEVICE_NAMESPACE,
-	    devmap_name);
-	if (devmap_pathname == NULL) {
-		free(devmap_name);
+	replace_char(loc_name, '/', LOC_SEPARATOR);
+	
+	asprintf(&loc_pathname, "%s/%s", LOC_DEVICE_NAMESPACE,
+	    loc_name);
+	if (loc_pathname == NULL) {
+		free(loc_name);
 		return;
 	}
 	
-	devmap_device_register_with_iface(devmap_pathname,
-	    &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
-	
-	tree_add_devmap_function(tree, fun);
-	
-	free(devmap_name);
-	free(devmap_pathname);
+	loc_service_register_with_iface(loc_pathname,
+	    &fun->service_id, DEVMAN_CONNECT_FROM_LOC);
+	
+	tree_add_loc_function(tree, fun);
+	
+	free(loc_name);
+	free(loc_pathname);
 }
 
@@ -741,5 +706,5 @@
  * @param node		The device's node in the device tree.
  */
-void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
+void add_device(driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
 {
 	/*
@@ -747,9 +712,6 @@
 	 * access any structures that would affect driver_t.
 	 */
-	printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name,
-	    dev->pfun->name);
-	
-	sysarg_t rc;
-	ipc_call_t answer;
+	log_msg(LVL_DEBUG, "add_device(drv=\"%s\", dev=\"%s\")",
+	    drv->name, dev->pfun->name);
 	
 	/* Send the device to the driver. */
@@ -760,11 +722,17 @@
 		parent_handle = 0;
 	}
-
-	aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle,
+	
+	async_exch_t *exch = async_exchange_begin(drv->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, DRIVER_ADD_DEVICE, dev->handle,
 	    parent_handle, &answer);
 	
-	/* Send the device's name to the driver. */
-	rc = async_data_write_start(phone, dev->pfun->name,
+	/* Send the device name to the driver. */
+	sysarg_t rc = async_data_write_start(exch, dev->pfun->name,
 	    str_size(dev->pfun->name) + 1);
+	
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
 		/* TODO handle error */
@@ -809,5 +777,5 @@
 	driver_t *drv = find_best_match_driver(drivers_list, dev);
 	if (drv == NULL) {
-		printf(NAME ": no driver found for device '%s'.\n",
+		log_msg(LVL_ERROR, "No driver found for device `%s'.",
 		    dev->pfun->pathname);
 		return false;
@@ -825,12 +793,7 @@
 	fibril_mutex_unlock(&drv->driver_mutex);
 
-	if (is_running) {
-		/* Notify the driver about the new device. */
-		int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
-		if (phone >= 0) {
-			add_device(phone, drv, dev, tree);
-			async_hangup(phone);
-		}
-	}
+	/* Notify the driver about the new device. */
+	if (is_running)
+		add_device(drv, dev, tree);
 	
 	return true;
@@ -847,5 +810,5 @@
 bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
 {
-	printf(NAME ": init_device_tree.\n");
+	log_msg(LVL_DEBUG, "init_device_tree()");
 	
 	tree->current_handle = 0;
@@ -855,6 +818,6 @@
 	hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1,
 	    &devman_functions_ops);
-	hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1,
-	    &devmap_devices_ops);
+	hash_table_create(&tree->loc_functions, DEVICE_BUCKETS, 1,
+	    &loc_devices_ops);
 	
 	fibril_rwlock_initialize(&tree->rwlock);
@@ -935,4 +898,35 @@
 }
 
+/** Get list of device functions. */
+int dev_get_functions(dev_tree_t *tree, dev_node_t *dev,
+    devman_handle_t *hdl_buf, size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+
+	buf_cnt = buf_size / sizeof(devman_handle_t);
+
+	act_cnt = list_count(&dev->functions);
+	*act_size = act_cnt * sizeof(devman_handle_t);
+
+	if (buf_size % sizeof(devman_handle_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(dev->functions, item) {
+		fun_node_t *fun =
+		    list_get_instance(item, fun_node_t, dev_functions);
+
+		if (pos < buf_cnt)
+			hdl_buf[pos] = fun->handle;
+		pos++;
+	}
+
+	return EOK;
+}
+
+
 /* Function nodes */
 
@@ -949,7 +943,6 @@
 		link_initialize(&res->dev_functions);
 		list_initialize(&res->match_ids.ids);
-		list_initialize(&res->classes);
 		link_initialize(&res->devman_fun);
-		link_initialize(&res->devmap_fun);
+		link_initialize(&res->loc_fun);
 	}
 	
@@ -1026,5 +1019,5 @@
 	fun->pathname = (char *) malloc(pathsize);
 	if (fun->pathname == NULL) {
-		printf(NAME ": failed to allocate device path.\n");
+		log_msg(LVL_ERROR, "Failed to allocate device path.");
 		return false;
 	}
@@ -1057,4 +1050,7 @@
 	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
 	
+	log_msg(LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])",
+	    dev, pfun, pfun->pathname);
+
 	/* Add the node to the handle-to-node map. */
 	dev->handle = ++tree->current_handle;
@@ -1063,5 +1059,4 @@
 
 	/* Add the node to the list of its parent's children. */
-	printf("insert_dev_node: dev=%p, dev->pfun := %p\n", dev, pfun);
 	dev->pfun = pfun;
 	pfun->child = dev;
@@ -1112,4 +1107,24 @@
 	
 	return true;
+}
+
+/** Remove function from device tree.
+ *
+ * @param tree		Device tree
+ * @param node		Function node to remove
+ */
+void remove_fun_node(dev_tree_t *tree, fun_node_t *fun)
+{
+	assert(tree != NULL);
+	assert(fun != NULL);
+	assert(fibril_rwlock_is_write_locked(&tree->rwlock));
+	
+	/* Remove the node from the handle-to-node map. */
+	unsigned long key = fun->handle;
+	hash_table_remove(&tree->devman_functions, &key, 1);
+	
+	/* Remove the node from the list of its parent's children. */
+	if (fun->dev != NULL)
+		list_remove(&fun->dev_functions);
 }
 
@@ -1123,4 +1138,11 @@
 fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path)
 {
+	assert(path != NULL);
+
+	bool is_absolute = path[0] == '/';
+	if (!is_absolute) {
+		return NULL;
+	}
+
 	fibril_rwlock_read_lock(&tree->rwlock);
 	
@@ -1132,5 +1154,5 @@
 	char *rel_path = path;
 	char *next_path_elem = NULL;
-	bool cont = (rel_path[0] == '/');
+	bool cont = (rel_path[1] != '\0');
 	
 	while (cont && fun != NULL) {
@@ -1157,4 +1179,30 @@
 }
 
+/** Find function with a specified name belonging to given device.
+ *
+ * Device tree rwlock should be held at least for reading.
+ *
+ * @param dev Device the function belongs to.
+ * @param name Function name (not path).
+ * @return Function node.
+ * @retval NULL No function with given name.
+ */
+fun_node_t *find_fun_node_in_device(dev_node_t *dev, const char *name)
+{
+	assert(dev != NULL);
+	assert(name != NULL);
+
+	fun_node_t *fun;
+
+	list_foreach(dev->functions, link) {
+		fun = list_get_instance(link, fun_node_t, dev_functions);
+
+		if (str_cmp(name, fun->name) == 0)
+			return fun;
+	}
+
+	return NULL;
+}
+
 /** Find child function node with a specified name.
  *
@@ -1167,201 +1215,19 @@
 fun_node_t *find_node_child(fun_node_t *pfun, const char *name)
 {
-	fun_node_t *fun;
-	link_t *link;
-	
-	link = pfun->child->functions.next;
-	
-	while (link != &pfun->child->functions) {
-		fun = list_get_instance(link, fun_node_t, dev_functions);
-		
-		if (str_cmp(name, fun->name) == 0)
-			return fun;
-		
-		link = link->next;
-	}
-	
-	return NULL;
-}
-
-/* Device classes */
-
-/** Create device class.
- *
- * @return	Device class.
- */
-dev_class_t *create_dev_class(void)
-{
-	dev_class_t *cl;
-	
-	cl = (dev_class_t *) malloc(sizeof(dev_class_t));
-	if (cl != NULL) {
-		memset(cl, 0, sizeof(dev_class_t));
-		list_initialize(&cl->devices);
-		fibril_mutex_initialize(&cl->mutex);
-	}
-	
-	return cl;
-}
-
-/** Create device class info.
- *
- * @return		Device class info.
- */
-dev_class_info_t *create_dev_class_info(void)
-{
-	dev_class_info_t *info;
-	
-	info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));
-	if (info != NULL) {
-		memset(info, 0, sizeof(dev_class_info_t));
-		link_initialize(&info->dev_classes);
-		link_initialize(&info->devmap_link);
-		link_initialize(&info->link);
-	}
-	
-	return info;
-}
-
-size_t get_new_class_dev_idx(dev_class_t *cl)
-{
-	size_t dev_idx;
-	
-	fibril_mutex_lock(&cl->mutex);
-	dev_idx = ++cl->curr_dev_idx;
-	fibril_mutex_unlock(&cl->mutex);
-	
-	return dev_idx;
-}
-
-
-/** Create unique device name within the class.
- *
- * @param cl		The class.
- * @param base_dev_name	Contains the base name for the device if it was
- *			specified by the driver when it registered the device by
- *			the class; NULL if driver specified no base name.
- * @return		The unique name for the device within the class.
- */
-char *create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name)
-{
-	char *dev_name;
-	const char *base_name;
-	
-	if (base_dev_name != NULL)
-		base_name = base_dev_name;
-	else
-		base_name = cl->base_dev_name;
-	
-	size_t idx = get_new_class_dev_idx(cl);
-	asprintf(&dev_name, "%s%zu", base_name, idx);
-	
-	return dev_name;
-}
-
-/** Add the device function to the class.
- *
- * The device may be added to multiple classes and a class may contain multiple
- * devices. The class and the device are associated with each other by the
- * dev_class_info_t structure.
- *
- * @param dev		The device.
- * @param class		The class.
- * @param base_dev_name	The base name of the device within the class if
- *			specified by the driver, NULL otherwise.
- * @return		dev_class_info_t structure which associates the device
- *			with the class.
- */
-dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,
-    const char *base_dev_name)
-{
-	dev_class_info_t *info;
-
-	assert(fun != NULL);
-	assert(cl != NULL);
-
-	info = create_dev_class_info();
-
-	
-	if (info != NULL) {
-		info->dev_class = cl;
-		info->fun = fun;
-		
-		/* Add the device to the class. */
-		fibril_mutex_lock(&cl->mutex);
-		list_append(&info->link, &cl->devices);
-		fibril_mutex_unlock(&cl->mutex);
-		
-		/* Add the class to the device. */
-		list_append(&info->dev_classes, &fun->classes);
-		
-		/* Create unique name for the device within the class. */
-		info->dev_name = create_dev_name_for_class(cl, base_dev_name);
-	}
-	
-	return info;
-}
-
-dev_class_t *get_dev_class(class_list_t *class_list, char *class_name)
-{
-	dev_class_t *cl;
-	
-	fibril_rwlock_write_lock(&class_list->rwlock);
-	cl = find_dev_class_no_lock(class_list, class_name);
-	if (cl == NULL) {
-		cl = create_dev_class();
-		if (cl != NULL) {
-			cl->name = class_name;
-			cl->base_dev_name = "";
-			add_dev_class_no_lock(class_list, cl);
-		}
-	}
-
-	fibril_rwlock_write_unlock(&class_list->rwlock);
-	return cl;
-}
-
-dev_class_t *find_dev_class_no_lock(class_list_t *class_list,
-    const char *class_name)
-{
-	dev_class_t *cl;
-	link_t *link = class_list->classes.next;
-	
-	while (link != &class_list->classes) {
-		cl = list_get_instance(link, dev_class_t, link);
-		if (str_cmp(cl->name, class_name) == 0) {
-			return cl;
-		}
-		link = link->next;
-	}
-	
-	return NULL;
-}
-
-void add_dev_class_no_lock(class_list_t *class_list, dev_class_t *cl)
-{
-	list_append(&cl->link, &class_list->classes);
-}
-
-void init_class_list(class_list_t *class_list)
-{
-	list_initialize(&class_list->classes);
-	fibril_rwlock_initialize(&class_list->rwlock);
-	hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1,
-	    &devmap_devices_class_ops);
-}
-
-
-/* Devmap devices */
-
-fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle)
+	return find_fun_node_in_device(pfun->child, name);
+}
+
+/* loc devices */
+
+fun_node_t *find_loc_tree_function(dev_tree_t *tree, service_id_t service_id)
 {
 	fun_node_t *fun = NULL;
 	link_t *link;
-	unsigned long key = (unsigned long) devmap_handle;
+	unsigned long key = (unsigned long) service_id;
 	
 	fibril_rwlock_read_lock(&tree->rwlock);
-	link = hash_table_find(&tree->devmap_functions, &key);
+	link = hash_table_find(&tree->loc_functions, &key);
 	if (link != NULL)
-		fun = hash_table_get_instance(link, fun_node_t, devmap_fun);
+		fun = hash_table_get_instance(link, fun_node_t, loc_fun);
 	fibril_rwlock_read_unlock(&tree->rwlock);
 	
@@ -1369,40 +1235,9 @@
 }
 
-fun_node_t *find_devmap_class_function(class_list_t *classes,
-    devmap_handle_t devmap_handle)
-{
-	fun_node_t *fun = NULL;
-	dev_class_info_t *cli;
-	link_t *link;
-	unsigned long key = (unsigned long)devmap_handle;
-	
-	fibril_rwlock_read_lock(&classes->rwlock);
-	link = hash_table_find(&classes->devmap_functions, &key);
-	if (link != NULL) {
-		cli = hash_table_get_instance(link, dev_class_info_t,
-		    devmap_link);
-		fun = cli->fun;
-	}
-	fibril_rwlock_read_unlock(&classes->rwlock);
-	
-	return fun;
-}
-
-void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli)
-{
-	unsigned long key = (unsigned long) cli->devmap_handle;
-	
-	fibril_rwlock_write_lock(&class_list->rwlock);
-	hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link);
-	fibril_rwlock_write_unlock(&class_list->rwlock);
-
-	assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL);
-}
-
-void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun)
-{
-	unsigned long key = (unsigned long) fun->devmap_handle;
+void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun)
+{
+	unsigned long key = (unsigned long) fun->service_id;
 	fibril_rwlock_write_lock(&tree->rwlock);
-	hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun);
+	hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun);
 	fibril_rwlock_write_unlock(&tree->rwlock);
 }
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/devman/devman.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -41,7 +42,8 @@
 #include <adt/hash_table.h>
 #include <ipc/devman.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <fibril_synch.h>
 #include <atomic.h>
+#include <async.h>
 
 #include "util.h"
@@ -52,7 +54,6 @@
 #define DEVICE_BUCKETS 256
 
-#define DEVMAP_CLASS_NAMESPACE "class"
-#define DEVMAP_DEVICE_NAMESPACE "devices"
-#define DEVMAP_SEPARATOR '\\'
+#define LOC_DEVICE_NAMESPACE "devices"
+#define LOC_SEPARATOR '\\'
 
 struct dev_node;
@@ -87,6 +88,6 @@
 	int state;
 	
-	/** Phone asociated with this driver. */
-	sysarg_t phone;
+	/** Session asociated with this driver. */
+	async_sess_t *sess;
 	/** Name of the device driver. */
 	char *name;
@@ -95,9 +96,9 @@
 	/** List of device ids for device-to-driver matching. */
 	match_id_list_t match_ids;
-	/** Pointer to the linked list of devices controlled by this driver. */
-	link_t devices;
-	
-	/**
-	 * Fibril mutex for this driver - driver state, list of devices, phone.
+	/** List of devices controlled by this driver. */
+	list_t devices;
+	
+	/**
+	 * Fibril mutex for this driver - driver state, list of devices, session.
 	 */
 	fibril_mutex_t driver_mutex;
@@ -107,5 +108,5 @@
 typedef struct driver_list {
 	/** List of drivers */
-	link_t drivers;
+	list_t drivers;
 	/** Fibril mutex for list of drivers. */
 	fibril_mutex_t drivers_mutex;
@@ -129,5 +130,5 @@
 	
 	/** List of device functions. */
-	link_t functions;
+	list_t functions;
 	/** Driver of this device. */
 	driver_t *drv;
@@ -154,4 +155,6 @@
 	/** Name of the function, assigned by the device driver */
 	char *name;
+	/** Function type */
+	fun_type_t ftype;
 	
 	/** Full path and name of the device in device hierarchy */
@@ -169,8 +172,6 @@
 	match_id_list_t match_ids;
 	
-	/** The list of device classes to which this device function belongs. */
-	link_t classes;
-	/** Devmap handle if the device function is registered by devmap. */
-	devmap_handle_t devmap_handle;
+	/** Service ID if the device function is registered with loc. */
+	service_id_t service_id;
 	
 	/**
@@ -180,7 +181,7 @@
 	
 	/**
-	 * Used by the hash table of functions indexed by devmap device handles.
-	 */
-	link_t devmap_fun;
+	 * Used by the hash table of functions indexed by service IDs.
+	 */
+	link_t loc_fun;
 };
 
@@ -207,87 +208,9 @@
 	
 	/**
-	 * Hash table of devices registered by devmapper, indexed by devmap
-	 * handles.
-	 */
-	hash_table_t devmap_functions;
+	 * Hash table of services registered with location service, indexed by
+	 * service IDs.
+	 */
+	hash_table_t loc_functions;
 } dev_tree_t;
-
-typedef struct dev_class {
-	/** The name of the class. */
-	const char *name;
-	
-	/**
-	 * Pointer to the previous and next class in the list of registered
-	 * classes.
-	 */
-	link_t link;
-	
-	/**
-	 * List of dev_class_info structures - one for each device registered by
-	 * this class.
-	 */
-	link_t devices;
-	
-	/**
-	 * Default base name for the device within the class, might be overrided
-	 * by the driver.
-	 */
-	const char *base_dev_name;
-	
-	/** Unique numerical identifier of the newly added device. */
-	size_t curr_dev_idx;
-	/** Synchronize access to the list of devices in this class. */
-	fibril_mutex_t mutex;
-} dev_class_t;
-
-/**
- * Provides n-to-m mapping between function nodes and classes - each function
- * can register in an arbitrary number of classes and each class can contain
- * an arbitrary number of device functions.
- */
-typedef struct dev_class_info {
-	/** The class. */
-	dev_class_t *dev_class;
-	/** The device. */
-	fun_node_t *fun;
-	
-	/**
-	 * Pointer to the previous and next class info in the list of devices
-	 * registered by the class.
-	 */
-	link_t link;
-	
-	/**
-	 * Pointer to the previous and next class info in the list of classes
-	 * by which the device is registered.
-	 */
-	link_t dev_classes;
-	
-	/** The name of the device function within the class. */
-	char *dev_name;
-	/** The handle of the device by device mapper in the class namespace. */
-	devmap_handle_t devmap_handle;
-	
-	/**
-	 * Link in the hash table of devices registered by the devmapper using
-	 * their class names.
-	 */
-	link_t devmap_link;
-} dev_class_info_t;
-
-/** The list of device classes. */
-typedef struct class_list {
-	/** List of classes. */
-	link_t classes;
-	
-	/**
-	 * Hash table of devices registered by devmapper using their class name,
-	 * indexed by devmap handles.
-	 */
-	hash_table_t devmap_functions;
-	
-	/** Fibril mutex for list of classes. */
-	fibril_rwlock_t rwlock;
-} class_list_t;
 
 /* Match ids and scores */
@@ -312,9 +235,8 @@
 extern void add_driver(driver_list_t *, driver_t *);
 extern void attach_driver(dev_node_t *, driver_t *);
-extern void add_device(int, driver_t *, dev_node_t *, dev_tree_t *);
+extern void add_device(driver_t *, dev_node_t *, dev_tree_t *);
 extern bool start_driver(driver_t *);
 
 extern driver_t *find_driver(driver_list_t *, const char *);
-extern void set_driver_phone(driver_t *, sysarg_t);
 extern void initialize_running_driver(driver_t *, dev_tree_t *);
 
@@ -331,4 +253,6 @@
 extern dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
 extern dev_node_t *find_dev_function(dev_node_t *, const char *);
+extern int dev_get_functions(dev_tree_t *tree, dev_node_t *, devman_handle_t *,
+    size_t, size_t *);
 
 extern fun_node_t *create_fun_node(void);
@@ -338,4 +262,5 @@
 extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle);
 extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *);
+extern fun_node_t *find_fun_node_in_device(dev_node_t *, const char *);
 
 /* Device tree */
@@ -345,29 +270,13 @@
 extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *);
 extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *);
-
-/* Device classes */
-
-extern dev_class_t *create_dev_class(void);
-extern dev_class_info_t *create_dev_class_info(void);
-extern size_t get_new_class_dev_idx(dev_class_t *);
-extern char *create_dev_name_for_class(dev_class_t *, const char *);
-extern dev_class_info_t *add_function_to_class(fun_node_t *, dev_class_t *,
-    const char *);
-
-extern void init_class_list(class_list_t *);
-
-extern dev_class_t *get_dev_class(class_list_t *, char *);
-extern dev_class_t *find_dev_class_no_lock(class_list_t *, const char *);
-extern void add_dev_class_no_lock(class_list_t *, dev_class_t *);
-
-/* Devmap devices */
-
-extern void devmap_register_tree_function(fun_node_t *, dev_tree_t *);
-
-extern fun_node_t *find_devmap_tree_function(dev_tree_t *, devmap_handle_t);
-extern fun_node_t *find_devmap_class_function(class_list_t *, devmap_handle_t);
-
-extern void class_add_devmap_function(class_list_t *, dev_class_info_t *);
-extern void tree_add_devmap_function(dev_tree_t *, fun_node_t *);
+extern void remove_fun_node(dev_tree_t *, fun_node_t *);
+
+/* Loc services */
+
+extern void loc_register_tree_function(fun_node_t *, dev_tree_t *);
+
+extern fun_node_t *find_loc_tree_function(dev_tree_t *, service_id_t);
+
+extern void tree_add_loc_function(dev_tree_t *, fun_node_t *);
 
 #endif
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/devman/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,8 +39,9 @@
 #include <assert.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <stdio.h>
 #include <errno.h>
+#include <str_error.h>
 #include <bool.h>
 #include <fibril_synch.h>
@@ -51,8 +52,9 @@
 #include <sys/stat.h>
 #include <ctype.h>
+#include <io/log.h>
 #include <ipc/devman.h>
 #include <ipc/driver.h>
 #include <thread.h>
-#include <devmap.h>
+#include <loc.h>
 
 #include "devman.h"
@@ -62,5 +64,4 @@
 static driver_list_t drivers_list;
 static dev_tree_t device_tree;
-static class_list_t class_list;
 
 /** Register running driver. */
@@ -71,5 +72,5 @@
 	driver_t *driver = NULL;
 
-	printf(NAME ": devman_driver_register \n");
+	log_msg(LVL_DEBUG, "devman_driver_register");
 	
 	iid = async_get_call(&icall);
@@ -88,12 +89,11 @@
 	}
 
-	printf(NAME ": the %s driver is trying to register by the service.\n",
+	log_msg(LVL_DEBUG, "The `%s' driver is trying to register.",
 	    drv_name);
 	
 	/* Find driver structure. */
 	driver = find_driver(&drivers_list, drv_name);
-	
 	if (driver == NULL) {
-		printf(NAME ": no driver named %s was found.\n", drv_name);
+		log_msg(LVL_ERROR, "No driver named `%s' was found.", drv_name);
 		free(drv_name);
 		drv_name = NULL;
@@ -105,21 +105,46 @@
 	drv_name = NULL;
 	
+	fibril_mutex_lock(&driver->driver_mutex);
+	
+	if (driver->sess) {
+		/* We already have a connection to the driver. */
+		log_msg(LVL_ERROR, "Driver '%s' already started.\n",
+		    driver->name);
+		fibril_mutex_unlock(&driver->driver_mutex);
+		async_answer_0(iid, EEXISTS);
+		return NULL;
+	}
+	
+	switch (driver->state) {
+	case DRIVER_NOT_STARTED:
+		/* Somebody started the driver manually. */
+		log_msg(LVL_NOTE, "Driver '%s' started manually.\n",
+		    driver->name);
+		driver->state = DRIVER_STARTING;
+		break;
+	case DRIVER_STARTING:
+		/* The expected case */
+		break;
+	case DRIVER_RUNNING:
+		/* Should not happen since we do not have a connected session */
+		assert(false);
+	}
+	
 	/* Create connection to the driver. */
-	printf(NAME ":  creating connection to the %s driver.\n", driver->name);
-	ipc_call_t call;
-	ipc_callid_t callid = async_get_call(&call);
-	if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
-		async_answer_0(callid, ENOTSUP);
+	log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.",
+	    driver->name);
+	driver->sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (!driver->sess) {
+		fibril_mutex_unlock(&driver->driver_mutex);
 		async_answer_0(iid, ENOTSUP);
 		return NULL;
 	}
 	
-	/* Remember driver's phone. */
-	set_driver_phone(driver, IPC_GET_ARG5(call));
-	
-	printf(NAME ": the %s driver was successfully registered as running.\n",
+	fibril_mutex_unlock(&driver->driver_mutex);
+	
+	log_msg(LVL_NOTE,
+	    "The `%s' driver was successfully registered as running.",
 	    driver->name);
 	
-	async_answer_0(callid, EOK);
 	async_answer_0(iid, EOK);
 	
@@ -142,6 +167,6 @@
 	callid = async_get_call(&call);
 	if (DEVMAN_ADD_MATCH_ID != IPC_GET_IMETHOD(call)) {
-		printf(NAME ": ERROR: devman_receive_match_id - invalid "
-		    "protocol.\n");
+		log_msg(LVL_ERROR, 
+		    "Invalid protocol when trying to receive match id.");
 		async_answer_0(callid, EINVAL); 
 		delete_match_id(match_id);
@@ -150,6 +175,5 @@
 	
 	if (match_id == NULL) {
-		printf(NAME ": ERROR: devman_receive_match_id - failed to "
-		    "allocate match id.\n");
+		log_msg(LVL_ERROR, "Failed to allocate match id.");
 		async_answer_0(callid, ENOMEM);
 		return ENOMEM;
@@ -165,6 +189,6 @@
 	if (rc != EOK) {
 		delete_match_id(match_id);
-		printf(NAME ": devman_receive_match_id - failed to receive "
-		    "match id string.\n");
+		log_msg(LVL_ERROR, "Failed to receive match id string: %s.",
+		    str_error(rc));
 		return rc;
 	}
@@ -172,5 +196,5 @@
 	list_append(&match_id->link, &match_ids->ids);
 	
-	printf(NAME ": received match id '%s', score = %d \n",
+	log_msg(LVL_DEBUG, "Received match id `%s', score %d.",
 	    match_id->id, match_id->score);
 	return rc;
@@ -228,5 +252,7 @@
 	if (ftype != fun_inner && ftype != fun_exposed) {
 		/* Unknown function type */
-		printf(NAME ": Error, unknown function type provided by driver!\n");
+		log_msg(LVL_ERROR, 
+		    "Unknown function type %d provided by driver.",
+		    (int) ftype);
 
 		fibril_rwlock_write_unlock(&tree->rwlock);
@@ -243,5 +269,17 @@
 	}
 	
+	/* Check that function with same name is not there already. */
+	if (find_fun_node_in_device(pdev, fun_name) != NULL) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		async_answer_0(callid, EEXISTS);
+		printf(NAME ": Warning, driver tried to register `%s' twice.\n",
+		    fun_name);
+		free(fun_name);
+		return;
+	}
+	
 	fun_node_t *fun = create_fun_node();
+	fun->ftype = ftype;
+	
 	if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) {
 		fibril_rwlock_write_unlock(&tree->rwlock);
@@ -265,5 +303,5 @@
 	fibril_rwlock_write_unlock(&tree->rwlock);
 	
-	printf(NAME ": devman_add_function %s\n", fun->pathname);
+	log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
 	
 	devman_receive_match_ids(match_count, &fun->match_ids);
@@ -289,5 +327,5 @@
 		}
 	} else {
-		devmap_register_tree_function(fun, tree);
+		loc_register_tree_function(fun, tree);
 	}
 	
@@ -296,37 +334,13 @@
 }
 
-static void devmap_register_class_dev(dev_class_info_t *cli)
-{
-	/* Create devmap path and name for the device. */
-	char *devmap_pathname = NULL;
-
-	asprintf(&devmap_pathname, "%s/%s%c%s", DEVMAP_CLASS_NAMESPACE,
-	    cli->dev_class->name, DEVMAP_SEPARATOR, cli->dev_name);
-	if (devmap_pathname == NULL)
-		return;
-	
-	/*
-	 * Register the device by the device mapper and remember its devmap
-	 * handle.
-	 */
-	devmap_device_register_with_iface(devmap_pathname,
-	    &cli->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
-	
-	/*
-	 * Add device to the hash map of class devices registered by device
-	 * mapper.
-	 */
-	class_add_devmap_function(&class_list, cli);
-	
-	free(devmap_pathname);
-}
-
-static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call)
+static void devman_add_function_to_cat(ipc_callid_t callid, ipc_call_t *call)
 {
 	devman_handle_t handle = IPC_GET_ARG1(*call);
-	
-	/* Get class name. */
-	char *class_name;
-	int rc = async_data_write_accept((void **) &class_name, true,
+	category_id_t cat_id;
+	int rc;
+	
+	/* Get category name. */
+	char *cat_name;
+	rc = async_data_write_accept((void **) &cat_name, true,
 	    0, 0, 0, 0);
 	if (rc != EOK) {
@@ -341,13 +355,57 @@
 	}
 	
-	dev_class_t *cl = get_dev_class(&class_list, class_name);
-	dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL);
-	
-	/* Register the device's class alias by devmapper. */
-	devmap_register_class_dev(class_info);
-	
-	printf(NAME ": function'%s' added to class '%s', class name '%s' was "
-	    "asigned to it\n", fun->pathname, class_name, class_info->dev_name);
-
+	rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING);
+	if (rc == EOK) {
+		loc_service_add_to_cat(fun->service_id, cat_id);
+	} else {
+		log_msg(LVL_ERROR, "Failed adding function `%s' to category "
+		    "`%s'.", fun->pathname, cat_name);
+	}
+	
+	log_msg(LVL_NOTE, "Function `%s' added to category `%s'.",
+	    fun->pathname, cat_name);
+
+	async_answer_0(callid, EOK);
+}
+
+/** Remove function. */
+static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call)
+{
+	devman_handle_t fun_handle = IPC_GET_ARG1(*call);
+	dev_tree_t *tree = &device_tree;
+	int rc;
+	
+	fibril_rwlock_write_lock(&tree->rwlock);
+	
+	fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle);
+	if (fun == NULL) {
+		fibril_rwlock_write_unlock(&tree->rwlock);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
+	
+	if (fun->ftype == fun_inner) {
+		/* Handle possible descendants */
+		/* TODO */
+		log_msg(LVL_WARN, "devman_remove_function(): not handling "
+		    "descendants\n");
+	} else {
+		/* Unregister from location service */
+		rc = loc_service_unregister(fun->service_id);
+		if (rc != EOK) {
+			log_msg(LVL_ERROR, "Failed unregistering tree service.");
+			fibril_rwlock_write_unlock(&tree->rwlock);
+			async_answer_0(callid, EIO);
+			return;
+		}
+	}
+	
+	remove_fun_node(&device_tree, fun);
+	fibril_rwlock_write_unlock(&tree->rwlock);
+	delete_fun_node(fun);
+	
+	log_msg(LVL_DEBUG, "devman_remove_function() succeeded.");
 	async_answer_0(callid, EOK);
 }
@@ -363,5 +421,5 @@
 	
 	initialize_running_driver(driver, &device_tree);
-	printf(NAME ": the %s driver was successfully initialized. \n",
+	log_msg(LVL_DEBUG, "The `%s` driver was successfully initialized.",
 	    driver->name);
 	return 0;
@@ -385,25 +443,26 @@
 	fid_t fid = fibril_create(init_running_drv, driver);
 	if (fid == 0) {
-		printf(NAME ": Error creating fibril for the initialization of "
-		    "the newly registered running driver.\n");
+		log_msg(LVL_ERROR, "Failed to create initialization fibril " \
+		    "for driver `%s'.", driver->name);
 		return;
 	}
 	fibril_add_ready(fid);
 	
-	ipc_callid_t callid;
-	ipc_call_t call;
-	bool cont = true;
-	while (cont) {
-		callid = async_get_call(&call);
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			break;
 		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case DEVMAN_ADD_FUNCTION:
 			devman_add_function(callid, &call);
 			break;
-		case DEVMAN_ADD_DEVICE_TO_CLASS:
-			devman_add_function_to_class(callid, &call);
+		case DEVMAN_ADD_DEVICE_TO_CATEGORY:
+			devman_add_function_to_cat(callid, &call);
+			break;
+		case DEVMAN_REMOVE_FUNCTION:
+			devman_remove_function(callid, &call);
 			break;
 		default:
@@ -438,4 +497,165 @@
 }
 
+/** Get device name. */
+static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	size_t sent_length = str_size(fun->name);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->name, sent_length);
+	async_answer_0(iid, EOK);
+
+	free(buffer);
+}
+
+
+/** Get device path. */
+static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	size_t sent_length = str_size(fun->pathname);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->pathname, sent_length);
+	async_answer_0(iid, EOK);
+
+	free(buffer);
+}
+
+static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	dev_node_t *dev = find_dev_node_no_lock(&device_tree,
+	    IPC_GET_ARG1(*icall));
+	if (dev == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
+	if (hdl_buf == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	
+	sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
+	free(hdl_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+
+/** Get handle for child device of a function. */
+static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (fun->child == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, fun->child->handle);
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+}
+
+/** Find handle for the function instance identified by its service ID. */
+static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+
+	fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall));
+	
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+
+	async_answer_1(iid, EOK, fun->handle);
+}
 
 /** Function for handling connections from a client to the device manager. */
@@ -445,15 +665,29 @@
 	async_answer_0(iid, EOK);
 	
-	bool cont = true;
-	while (cont) {
+	while (true) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case DEVMAN_DEVICE_GET_HANDLE:
 			devman_function_get_handle(callid, &call);
+			break;
+		case DEVMAN_DEV_GET_FUNCTIONS:
+			devman_dev_get_functions(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_CHILD:
+			devman_fun_get_child(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_NAME:
+			devman_fun_get_name(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_PATH:
+			devman_fun_get_path(callid, &call);
+			break;
+		case DEVMAN_FUN_SID_TO_HANDLE:
+			devman_fun_sid_to_handle(callid, &call);
 			break;
 		default:
@@ -477,7 +711,13 @@
 		dev = fun->dev;
 
-	if (fun == NULL && dev == NULL) {
-		printf(NAME ": devman_forward error - no device or function with "
-		    "handle %" PRIun " was found.\n", handle);
+	/*
+	 * For a valid function to connect to we need a device. The root
+	 * function, for example, has no device and cannot be connected to.
+	 * This means @c dev needs to be valid regardless whether we are
+	 * connecting to a device or to a function.
+	 */
+	if (dev == NULL) {
+		log_msg(LVL_ERROR, "IPC forwarding failed - no device or "
+		    "function with handle %" PRIun " was found.", handle);
 		async_answer_0(iid, ENOENT);
 		return;
@@ -485,6 +725,7 @@
 
 	if (fun == NULL && !drv_to_parent) {
-		printf(NAME ": devman_forward error - cannot connect to "
-		    "handle %" PRIun ", refers to a device.\n", handle);
+		log_msg(LVL_ERROR, NAME ": devman_forward error - cannot "
+		    "connect to handle %" PRIun ", refers to a device.",
+		    handle);
 		async_answer_0(iid, ENOENT);
 		return;
@@ -507,6 +748,6 @@
 	
 	if (driver == NULL) {
-		printf(NAME ": devman_forward error - the device is not in %" PRIun
-		    " usable state.\n", handle);
+		log_msg(LVL_ERROR, "IPC forwarding refused - " \
+		    "the device %" PRIun " is not in usable state.", handle);
 		async_answer_0(iid, ENOENT);
 		return;
@@ -519,8 +760,7 @@
 		method = DRIVER_CLIENT;
 	
-	if (driver->phone <= 0) {
-		printf(NAME ": devman_forward: cound not forward to driver %s ",
-		    driver->name);
-		printf("the driver's phone is %" PRIun ").\n", driver->phone);
+	if (!driver->sess) {
+		log_msg(LVL_ERROR,
+		    "Could not forward to driver `%s'.", driver->name);
 		async_answer_0(iid, EINVAL);
 		return;
@@ -528,27 +768,31 @@
 
 	if (fun != NULL) {
-		printf(NAME ": devman_forward: forward connection to function %s to "
-		    "driver %s.\n", fun->pathname, driver->name);
+		log_msg(LVL_DEBUG, 
+		    "Forwarding request for `%s' function to driver `%s'.",
+		    fun->pathname, driver->name);
 	} else {
-		printf(NAME ": devman_forward: forward connection to device %s to "
-		    "driver %s.\n", dev->pfun->pathname, driver->name);
-	}
-
-	async_forward_fast(iid, driver->phone, method, fwd_h, 0, IPC_FF_NONE);
-}
-
-/** Function for handling connections from a client forwarded by the device
- * mapper to the device manager. */
-static void devman_connection_devmapper(ipc_callid_t iid, ipc_call_t *icall)
-{
-	devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall);
+		log_msg(LVL_DEBUG, 
+		    "Forwarding request for `%s' device to driver `%s'.",
+		    dev->pfun->pathname, driver->name);
+	}
+	
+	async_exch_t *exch = async_exchange_begin(driver->sess);
+	async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE);
+	async_exchange_end(exch);
+}
+
+/** Function for handling connections from a client forwarded by the location
+ * service to the device manager. */
+static void devman_connection_loc(ipc_callid_t iid, ipc_call_t *icall)
+{
+	service_id_t service_id = IPC_GET_ARG2(*icall);
 	fun_node_t *fun;
 	dev_node_t *dev;
 
-	fun = find_devmap_tree_function(&device_tree, devmap_handle);
-	if (fun == NULL)
-		fun = find_devmap_class_function(&class_list, devmap_handle);
+	fun = find_loc_tree_function(&device_tree, service_id);
 	
 	if (fun == NULL || fun->dev->drv == NULL) {
+		log_msg(LVL_WARN, "devman_connection_loc(): function "
+		    "not found.\n");
 		async_answer_0(iid, ENOENT);
 		return;
@@ -557,17 +801,16 @@
 	dev = fun->dev;
 	
-	if (dev->state != DEVICE_USABLE || dev->drv->phone <= 0) {
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	async_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, fun->handle, 0,
+	async_exch_t *exch = async_exchange_begin(dev->drv->sess);
+	async_forward_fast(iid, exch, DRIVER_CLIENT, fun->handle, 0,
 	    IPC_FF_NONE);
-	printf(NAME ": devman_connection_devmapper: forwarded connection to "
-	    "device %s to driver %s.\n", fun->pathname, dev->drv->name);
+	async_exchange_end(exch);
+	
+	log_msg(LVL_DEBUG,
+	    "Forwarding loc service request for `%s' function to driver `%s'.",
+	    fun->pathname, dev->drv->name);
 }
 
 /** Function for handling connections to device manager. */
-static void devman_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	/* Select interface. */
@@ -583,7 +826,7 @@
 		devman_forward(iid, icall, false);
 		break;
-	case DEVMAN_CONNECT_FROM_DEVMAP:
-		/* Someone connected through devmap node. */
-		devman_connection_devmapper(iid, icall);
+	case DEVMAN_CONNECT_FROM_LOC:
+		/* Someone connected through loc node. */
+		devman_connection_loc(iid, icall);
 		break;
 	case DEVMAN_CONNECT_TO_PARENTS_DEVICE:
@@ -600,5 +843,5 @@
 static bool devman_init(void)
 {
-	printf(NAME ": devman_init - looking for available drivers.\n");
+	log_msg(LVL_DEBUG, "devman_init - looking for available drivers.");
 	
 	/* Initialize list of available drivers. */
@@ -606,25 +849,23 @@
 	if (lookup_available_drivers(&drivers_list,
 	    DRIVER_DEFAULT_STORE) == 0) {
-		printf(NAME " no drivers found.");
+		log_msg(LVL_FATAL, "No drivers found.");
 		return false;
 	}
 
-	printf(NAME ": devman_init  - list of drivers has been initialized.\n");
+	log_msg(LVL_DEBUG, "devman_init - list of drivers has been initialized.");
 
 	/* Create root device node. */
 	if (!init_device_tree(&device_tree, &drivers_list)) {
-		printf(NAME " failed to initialize device tree.");
+		log_msg(LVL_FATAL, "Failed to initialize device tree.");
 		return false;
 	}
 
-	init_class_list(&class_list);
-	
 	/*
-	 * !!! devman_connection ... as the device manager is not a real devmap
+	 * !!! devman_connection ... as the device manager is not a real loc
 	 * driver (it uses a completely different ipc protocol than an ordinary
-	 * devmap driver) forwarding a connection from client to the devman by
-	 * devmapper would not work.
+	 * loc driver) forwarding a connection from client to the devman by
+	 * location service would not work.
 	 */
-	devmap_driver_register(NAME, devman_connection);
+	loc_server_register(NAME, devman_connection);
 	
 	return true;
@@ -635,6 +876,11 @@
 	printf(NAME ": HelenOS Device Manager\n");
 
+	if (log_init(NAME, LVL_WARN) != EOK) {
+		printf(NAME ": Error initializing logging subsystem.\n");
+		return -1;
+	}
+
 	if (!devman_init()) {
-		printf(NAME ": Error while initializing service\n");
+		log_msg(LVL_ERROR, "Error while initializing service.");
 		return -1;
 	}
@@ -644,8 +890,11 @@
 
 	/* Register device manager at naming service. */
-	if (service_register(SERVICE_DEVMAN) != EOK)
+	if (service_register(SERVICE_DEVMAN) != EOK) {
+		log_msg(LVL_ERROR, "Failed registering as a service.");
 		return -1;
-
-	printf(NAME ": Accepting connections\n");
+	}
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
 	async_manager();
 
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/devman/match.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -59,9 +59,11 @@
 int get_match_score(driver_t *drv, dev_node_t *dev)
 {
-	link_t *drv_head = &drv->match_ids.ids;
-	link_t *dev_head = &dev->pfun->match_ids.ids;
+	link_t *drv_head = &drv->match_ids.ids.head;
+	link_t *dev_head = &dev->pfun->match_ids.ids.head;
 	
-	if (list_empty(drv_head) || list_empty(dev_head))
+	if (list_empty(&drv->match_ids.ids) ||
+	    list_empty(&dev->pfun->match_ids.ids)) {
 		return 0;
+	}
 	
 	/*
@@ -70,5 +72,5 @@
 	int highest_score = 0;
 	
-	link_t *drv_link = drv->match_ids.ids.next;
+	link_t *drv_link = drv->match_ids.ids.head.next;
 	while (drv_link != drv_head) {
 		link_t *dev_link = dev_head->next;
Index: uspace/srv/devman/util.c
===================================================================
--- uspace/srv/devman/util.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/devman/util.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -91,15 +91,4 @@
 }
 
-char *clone_string(const char *s)
-{
-	size_t size = str_size(s) + 1;
-	char *str;
-	
-	str = (char *) malloc(size);
-	if (str != NULL)
-		str_cpy(str, size, s);
-	return str;
-}
-
 void replace_char(char *str, char orig, char repl)
 {
Index: uspace/srv/devman/util.h
===================================================================
--- uspace/srv/devman/util.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/devman/util.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,5 +44,4 @@
 extern size_t get_nonspace_len(const char *);
 extern void free_not_null(const void *);
-extern char *clone_string(const char *);
 extern void replace_char(char *, char, char);
 
Index: pace/srv/devmap/Makefile
===================================================================
--- uspace/srv/devmap/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,36 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../..
-BINARY = devmap
-
-SOURCES = \
-	devmap.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1175 +1,0 @@
-/*
- * Copyright (c) 2007 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @defgroup devmap Device mapper.
- * @brief HelenOS device mapper.
- * @{
- */
-
-/** @file
- */
-
-#include <ipc/services.h>
-#include <ipc/ns.h>
-#include <async.h>
-#include <stdio.h>
-#include <errno.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <stdlib.h>
-#include <str.h>
-#include <ipc/devmap.h>
-#include <assert.h>
-
-#define NAME          "devmap"
-#define NULL_DEVICES  256
-
-/** Representation of device driver.
- *
- * Each driver is responsible for a set of devices.
- *
- */
-typedef struct {
-	/** Pointers to previous and next drivers in linked list */
-	link_t drivers;
-	/** Pointer to the linked list of devices controlled by this driver */
-	link_t devices;
-	/** Phone asociated with this driver */
-	sysarg_t phone;
-	/** Device driver name */
-	char *name;
-	/** Fibril mutex for list of devices owned by this driver */
-	fibril_mutex_t devices_mutex;
-} devmap_driver_t;
-
-/** Info about registered namespaces
- *
- */
-typedef struct {
-	/** Pointer to the previous and next device in the list of all namespaces */
-	link_t namespaces;
-	/** Unique namespace identifier */
-	devmap_handle_t handle;
-	/** Namespace name */
-	char *name;
-	/** Reference count */
-	size_t refcnt;
-} devmap_namespace_t;
-
-/** Info about registered device
- *
- */
-typedef struct {
-	/** Pointer to the previous and next device in the list of all devices */
-	link_t devices;
-	/** Pointer to the previous and next device in the list of devices
-	    owned by one driver */
-	link_t driver_devices;
-	/** Unique device identifier */
-	devmap_handle_t handle;
-	/** Device namespace */
-	devmap_namespace_t *namespace;
-	/** Device name */
-	char *name;
-	/** Device driver handling this device */
-	devmap_driver_t *driver;
-	/** Use this interface when forwarding to driver. */
-	sysarg_t forward_interface;
-} devmap_device_t;
-
-LIST_INITIALIZE(devices_list);
-LIST_INITIALIZE(namespaces_list);
-LIST_INITIALIZE(drivers_list);
-
-/* Locking order:
- *  drivers_list_mutex
- *  devices_list_mutex
- *  (devmap_driver_t *)->devices_mutex
- *  create_handle_mutex
- **/
-
-static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
-static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
-static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
-static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
-static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
-
-static devmap_handle_t last_handle = 0;
-static devmap_device_t *null_devices[NULL_DEVICES];
-
-/*
- * Dummy list for null devices. This is necessary so that null devices can
- * be used just as any other devices, e.g. in devmap_device_unregister_core().
- */
-static LIST_INITIALIZE(dummy_null_driver_devices);
-
-static devmap_handle_t devmap_create_handle(void)
-{
-	/* TODO: allow reusing old handles after their unregistration
-	 * and implement some version of LRU algorithm, avoid overflow
-	 */
-	
-	fibril_mutex_lock(&create_handle_mutex);
-	last_handle++;
-	fibril_mutex_unlock(&create_handle_mutex);
-	
-	return last_handle;
-}
-
-/** Convert fully qualified device name to namespace and device name.
- *
- * A fully qualified device name can be either a plain device name
- * (then the namespace is considered to be an empty string) or consist
- * of two components separated by a slash. No more than one slash
- * is allowed.
- *
- */
-static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name)
-{
-	size_t cnt = 0;
-	size_t slash_offset = 0;
-	size_t slash_after = 0;
-	
-	size_t offset = 0;
-	size_t offset_prev = 0;
-	wchar_t c;
-	
-	while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) {
-		if (c == '/') {
-			cnt++;
-			slash_offset = offset_prev;
-			slash_after = offset;
-		}
-		offset_prev = offset;
-	}
-	
-	/* More than one slash */
-	if (cnt > 1)
-		return false;
-	
-	/* No slash -> namespace is empty */
-	if (cnt == 0) {
-		*ns_name = str_dup("");
-		if (*ns_name == NULL)
-			return false;
-		
-		*name = str_dup(fqdn);
-		if (*name == NULL) {
-			free(*ns_name);
-			return false;
-		}
-		
-		if (str_cmp(*name, "") == 0) {
-			free(*name);
-			free(*ns_name);
-			return false;
-		}
-		
-		return true;
-	}
-	
-	/* Exactly one slash */
-	*ns_name = str_ndup(fqdn, slash_offset);
-	if (*ns_name == NULL)
-		return false;
-	
-	*name = str_dup(fqdn + slash_after);
-	if (*name == NULL) {
-		free(*ns_name);
-		return false;
-	}
-	
-	if (str_cmp(*name, "") == 0) {
-		free(*name);
-		free(*ns_name);
-		return false;
-	}
-	
-	return true;
-}
-
-/** Find namespace with given name. */
-static devmap_namespace_t *devmap_namespace_find_name(const char *name)
-{
-	link_t *item;
-	
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
-		devmap_namespace_t *namespace =
-		    list_get_instance(item, devmap_namespace_t, namespaces);
-		if (str_cmp(namespace->name, name) == 0)
-			return namespace;
-	}
-	
-	return NULL;
-}
-
-/** Find namespace with given handle.
- *
- * @todo: use hash table
- *
- */
-static devmap_namespace_t *devmap_namespace_find_handle(devmap_handle_t handle)
-{
-	link_t *item;
-	
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
-		devmap_namespace_t *namespace =
-		    list_get_instance(item, devmap_namespace_t, namespaces);
-		if (namespace->handle == handle)
-			return namespace;
-	}
-	
-	return NULL;
-}
-
-/** Find device with given name. */
-static devmap_device_t *devmap_device_find_name(const char *ns_name,
-    const char *name)
-{
-	link_t *item;
-	
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
-		devmap_device_t *device =
-		    list_get_instance(item, devmap_device_t, devices);
-		if ((str_cmp(device->namespace->name, ns_name) == 0)
-		    && (str_cmp(device->name, name) == 0))
-			return device;
-	}
-	
-	return NULL;
-}
-
-/** Find device with given handle.
- *
- * @todo: use hash table
- *
- */
-static devmap_device_t *devmap_device_find_handle(devmap_handle_t handle)
-{
-	link_t *item;
-	
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
-		devmap_device_t *device =
-		    list_get_instance(item, devmap_device_t, devices);
-		if (device->handle == handle)
-			return device;
-	}
-	
-	return NULL;
-}
-
-/** Create a namespace (if not already present). */
-static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
-{
-	devmap_namespace_t *namespace;
-	
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-	
-	namespace = devmap_namespace_find_name(ns_name);
-	if (namespace != NULL)
-		return namespace;
-	
-	namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t));
-	if (namespace == NULL)
-		return NULL;
-	
-	namespace->name = str_dup(ns_name);
-	if (namespace->name == NULL) {
-		free(namespace);
-		return NULL;
-	}
-	
-	namespace->handle = devmap_create_handle();
-	namespace->refcnt = 0;
-	
-	/*
-	 * Insert new namespace into list of registered namespaces
-	 */
-	list_append(&(namespace->namespaces), &namespaces_list);
-	
-	return namespace;
-}
-
-/** Destroy a namespace (if it is no longer needed). */
-static void devmap_namespace_destroy(devmap_namespace_t *namespace)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-
-	if (namespace->refcnt == 0) {
-		list_remove(&(namespace->namespaces));
-		
-		free(namespace->name);
-		free(namespace);
-	}
-}
-
-/** Increase namespace reference count by including device. */
-static void devmap_namespace_addref(devmap_namespace_t *namespace,
-    devmap_device_t *device)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-
-	device->namespace = namespace;
-	namespace->refcnt++;
-}
-
-/** Decrease namespace reference count. */
-static void devmap_namespace_delref(devmap_namespace_t *namespace)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-
-	namespace->refcnt--;
-	devmap_namespace_destroy(namespace);
-}
-
-/** Unregister device and free it. */
-static void devmap_device_unregister_core(devmap_device_t *device)
-{
-	assert(fibril_mutex_is_locked(&devices_list_mutex));
-
-	devmap_namespace_delref(device->namespace);
-	list_remove(&(device->devices));
-	list_remove(&(device->driver_devices));
-	
-	free(device->name);
-	free(device);
-}
-
-/**
- * Read info about new driver and add it into linked list of registered
- * drivers.
- */
-static devmap_driver_t *devmap_driver_register(void)
-{
-	ipc_call_t icall;
-	ipc_callid_t iid = async_get_call(&icall);
-	
-	if (IPC_GET_IMETHOD(icall) != DEVMAP_DRIVER_REGISTER) {
-		async_answer_0(iid, EREFUSED);
-		return NULL;
-	}
-	
-	devmap_driver_t *driver =
-	    (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
-	if (driver == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return NULL;
-	}
-	
-	/*
-	 * Get driver name
-	 */
-	int rc = async_data_write_accept((void **) &driver->name, true, 0,
-	    DEVMAP_NAME_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		free(driver);
-		async_answer_0(iid, rc);
-		return NULL;
-	}
-	
-	/*
-	 * Create connection to the driver
-	 */
-	ipc_call_t call;
-	ipc_callid_t callid = async_get_call(&call);
-	
-	if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
-		free(driver->name);
-		free(driver);
-		async_answer_0(callid, ENOTSUP);
-		async_answer_0(iid, ENOTSUP);
-		return NULL;
-	}
-	
-	driver->phone = IPC_GET_ARG5(call);
-	async_answer_0(callid, EOK);
-	
-	/*
-	 * Initialize mutex for list of devices
-	 * owned by this driver
-	 */
-	fibril_mutex_initialize(&driver->devices_mutex);
-	
-	/*
-	 * Initialize list of asociated devices
-	 */
-	list_initialize(&driver->devices);
-
-	link_initialize(&driver->drivers);
-	
-	fibril_mutex_lock(&drivers_list_mutex);
-	
-	/* TODO:
-	 * Check that no driver with name equal to
-	 * driver->name is registered
-	 */
-	
-	/*
-	 * Insert new driver into list of registered drivers
-	 */
-	list_append(&(driver->drivers), &drivers_list);
-	fibril_mutex_unlock(&drivers_list_mutex);
-	
-	async_answer_0(iid, EOK);
-	
-	return driver;
-}
-
-/**
- * Unregister device driver, unregister all its devices and free driver
- * structure.
- *
- */
-static int devmap_driver_unregister(devmap_driver_t *driver)
-{
-	if (driver == NULL)
-		return EEXISTS;
-	
-	fibril_mutex_lock(&drivers_list_mutex);
-	
-	if (driver->phone != 0)
-		async_hangup(driver->phone);
-	
-	/* Remove it from list of drivers */
-	list_remove(&(driver->drivers));
-	
-	/* Unregister all its devices */
-	fibril_mutex_lock(&devices_list_mutex);
-	fibril_mutex_lock(&driver->devices_mutex);
-	
-	while (!list_empty(&(driver->devices))) {
-		devmap_device_t *device = list_get_instance(driver->devices.next,
-		    devmap_device_t, driver_devices);
-		devmap_device_unregister_core(device);
-	}
-	
-	fibril_mutex_unlock(&driver->devices_mutex);
-	fibril_mutex_unlock(&devices_list_mutex);
-	fibril_mutex_unlock(&drivers_list_mutex);
-	
-	/* Free name and driver */
-	if (driver->name != NULL)
-		free(driver->name);
-	
-	free(driver);
-	
-	return EOK;
-}
-
-/** Register instance of device
- *
- */
-static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
-    devmap_driver_t *driver)
-{
-	if (driver == NULL) {
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	/* Create new device entry */
-	devmap_device_t *device =
-	    (devmap_device_t *) malloc(sizeof(devmap_device_t));
-	if (device == NULL) {
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	/* Set the interface, if any. */
-	device->forward_interface = IPC_GET_ARG1(*icall);
-
-	/* Get fqdn */
-	char *fqdn;
-	int rc = async_data_write_accept((void **) &fqdn, true, 0,
-	    DEVMAP_NAME_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		free(device);
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	char *ns_name;
-	if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
-		free(fqdn);
-		free(device);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	free(fqdn);
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
-	free(ns_name);
-	if (namespace == NULL) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		free(device->name);
-		free(device);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_initialize(&device->devices);
-	link_initialize(&device->driver_devices);
-	
-	/* Check that device is not already registered */
-	if (devmap_device_find_name(namespace->name, device->name) != NULL) {
-		printf("%s: Device '%s/%s' already registered\n", NAME,
-		    device->namespace->name, device->name);
-		devmap_namespace_destroy(namespace);
-		fibril_mutex_unlock(&devices_list_mutex);
-		free(device->name);
-		free(device);
-		async_answer_0(iid, EEXISTS);
-		return;
-	}
-	
-	/* Get unique device handle */
-	device->handle = devmap_create_handle();
-
-	devmap_namespace_addref(namespace, device);
-	device->driver = driver;
-	
-	/* Insert device into list of all devices  */
-	list_append(&device->devices, &devices_list);
-	
-	/* Insert device into list of devices that belog to one driver */
-	fibril_mutex_lock(&device->driver->devices_mutex);
-	
-	list_append(&device->driver_devices, &device->driver->devices);
-	
-	fibril_mutex_unlock(&device->driver->devices_mutex);
-	fibril_condvar_broadcast(&devices_list_cv);
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	async_answer_1(iid, EOK, device->handle);
-}
-
-/**
- *
- */
-static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall, 
-    devmap_driver_t *driver)
-{
-	/* TODO */
-	return EOK;
-}
-
-/** Connect client to the device.
- *
- * Find device driver owning requested device and forward
- * the message to it.
- *
- */
-static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	/*
-	 * Get handle from request
-	 */
-	devmap_handle_t handle = IPC_GET_ARG2(*call);
-	devmap_device_t *dev = devmap_device_find_handle(handle);
-	
-	if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-	
-	if (dev->forward_interface == 0) {
-		async_forward_fast(callid, dev->driver->phone,
-		    dev->handle, 0, 0,
-		    IPC_FF_NONE);
-	} else {
-		async_forward_fast(callid, dev->driver->phone,
-		    dev->forward_interface, dev->handle, 0,
-		    IPC_FF_NONE);
-	}
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-}
-
-/** Find handle for device instance identified by name.
- *
- * In answer will be send EOK and device handle in arg1 or a error
- * code from errno.h.
- *
- */
-static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
-{
-	char *fqdn;
-	
-	/* Get fqdn */
-	int rc = async_data_write_accept((void **) &fqdn, true, 0,
-	    DEVMAP_NAME_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	char *ns_name;
-	char *name;
-	if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
-		free(fqdn);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	free(fqdn);
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	const devmap_device_t *dev;
-	
-recheck:
-	
-	/*
-	 * Find device name in the list of known devices.
-	 */
-	dev = devmap_device_find_name(ns_name, name);
-	
-	/*
-	 * Device was not found.
-	 */
-	if (dev == NULL) {
-		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
-			/* Blocking lookup */
-			fibril_condvar_wait(&devices_list_cv,
-			    &devices_list_mutex);
-			goto recheck;
-		}
-		
-		async_answer_0(iid, ENOENT);
-		free(ns_name);
-		free(name);
-		fibril_mutex_unlock(&devices_list_mutex);
-		return;
-	}
-	
-	async_answer_1(iid, EOK, dev->handle);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-	free(ns_name);
-	free(name);
-}
-
-/** Find handle for namespace identified by name.
- *
- * In answer will be send EOK and device handle in arg1 or a error
- * code from errno.h.
- *
- */
-static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
-{
-	char *name;
-	
-	/* Get device name */
-	int rc = async_data_write_accept((void **) &name, true, 0,
-	    DEVMAP_NAME_MAXLEN, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(iid, rc);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	const devmap_namespace_t *namespace;
-	
-recheck:
-	
-	/*
-	 * Find namespace name in the list of known namespaces.
-	 */
-	namespace = devmap_namespace_find_name(name);
-	
-	/*
-	 * Namespace was not found.
-	 */
-	if (namespace == NULL) {
-		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
-			/* Blocking lookup */
-			fibril_condvar_wait(&devices_list_cv,
-			    &devices_list_mutex);
-			goto recheck;
-		}
-		
-		async_answer_0(iid, ENOENT);
-		free(name);
-		fibril_mutex_unlock(&devices_list_mutex);
-		return;
-	}
-	
-	async_answer_1(iid, EOK, namespace->handle);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-	free(name);
-}
-
-static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace =
-	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
-	if (namespace == NULL) {
-		devmap_device_t *dev =
-		    devmap_device_find_handle(IPC_GET_ARG1(*icall));
-		if (dev == NULL)
-			async_answer_1(iid, EOK, DEV_HANDLE_NONE);
-		else
-			async_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
-	} else
-		async_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-}
-
-static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	async_answer_1(iid, EOK, list_count(&namespaces_list));
-	fibril_mutex_unlock(&devices_list_mutex);
-}
-
-static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace =
-	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
-	if (namespace == NULL)
-		async_answer_0(iid, EEXISTS);
-	else
-		async_answer_1(iid, EOK, namespace->refcnt);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-}
-
-static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_read_receive(&callid, &size)) {
-		async_answer_0(callid, EREFUSED);
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	if ((size % sizeof(dev_desc_t)) != 0) {
-		async_answer_0(callid, EINVAL);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	size_t count = size / sizeof(dev_desc_t);
-	if (count != list_count(&namespaces_list)) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, EOVERFLOW);
-		async_answer_0(iid, EOVERFLOW);
-		return;
-	}
-	
-	dev_desc_t *desc = (dev_desc_t *) malloc(size);
-	if (desc == NULL) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, ENOMEM);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_t *item;
-	size_t pos = 0;
-	for (item = namespaces_list.next; item != &namespaces_list;
-	    item = item->next) {
-		devmap_namespace_t *namespace =
-		    list_get_instance(item, devmap_namespace_t, namespaces);
-		
-		desc[pos].handle = namespace->handle;
-		str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
-		pos++;
-	}
-	
-	sysarg_t retval = async_data_read_finalize(callid, desc, size);
-	
-	free(desc);
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	async_answer_0(iid, retval);
-}
-
-static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* FIXME: Use faster algorithm which can make better use
-	   of namespaces */
-	
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_read_receive(&callid, &size)) {
-		async_answer_0(callid, EREFUSED);
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	if ((size % sizeof(dev_desc_t)) != 0) {
-		async_answer_0(callid, EINVAL);
-		async_answer_0(iid, EINVAL);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace =
-	    devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
-	if (namespace == NULL) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, ENOENT);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	size_t count = size / sizeof(dev_desc_t);
-	if (count != namespace->refcnt) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, EOVERFLOW);
-		async_answer_0(iid, EOVERFLOW);
-		return;
-	}
-	
-	dev_desc_t *desc = (dev_desc_t *) malloc(size);
-	if (desc == NULL) {
-		fibril_mutex_unlock(&devices_list_mutex);
-		async_answer_0(callid, ENOMEM);
-		async_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	link_t *item;
-	size_t pos = 0;
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
-		devmap_device_t *device =
-		    list_get_instance(item, devmap_device_t, devices);
-		
-		if (device->namespace == namespace) {
-			desc[pos].handle = device->handle;
-			str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
-			pos++;
-		}
-	}
-	
-	sysarg_t retval = async_data_read_finalize(callid, desc, size);
-	
-	free(desc);
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	async_answer_0(iid, retval);
-}
-
-static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall)
-{
-	fibril_mutex_lock(&null_devices_mutex);
-	
-	unsigned int i;
-	bool fnd = false;
-	
-	for (i = 0; i < NULL_DEVICES; i++) {
-		if (null_devices[i] == NULL) {
-			fnd = true;
-			break;
-		}
-	}
-	
-	if (!fnd) {
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	char null[DEVMAP_NAME_MAXLEN];
-	snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
-	
-	char *dev_name = str_dup(null);
-	if (dev_name == NULL) {
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	devmap_device_t *device =
-	    (devmap_device_t *) malloc(sizeof(devmap_device_t));
-	if (device == NULL) {
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	devmap_namespace_t *namespace = devmap_namespace_create("null");
-	if (namespace == NULL) {
-		fibril_mutex_lock(&devices_list_mutex);
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOMEM);
-		return;
-	}
-	
-	link_initialize(&device->devices);
-	link_initialize(&device->driver_devices);
-	
-	/* Get unique device handle */
-	device->handle = devmap_create_handle();
-	device->driver = NULL;
-	
-	devmap_namespace_addref(namespace, device);
-	device->name = dev_name;
-	
-	/*
-	 * Insert device into list of all devices and into null devices array.
-	 * Insert device into a dummy list of null driver's devices so that it
-	 * can be safely removed later.
-	 */
-	list_append(&device->devices, &devices_list);
-	list_append(&device->driver_devices, &dummy_null_driver_devices);
-	null_devices[i] = device;
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-	fibril_mutex_unlock(&null_devices_mutex);
-	
-	async_answer_1(iid, EOK, (sysarg_t) i);
-}
-
-static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
-{
-	sysarg_t i = IPC_GET_ARG1(*icall);
-	if (i >= NULL_DEVICES) {
-		async_answer_0(iid, ELIMIT);
-		return;
-	}
-	
-	fibril_mutex_lock(&null_devices_mutex);
-	
-	if (null_devices[i] == NULL) {
-		fibril_mutex_unlock(&null_devices_mutex);
-		async_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	fibril_mutex_lock(&devices_list_mutex);
-	devmap_device_unregister_core(null_devices[i]);
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	null_devices[i] = NULL;
-	
-	fibril_mutex_unlock(&null_devices_mutex);
-	async_answer_0(iid, EOK);
-}
-
-/** Initialize device mapper.
- *
- *
- */
-static bool devmap_init(void)
-{
-	fibril_mutex_lock(&null_devices_mutex);
-	
-	unsigned int i;
-	for (i = 0; i < NULL_DEVICES; i++)
-		null_devices[i] = NULL;
-	
-	fibril_mutex_unlock(&null_devices_mutex);
-	
-	return true;
-}
-
-/** Handle connection with device driver.
- *
- */
-static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Accept connection */
-	async_answer_0(iid, EOK);
-	
-	devmap_driver_t *driver = devmap_driver_register();
-	if (driver == NULL)
-		return;
-	
-	bool cont = true;
-	while (cont) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
-		case DEVMAP_DRIVER_UNREGISTER:
-			if (NULL == driver)
-				async_answer_0(callid, ENOENT);
-			else
-				async_answer_0(callid, EOK);
-			break;
-		case DEVMAP_DEVICE_REGISTER:
-			/* Register one instance of device */
-			devmap_device_register(callid, &call, driver);
-			break;
-		case DEVMAP_DEVICE_UNREGISTER:
-			/* Remove instance of device identified by handler */
-			devmap_device_unregister(callid, &call, driver);
-			break;
-		case DEVMAP_DEVICE_GET_HANDLE:
-			devmap_device_get_handle(callid, &call);
-			break;
-		case DEVMAP_NAMESPACE_GET_HANDLE:
-			devmap_namespace_get_handle(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOENT);
-		}
-	}
-	
-	if (driver != NULL) {
-		/*
-		 * Unregister the device driver and all its devices.
-		 */
-		devmap_driver_unregister(driver);
-		driver = NULL;
-	}
-}
-
-/** Handle connection with device client.
- *
- */
-static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Accept connection */
-	async_answer_0(iid, EOK);
-	
-	bool cont = true;
-	while (cont) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
-		case DEVMAP_DEVICE_GET_HANDLE:
-			devmap_device_get_handle(callid, &call);
-			break;
-		case DEVMAP_NAMESPACE_GET_HANDLE:
-			devmap_namespace_get_handle(callid, &call);
-			break;
-		case DEVMAP_HANDLE_PROBE:
-			devmap_handle_probe(callid, &call);
-			break;
-		case DEVMAP_NULL_CREATE:
-			devmap_null_create(callid, &call);
-			break;
-		case DEVMAP_NULL_DESTROY:
-			devmap_null_destroy(callid, &call);
-			break;
-		case DEVMAP_GET_NAMESPACE_COUNT:
-			devmap_get_namespace_count(callid, &call);
-			break;
-		case DEVMAP_GET_DEVICE_COUNT:
-			devmap_get_device_count(callid, &call);
-			break;
-		case DEVMAP_GET_NAMESPACES:
-			devmap_get_namespaces(callid, &call);
-			break;
-		case DEVMAP_GET_DEVICES:
-			devmap_get_devices(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOENT);
-		}
-	}
-}
-
-/** Function for handling connections to devmap
- *
- */
-static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Select interface */
-	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
-	case DEVMAP_DRIVER:
-		devmap_connection_driver(iid, icall);
-		break;
-	case DEVMAP_CLIENT:
-		devmap_connection_client(iid, icall);
-		break;
-	case DEVMAP_CONNECT_TO_DEVICE:
-		/* Connect client to selected device */
-		devmap_forward(iid, icall);
-		break;
-	default:
-		/* No such interface */
-		async_answer_0(iid, ENOENT);
-	}
-}
-
-/**
- *
- */
-int main(int argc, char *argv[])
-{
-	printf("%s: HelenOS Device Mapper\n", NAME);
-	
-	if (!devmap_init()) {
-		printf("%s: Error while initializing service\n", NAME);
-		return -1;
-	}
-	
-	/* Set a handler of incomming connections */
-	async_set_client_connection(devmap_connection);
-	
-	/* Register device mapper at naming service */
-	if (service_register(SERVICE_DEVMAP) != EOK)
-		return -1;
-	
-	printf("%s: Accepting connections\n", NAME);
-	async_manager();
-	
-	/* Never reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/fs/devfs/Makefile
===================================================================
--- uspace/srv/fs/devfs/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,39 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-LIBS = $(LIBFS_PREFIX)/libfs.a
-EXTRA_CFLAGS += -I$(LIBFS_PREFIX)
-BINARY = devfs
-
-SOURCES = \
-	devfs.c \
-	devfs_ops.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/fs/devfs/devfs.c
===================================================================
--- uspace/srv/fs/devfs/devfs.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,151 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-/**
- * @file devfs.c
- * @brief Devices file system.
- *
- * Every device registered to device mapper is represented as a file in this
- * file system.
- */
-
-#include <stdio.h>
-#include <ipc/services.h>
-#include <ipc/ns.h>
-#include <async.h>
-#include <errno.h>
-#include <task.h>
-#include <libfs.h>
-#include "devfs.h"
-#include "devfs_ops.h"
-
-#define NAME  "devfs"
-
-static vfs_info_t devfs_vfs_info = {
-	.name = NAME,
-	.concurrent_read_write = false,
-	.write_retains_size = false,
-};
-
-fs_reg_t devfs_reg;
-
-static void devfs_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (iid)
-		async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		switch  (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			return;
-		case VFS_OUT_MOUNTED:
-			devfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			devfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			devfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			devfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			devfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			devfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			devfs_stat(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			devfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			devfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			devfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			devfs_close(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			devfs_sync(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			devfs_destroy(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS Device Filesystem\n");
-	
-	if (!devfs_init()) {
-		printf(NAME ": failed to initialize devfs\n");
-		return -1;
-	}
-	
-	int vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
-	if (vfs_phone < EOK) {
-		printf(NAME ": Unable to connect to VFS\n");
-		return -1;
-	}
-	
-	int rc = fs_register(vfs_phone, &devfs_reg, &devfs_vfs_info,
-	    devfs_connection);
-	if (rc != EOK) {
-		printf(NAME ": Failed to register file system (%d)\n", rc);
-		return rc;
-	}
-	
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-	
-	/* Not reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/fs/devfs/devfs.h
===================================================================
--- uspace/srv/fs/devfs/devfs.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,44 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-/** @addtogroup fs
- * @{
- */ 
-
-#ifndef DEVFS_DEVFS_H_
-#define DEVFS_DEVFS_H_
-
-#include <libfs.h>
-
-extern fs_reg_t devfs_reg;
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,820 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-/**
- * @file devfs_ops.c
- * @brief Implementation of VFS operations for the devfs file system server.
- */
-
-#include <macros.h>
-#include <bool.h>
-#include <errno.h>
-#include <malloc.h>
-#include <str.h>
-#include <libfs.h>
-#include <fibril_synch.h>
-#include <adt/hash_table.h>
-#include <ipc/devmap.h>
-#include <sys/stat.h>
-#include <libfs.h>
-#include <assert.h>
-#include "devfs.h"
-#include "devfs_ops.h"
-
-typedef struct {
-	devmap_handle_type_t type;
-	devmap_handle_t handle;
-} devfs_node_t;
-
-/** Opened devices structure */
-typedef struct {
-	devmap_handle_t handle;
-	int phone;		/**< When < 0, the structure is incomplete. */
-	size_t refcount;
-	link_t link;
-	fibril_condvar_t cv;	/**< Broadcast when completed. */
-} device_t;
-
-/** Hash table of opened devices */
-static hash_table_t devices;
-
-/** Hash table mutex */
-static FIBRIL_MUTEX_INITIALIZE(devices_mutex);
-
-#define DEVICES_KEYS        1
-#define DEVICES_KEY_HANDLE  0
-#define DEVICES_BUCKETS     256
-
-/* Implementation of hash table interface for the nodes hash table. */
-static hash_index_t devices_hash(unsigned long key[])
-{
-	return key[DEVICES_KEY_HANDLE] % DEVICES_BUCKETS;
-}
-
-static int devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	device_t *dev = hash_table_get_instance(item, device_t, link);
-	return (dev->handle == (devmap_handle_t) key[DEVICES_KEY_HANDLE]);
-}
-
-static void devices_remove_callback(link_t *item)
-{
-	free(hash_table_get_instance(item, device_t, link));
-}
-
-static hash_table_operations_t devices_ops = {
-	.hash = devices_hash,
-	.compare = devices_compare,
-	.remove_callback = devices_remove_callback
-};
-
-static int devfs_node_get_internal(fs_node_t **rfn, devmap_handle_type_t type,
-    devmap_handle_t handle)
-{
-	devfs_node_t *node = (devfs_node_t *) malloc(sizeof(devfs_node_t));
-	if (node == NULL) {
-		*rfn = NULL;
-		return ENOMEM;
-	}
-	
-	*rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
-	if (*rfn == NULL) {
-		free(node);
-		*rfn = NULL;
-		return ENOMEM;
-	}
-	
-	fs_node_initialize(*rfn);
-	node->type = type;
-	node->handle = handle;
-	
-	(*rfn)->data = node;
-	return EOK;
-}
-
-static int devfs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
-{
-	return devfs_node_get_internal(rfn, DEV_HANDLE_NONE, 0);
-}
-
-static int devfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
-{
-	devfs_node_t *node = (devfs_node_t *) pfn->data;
-	int ret;
-	
-	if (node->handle == 0) {
-		/* Root directory */
-		
-		dev_desc_t *devs;
-		size_t count = devmap_get_namespaces(&devs);
-		
-		if (count > 0) {
-			size_t pos;
-			for (pos = 0; pos < count; pos++) {
-				/* Ignore root namespace */
-				if (str_cmp(devs[pos].name, "") == 0)
-					continue;
-				
-				if (str_cmp(devs[pos].name, component) == 0) {
-					ret = devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
-					free(devs);
-					return ret;
-				}
-			}
-			
-			free(devs);
-		}
-		
-		/* Search root namespace */
-		devmap_handle_t namespace;
-		if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
-			count = devmap_get_devices(namespace, &devs);
-			
-			if (count > 0) {
-				size_t pos;
-				for (pos = 0; pos < count; pos++) {
-					if (str_cmp(devs[pos].name, component) == 0) {
-						ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
-						free(devs);
-						return ret;
-					}
-				}
-				
-				free(devs);
-			}
-		}
-		
-		*rfn = NULL;
-		return EOK;
-	}
-	
-	if (node->type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		
-		dev_desc_t *devs;
-		size_t count = devmap_get_devices(node->handle, &devs);
-		if (count > 0) {
-			size_t pos;
-			for (pos = 0; pos < count; pos++) {
-				if (str_cmp(devs[pos].name, component) == 0) {
-					ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
-					free(devs);
-					return ret;
-				}
-			}
-			
-			free(devs);
-		}
-		
-		*rfn = NULL;
-		return EOK;
-	}
-	
-	*rfn = NULL;
-	return EOK;
-}
-
-static int devfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
-{
-	return devfs_node_get_internal(rfn, devmap_handle_probe(index), index);
-}
-
-static int devfs_node_open(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	if (node->handle == 0) {
-		/* Root directory */
-		return EOK;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(node->handle);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		return EOK;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		/* Device node */
-		
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) node->handle
-		};
-		link_t *lnk;
-
-		fibril_mutex_lock(&devices_mutex);
-restart:
-		lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			device_t *dev = (device_t *) malloc(sizeof(device_t));
-			if (dev == NULL) {
-				fibril_mutex_unlock(&devices_mutex);
-				return ENOMEM;
-			}
-			
-			dev->handle = node->handle;
-			dev->phone = -1;	/* mark as incomplete */
-			dev->refcount = 1;
-			fibril_condvar_initialize(&dev->cv);
-
-			/*
-			 * Insert the incomplete device structure so that other
-			 * fibrils will not race with us when we drop the mutex
-			 * below.
-			 */
-			hash_table_insert(&devices, key, &dev->link);
-
-			/*
-			 * Drop the mutex to allow recursive devfs requests.
-			 */
-			fibril_mutex_unlock(&devices_mutex);
-
-			int phone = devmap_device_connect(node->handle, 0);
-
-			fibril_mutex_lock(&devices_mutex);
-
-			/*
-			 * Notify possible waiters about this device structure
-			 * being completed (or destroyed).
-			 */
-			fibril_condvar_broadcast(&dev->cv);
-
-			if (phone < 0) {
-				/*
-				 * Connecting failed, need to remove the
-				 * entry and free the device structure.
-				 */
-				hash_table_remove(&devices, key, DEVICES_KEYS);
-				fibril_mutex_unlock(&devices_mutex);
-
-				return ENOENT;
-			}
-			
-			/* Set the correct phone. */
-			dev->phone = phone;
-		} else {
-			device_t *dev = hash_table_get_instance(lnk, device_t, link);
-
-			if (dev->phone < 0) {
-				/*
-				 * Wait until the device structure is completed
-				 * and start from the beginning as the device
-				 * structure might have entirely disappeared
-				 * while we were not holding the mutex in
-				 * fibril_condvar_wait().
-				 */
-				fibril_condvar_wait(&dev->cv, &devices_mutex);
-				goto restart;
-			}
-
-			dev->refcount++;
-		}
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		return EOK;
-	}
-	
-	return ENOENT;
-}
-
-static int devfs_node_put(fs_node_t *fn)
-{
-	free(fn->data);
-	free(fn);
-	return EOK;
-}
-
-static int devfs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int lflag)
-{
-	assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
-	
-	*rfn = NULL;
-	return ENOTSUP;
-}
-
-static int devfs_destroy_node(fs_node_t *fn)
-{
-	return ENOTSUP;
-}
-
-static int devfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
-{
-	return ENOTSUP;
-}
-
-static int devfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
-{
-	return ENOTSUP;
-}
-
-static int devfs_has_children(bool *has_children, fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	if (node->handle == 0) {
-		size_t count = devmap_count_namespaces();
-		if (count > 0) {
-			*has_children = true;
-			return EOK;
-		}
-		
-		/* Root namespace */
-		devmap_handle_t namespace;
-		if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
-			count = devmap_count_devices(namespace);
-			if (count > 0) {
-				*has_children = true;
-				return EOK;
-			}
-		}
-		
-		*has_children = false;
-		return EOK;
-	}
-	
-	if (node->type == DEV_HANDLE_NAMESPACE) {
-		size_t count = devmap_count_devices(node->handle);
-		if (count > 0) {
-			*has_children = true;
-			return EOK;
-		}
-		
-		*has_children = false;
-		return EOK;
-	}
-	
-	*has_children = false;
-	return EOK;
-}
-
-static fs_index_t devfs_index_get(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	return node->handle;
-}
-
-static aoff64_t devfs_size_get(fs_node_t *fn)
-{
-	return 0;
-}
-
-static unsigned int devfs_lnkcnt_get(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	if (node->handle == 0)
-		return 0;
-	
-	return 1;
-}
-
-static char devfs_plb_get_char(unsigned pos)
-{
-	return devfs_reg.plb_ro[pos % PLB_SIZE];
-}
-
-static bool devfs_is_directory(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	return ((node->type == DEV_HANDLE_NONE) || (node->type == DEV_HANDLE_NAMESPACE));
-}
-
-static bool devfs_is_file(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	return (node->type == DEV_HANDLE_DEVICE);
-}
-
-static devmap_handle_t devfs_device_get(fs_node_t *fn)
-{
-	devfs_node_t *node = (devfs_node_t *) fn->data;
-	
-	if (node->type == DEV_HANDLE_DEVICE)
-		return node->handle;
-	
-	return 0;
-}
-
-/** libfs operations */
-libfs_ops_t devfs_libfs_ops = {
-	.root_get = devfs_root_get,
-	.match = devfs_match,
-	.node_get = devfs_node_get,
-	.node_open = devfs_node_open,
-	.node_put = devfs_node_put,
-	.create = devfs_create_node,
-	.destroy = devfs_destroy_node,
-	.link = devfs_link_node,
-	.unlink = devfs_unlink_node,
-	.has_children = devfs_has_children,
-	.index_get = devfs_index_get,
-	.size_get = devfs_size_get,
-	.lnkcnt_get = devfs_lnkcnt_get,
-	.plb_get_char = devfs_plb_get_char,
-	.is_directory = devfs_is_directory,
-	.is_file = devfs_is_file,
-	.device_get = devfs_device_get
-};
-
-bool devfs_init(void)
-{
-	if (!hash_table_create(&devices, DEVICES_BUCKETS,
-	    DEVICES_KEYS, &devices_ops))
-		return false;
-	
-	return true;
-}
-
-void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	char *opts;
-	
-	/* Accept the mount options */
-	sysarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
-	    0, NULL);
-	if (retval != EOK) {
-		async_answer_0(rid, retval);
-		return;
-	}
-	
-	free(opts);
-	async_answer_3(rid, EOK, 0, 0, 0);
-}
-
-void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void devfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&devfs_libfs_ops, rid, request);
-}
-
-void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
-	if (index == 0) {
-		ipc_callid_t callid;
-		size_t size;
-		if (!async_data_read_receive(&callid, &size)) {
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
-		}
-		
-		dev_desc_t *desc;
-		size_t count = devmap_get_namespaces(&desc);
-		
-		/* Get rid of root namespace */
-		size_t i;
-		for (i = 0; i < count; i++) {
-			if (str_cmp(desc[i].name, "") == 0) {
-				if (pos >= i)
-					pos++;
-				
-				break;
-			}
-		}
-		
-		if (pos < count) {
-			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
-			free(desc);
-			async_answer_1(rid, EOK, 1);
-			return;
-		}
-		
-		free(desc);
-		pos -= count;
-		
-		/* Search root namespace */
-		devmap_handle_t namespace;
-		if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
-			count = devmap_get_devices(namespace, &desc);
-			
-			if (pos < count) {
-				async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
-				free(desc);
-				async_answer_1(rid, EOK, 1);
-				return;
-			}
-			
-			free(desc);
-		}
-		
-		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(index);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		ipc_callid_t callid;
-		size_t size;
-		if (!async_data_read_receive(&callid, &size)) {
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
-		}
-		
-		dev_desc_t *desc;
-		size_t count = devmap_get_devices(index, &desc);
-		
-		if (pos < count) {
-			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
-			free(desc);
-			async_answer_1(rid, EOK, 1);
-			return;
-		}
-		
-		free(desc);
-		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		/* Device node */
-		
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
-		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->phone >= 0);
-		
-		ipc_callid_t callid;
-		if (!async_data_read_receive(&callid, NULL)) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
-		}
-		
-		/* Make a request at the driver */
-		ipc_call_t answer;
-		aid_t msg = async_send_3(dev->phone, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
-		    IPC_GET_ARG3(*request), &answer);
-		
-		/* Forward the IPC_M_DATA_READ request to the driver */
-		async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
-		fibril_mutex_unlock(&devices_mutex);
-		
-		/* Wait for reply from the driver. */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		size_t bytes = IPC_GET_ARG1(answer);
-		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_1(rid, rc, bytes);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	if (index == 0) {
-		async_answer_0(rid, ENOTSUP);
-		return;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(index);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		async_answer_0(rid, ENOTSUP);
-		return;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		/* Device node */
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
-		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->phone >= 0);
-		
-		ipc_callid_t callid;
-		if (!async_data_write_receive(&callid, NULL)) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
-		}
-		
-		/* Make a request at the driver */
-		ipc_call_t answer;
-		aid_t msg = async_send_3(dev->phone, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
-		    IPC_GET_ARG3(*request), &answer);
-		
-		/* Forward the IPC_M_DATA_WRITE request to the driver */
-		async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		/* Wait for reply from the driver. */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		size_t bytes = IPC_GET_ARG1(answer);
-		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_1(rid, rc, bytes);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void devfs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	if (index == 0) {
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(index);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
-		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->phone >= 0);
-		dev->refcount--;
-		
-		if (dev->refcount == 0) {
-			async_hangup(dev->phone);
-			hash_table_remove(&devices, key, DEVICES_KEYS);
-		}
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	if (index == 0) {
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	devmap_handle_type_t type = devmap_handle_probe(index);
-	
-	if (type == DEV_HANDLE_NAMESPACE) {
-		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	if (type == DEV_HANDLE_DEVICE) {
-		unsigned long key[] = {
-			[DEVICES_KEY_HANDLE] = (unsigned long) index
-		};
-		
-		fibril_mutex_lock(&devices_mutex);
-		link_t *lnk = hash_table_find(&devices, key);
-		if (lnk == NULL) {
-			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
-		}
-		
-		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->phone >= 0);
-		
-		/* Make a request at the driver */
-		ipc_call_t answer;
-		aid_t msg = async_send_2(dev->phone, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
-		
-		fibril_mutex_unlock(&devices_mutex);
-		
-		/* Wait for reply from the driver */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		
-		/* Driver reply is the final result of the whole operation */
-		async_answer_0(rid, rc);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-/**
- * @}
- */
Index: pace/srv/fs/devfs/devfs_ops.h
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-/** @addtogroup fs
- * @{
- */
-
-#ifndef DEVFS_DEVFS_OPS_H_
-#define DEVFS_DEVFS_OPS_H_
-
-#include <ipc/common.h>
-#include <bool.h>
-
-extern bool devfs_init(void);
-
-extern void devfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void devfs_mount(ipc_callid_t, ipc_call_t *);
-extern void devfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void devfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void devfs_stat(ipc_callid_t, ipc_call_t *);
-extern void devfs_sync(ipc_callid_t, ipc_call_t *);
-extern void devfs_read(ipc_callid_t, ipc_call_t *);
-extern void devfs_write(ipc_callid_t, ipc_call_t *);
-extern void devfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void devfs_close(ipc_callid_t, ipc_call_t *);
-extern void devfs_destroy(ipc_callid_t, ipc_call_t *);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/fs/ext2fs/Makefile
===================================================================
--- uspace/srv/fs/ext2fs/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/ext2fs/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# Copyright (c) 2010 Martin Sucha
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a $(LIBEXT2_PREFIX)/libext2.a
+EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX) -I$(LIBEXT2_PREFIX)
+BINARY = ext2fs
+
+SOURCES = \
+	ext2fs.c \
+	ext2fs_ops.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/ext2fs/ext2fs.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/ext2fs/ext2fs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2011 Martin Sucha
+ * 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 fs
+ * @{
+ */ 
+
+/**
+ * @file	ext2.c
+ * @brief	EXT2 file system driver for HelenOS.
+ */
+
+#include "ext2fs.h"
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <unistd.h>
+#include <task.h>
+#include <stdio.h>
+#include <libfs.h>
+#include "../../vfs/vfs.h"
+
+#define NAME	"ext2fs"
+
+vfs_info_t ext2fs_vfs_info = {
+	.name = NAME,
+};
+
+int main(int argc, char **argv)
+{
+	printf(NAME ": HelenOS EXT2 file system server\n");
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
+		printf(NAME ": failed to connect to VFS\n");
+		return -1;
+	}
+
+	int rc = ext2fs_global_init();
+	if (rc != EOK) {
+		printf(NAME ": Failed global initialization\n");
+		return 1;
+	}	
+		
+	rc = fs_register(vfs_sess, &ext2fs_vfs_info, &ext2fs_ops,
+	    &ext2fs_libfs_ops);
+	if (rc != EOK) {
+		fprintf(stdout, NAME ": Failed to register fs (%d)\n", rc);
+		return 1;
+	}
+	
+	printf(NAME ": Accepting connections\n");
+	task_retval(0);
+	async_manager();
+	/* not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/fs/ext2fs/ext2fs.h
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/ext2fs/ext2fs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 fs
+ * @{
+ */ 
+
+#ifndef EXT2FS_EXT2FS_H_
+#define EXT2FS_EXT2FS_H_
+
+#include <libext2.h>
+#include <libfs.h>
+#include <sys/types.h>
+
+#define min(a, b)		((a) < (b) ? (a) : (b))
+
+extern vfs_out_ops_t ext2fs_ops;
+extern libfs_ops_t ext2fs_libfs_ops;
+
+extern int ext2fs_global_init(void);
+extern int ext2fs_global_fini(void);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,973 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * 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 fs
+ * @{
+ */ 
+
+/**
+ * @file	ext2fs_ops.c
+ * @brief	Implementation of VFS operations for the EXT2 file system server.
+ */
+
+#include "ext2fs.h"
+#include "../../vfs/vfs.h"
+#include <libfs.h>
+#include <libblock.h>
+#include <libext2.h>
+#include <ipc/services.h>
+#include <ipc/loc.h>
+#include <macros.h>
+#include <async.h>
+#include <errno.h>
+#include <str.h>
+#include <byteorder.h>
+#include <adt/hash_table.h>
+#include <adt/list.h>
+#include <assert.h>
+#include <fibril_synch.h>
+#include <sys/mman.h>
+#include <align.h>
+#include <adt/hash_table.h>
+#include <sys/typefmt.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#define EXT2FS_NODE(node)	((node) ? (ext2fs_node_t *) (node)->data : NULL)
+#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
+#define OPEN_NODES_KEYS 2
+#define OPEN_NODES_DEV_HANDLE_KEY 0
+#define OPEN_NODES_INODE_KEY 1
+#define OPEN_NODES_BUCKETS 256
+
+typedef struct ext2fs_instance {
+	link_t link;
+	service_id_t service_id;
+	ext2_filesystem_t *filesystem;
+	unsigned int open_nodes_count;
+} ext2fs_instance_t;
+
+typedef struct ext2fs_node {
+	ext2fs_instance_t *instance;
+	ext2_inode_ref_t *inode_ref;
+	fs_node_t *fs_node;
+	link_t link;
+	unsigned int references;
+} ext2fs_node_t;
+
+/*
+ * Forward declarations of auxiliary functions
+ */
+static int ext2fs_instance_get(service_id_t, ext2fs_instance_t **);
+static int ext2fs_read_directory(ipc_callid_t, aoff64_t, size_t,
+    ext2fs_instance_t *, ext2_inode_ref_t *, size_t *);
+static int ext2fs_read_file(ipc_callid_t, aoff64_t, size_t, ext2fs_instance_t *,
+    ext2_inode_ref_t *, size_t *);
+static bool ext2fs_is_dots(const uint8_t *, size_t);
+static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
+static int ext2fs_node_put_core(ext2fs_node_t *);
+
+/*
+ * Forward declarations of EXT2 libfs operations.
+ */
+static int ext2fs_root_get(fs_node_t **, service_id_t);
+static int ext2fs_match(fs_node_t **, fs_node_t *, const char *);
+static int ext2fs_node_get(fs_node_t **, service_id_t, fs_index_t);
+static int ext2fs_node_open(fs_node_t *);
+static int ext2fs_node_put(fs_node_t *);
+static int ext2fs_create_node(fs_node_t **, service_id_t, int);
+static int ext2fs_destroy_node(fs_node_t *);
+static int ext2fs_link(fs_node_t *, fs_node_t *, const char *);
+static int ext2fs_unlink(fs_node_t *, fs_node_t *, const char *);
+static int ext2fs_has_children(bool *, fs_node_t *);
+static fs_index_t ext2fs_index_get(fs_node_t *);
+static aoff64_t ext2fs_size_get(fs_node_t *);
+static unsigned ext2fs_lnkcnt_get(fs_node_t *);
+static bool ext2fs_is_directory(fs_node_t *);
+static bool ext2fs_is_file(fs_node_t *node);
+static service_id_t ext2fs_device_get(fs_node_t *node);
+
+/*
+ * Static variables
+ */
+static LIST_INITIALIZE(instance_list);
+static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex);
+static hash_table_t open_nodes;
+static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
+
+/* Hash table interface for open nodes hash table */
+static hash_index_t open_nodes_hash(unsigned long key[])
+{
+	/* TODO: This is very simple and probably can be improved */
+	return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
+}
+
+static int open_nodes_compare(unsigned long key[], hash_count_t keys, 
+    link_t *item)
+{
+	ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
+	assert(keys > 0);
+	if (enode->instance->service_id !=
+	    ((service_id_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
+		return false;
+	}
+	if (keys == 1) {
+		return true;
+	}
+	assert(keys == 2);
+	return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]);
+}
+
+static void open_nodes_remove_cb(link_t *link)
+{
+	/* We don't use remove callback for this hash table */
+}
+
+static hash_table_operations_t open_nodes_ops = {
+	.hash = open_nodes_hash,
+	.compare = open_nodes_compare,
+	.remove_callback = open_nodes_remove_cb,
+};
+
+/**
+ * 
+ */
+int ext2fs_global_init(void)
+{
+	if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
+	    OPEN_NODES_KEYS, &open_nodes_ops)) {
+		return ENOMEM;
+	}
+	return EOK;
+}
+
+int ext2fs_global_fini(void)
+{
+	hash_table_destroy(&open_nodes);
+	return EOK;
+}
+
+
+/*
+ * EXT2 libfs operations.
+ */
+
+/**
+ * Find an instance of filesystem for the given service_id
+ */
+int ext2fs_instance_get(service_id_t service_id, ext2fs_instance_t **inst)
+{
+	EXT2FS_DBG("(%" PRIun ", -)", service_id);
+	ext2fs_instance_t *tmp;
+	
+	fibril_mutex_lock(&instance_list_mutex);
+
+	if (list_empty(&instance_list)) {
+		EXT2FS_DBG("list empty");
+		fibril_mutex_unlock(&instance_list_mutex);
+		return EINVAL;
+	}
+
+	list_foreach(instance_list, link) {
+		tmp = list_get_instance(link, ext2fs_instance_t, link);
+		
+		if (tmp->service_id == service_id) {
+			*inst = tmp;
+			fibril_mutex_unlock(&instance_list_mutex);
+			return EOK;
+		}
+	}
+	
+	EXT2FS_DBG("not found");
+	
+	fibril_mutex_unlock(&instance_list_mutex);
+	return EINVAL;
+}
+
+
+
+int ext2fs_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	EXT2FS_DBG("(-, %" PRIun ")", service_id);
+	return ext2fs_node_get(rfn, service_id, EXT2_INODE_ROOT_INDEX);
+}
+
+int ext2fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+	EXT2FS_DBG("(-,-,%s)", component);
+	ext2fs_node_t *eparent = EXT2FS_NODE(pfn);
+	ext2_filesystem_t *fs;
+	ext2_directory_iterator_t it;
+	int rc;
+	size_t name_size;
+	size_t component_size;
+	bool found = false;
+	uint32_t inode;
+	
+	fs = eparent->instance->filesystem;
+	
+	if (!ext2_inode_is_type(fs->superblock, eparent->inode_ref->inode,
+	    EXT2_INODE_MODE_DIRECTORY)) {
+		return ENOTDIR;
+	}
+	
+	rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref, 0);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Find length of component in bytes
+	 * TODO: check for library function call that does this
+	 */
+	component_size = 0;
+	while (*(component+component_size) != 0) {
+		component_size++;
+	}
+	
+	while (it.current != NULL) {
+		inode = ext2_directory_entry_ll_get_inode(it.current);
+		
+		/* ignore empty directory entries */
+		if (inode != 0) {
+			name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
+				it.current);
+
+			if (name_size == component_size && bcmp(component, &it.current->name,
+				    name_size) == 0) {
+				rc = ext2fs_node_get_core(rfn, eparent->instance,
+					inode);
+				if (rc != EOK) {
+					ext2_directory_iterator_fini(&it);
+					return rc;
+				}
+				found = true;
+				break;
+			}
+		}
+		
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK) {
+			ext2_directory_iterator_fini(&it);
+			return rc;
+		}
+	}
+	
+	ext2_directory_iterator_fini(&it);
+	
+	if (!found) {
+		return ENOENT;
+	}
+	
+	return EOK;
+}
+
+/** Instantiate a EXT2 in-core node. */
+int ext2fs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
+{
+	EXT2FS_DBG("(-,%" PRIun ",%u)", service_id, index);
+	
+	ext2fs_instance_t *inst = NULL;
+	int rc;
+	
+	rc = ext2fs_instance_get(service_id, &inst);
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	return ext2fs_node_get_core(rfn, inst, index);
+}
+
+int ext2fs_node_get_core(fs_node_t **rfn, ext2fs_instance_t *inst,
+		fs_index_t index)
+{
+	int rc;
+	fs_node_t *node = NULL;
+	ext2fs_node_t *enode = NULL;
+	
+	ext2_inode_ref_t *inode_ref = NULL;
+
+	fibril_mutex_lock(&open_nodes_lock);
+	
+	/* Check if the node is not already open */
+	unsigned long key[] = {
+		[OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id,
+		[OPEN_NODES_INODE_KEY] = index,
+	};
+	link_t *already_open = hash_table_find(&open_nodes, key);
+
+	if (already_open) {
+		enode = hash_table_get_instance(already_open, ext2fs_node_t, link);
+		*rfn = enode->fs_node;
+		enode->references++;
+
+		fibril_mutex_unlock(&open_nodes_lock);
+		return EOK;
+	}
+
+	enode = malloc(sizeof(ext2fs_node_t));
+	if (enode == NULL) {
+		fibril_mutex_unlock(&open_nodes_lock);
+		return ENOMEM;
+	}
+
+	node = malloc(sizeof(fs_node_t));
+	if (node == NULL) {
+		free(enode);
+		fibril_mutex_unlock(&open_nodes_lock);
+		return ENOMEM;
+	}	
+	fs_node_initialize(node);
+
+	rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
+	if (rc != EOK) {
+		free(enode);
+		free(node);
+		fibril_mutex_unlock(&open_nodes_lock);
+		return rc;
+	}
+	
+	enode->inode_ref = inode_ref;
+	enode->instance = inst;
+	enode->references = 1;
+	enode->fs_node = node;
+	link_initialize(&enode->link);
+	
+	node->data = enode;
+	*rfn = node;
+	
+	hash_table_insert(&open_nodes, key, &enode->link);
+	inst->open_nodes_count++;
+	
+	EXT2FS_DBG("inode: %u", inode_ref->index);
+	
+	EXT2FS_DBG("EOK");
+
+	fibril_mutex_unlock(&open_nodes_lock);
+	return EOK;
+}
+
+int ext2fs_node_open(fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	/*
+	 * Opening a file is stateless, nothing
+	 * to be done here.
+	 */
+	return EOK;
+}
+
+int ext2fs_node_put(fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	int rc;
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	
+	fibril_mutex_lock(&open_nodes_lock);
+
+	assert(enode->references > 0);
+	enode->references--;
+	if (enode->references == 0) {
+		rc = ext2fs_node_put_core(enode);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&open_nodes_lock);
+			return rc;
+		}
+	}
+
+	fibril_mutex_unlock(&open_nodes_lock);
+	
+	return EOK;
+}
+
+int ext2fs_node_put_core(ext2fs_node_t *enode)
+{
+	int rc;
+
+	unsigned long key[] = {
+		[OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id,
+		[OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
+	};
+	hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
+	assert(enode->instance->open_nodes_count > 0);
+	enode->instance->open_nodes_count--;
+
+	rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
+	if (rc != EOK) {
+		EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
+		return rc;
+	}
+
+	free(enode->fs_node);
+	free(enode);
+	return EOK;
+}
+
+int ext2fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
+{
+	EXT2FS_DBG("");
+	// TODO
+	return ENOTSUP;
+}
+
+int ext2fs_destroy_node(fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	// TODO
+	return ENOTSUP;
+}
+
+int ext2fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	EXT2FS_DBG("");
+	// TODO
+	return ENOTSUP;
+}
+
+int ext2fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+	EXT2FS_DBG("");
+	// TODO
+	return ENOTSUP;
+}
+
+int ext2fs_has_children(bool *has_children, fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	ext2_directory_iterator_t it;
+	ext2_filesystem_t *fs;
+	int rc;
+	bool found = false;
+	size_t name_size;
+
+	fs = enode->instance->filesystem;
+
+	if (!ext2_inode_is_type(fs->superblock, enode->inode_ref->inode,
+	    EXT2_INODE_MODE_DIRECTORY)) {
+		*has_children = false;
+		EXT2FS_DBG("EOK - false");
+		return EOK;
+	}
+	
+	rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref, 0);
+	if (rc != EOK) {
+		EXT2FS_DBG("error %u", rc);
+		return rc;
+	}
+	
+	/* Find a non-empty directory entry */
+	while (it.current != NULL) {
+		if (it.current->inode != 0) {
+			name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
+				it.current);
+			if (!ext2fs_is_dots(&it.current->name, name_size)) {
+				found = true;
+				break;
+			}
+		}
+		
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK) {
+			ext2_directory_iterator_fini(&it);
+			EXT2FS_DBG("error %u", rc);
+			return rc;
+		}
+	}
+	
+	rc = ext2_directory_iterator_fini(&it);
+	if (rc != EOK) {
+		EXT2FS_DBG("error %u", rc);
+		return rc;
+	}
+
+	*has_children = found;
+	EXT2FS_DBG("EOK");
+	
+	return EOK;
+}
+
+
+fs_index_t ext2fs_index_get(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	EXT2FS_DBG("%u", enode->inode_ref->index);
+	return enode->inode_ref->index;
+}
+
+aoff64_t ext2fs_size_get(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	aoff64_t size = ext2_inode_get_size(enode->instance->filesystem->superblock,
+	    enode->inode_ref->inode);
+	EXT2FS_DBG("%" PRIu64, size);
+	return size;
+}
+
+unsigned ext2fs_lnkcnt_get(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	unsigned count = ext2_inode_get_usage_count(enode->inode_ref->inode);
+	EXT2FS_DBG("%u", count);
+	return count;
+}
+
+bool ext2fs_is_directory(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	bool is_dir = ext2_inode_is_type(enode->instance->filesystem->superblock,
+	    enode->inode_ref->inode, EXT2_INODE_MODE_DIRECTORY);
+	EXT2FS_DBG("%s", is_dir ? "true" : "false");
+	EXT2FS_DBG("%u", enode->inode_ref->index);
+	return is_dir;
+}
+
+bool ext2fs_is_file(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	bool is_file = ext2_inode_is_type(enode->instance->filesystem->superblock,
+	    enode->inode_ref->inode, EXT2_INODE_MODE_FILE);
+	EXT2FS_DBG("%s", is_file ? "true" : "false");
+	return is_file;
+}
+
+service_id_t ext2fs_device_get(fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	return enode->instance->service_id;
+}
+
+/** libfs operations */
+libfs_ops_t ext2fs_libfs_ops = {
+	.root_get = ext2fs_root_get,
+	.match = ext2fs_match,
+	.node_get = ext2fs_node_get,
+	.node_open = ext2fs_node_open,
+	.node_put = ext2fs_node_put,
+	.create = ext2fs_create_node,
+	.destroy = ext2fs_destroy_node,
+	.link = ext2fs_link,
+	.unlink = ext2fs_unlink,
+	.has_children = ext2fs_has_children,
+	.index_get = ext2fs_index_get,
+	.size_get = ext2fs_size_get,
+	.lnkcnt_get = ext2fs_lnkcnt_get,
+	.is_directory = ext2fs_is_directory,
+	.is_file = ext2fs_is_file,
+	.device_get = ext2fs_device_get
+};
+
+/*
+ * VFS operations.
+ */
+
+static int ext2fs_mounted(service_id_t service_id, const char *opts,
+   fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	EXT2FS_DBG("");
+	int rc;
+	ext2_filesystem_t *fs;
+	ext2fs_instance_t *inst;
+	bool read_only;
+	
+	/* Allocate libext2 filesystem structure */
+	fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
+	if (fs == NULL)
+		return ENOMEM;
+	
+	/* Allocate instance structure */
+	inst = (ext2fs_instance_t *) malloc(sizeof(ext2fs_instance_t));
+	if (inst == NULL) {
+		free(fs);
+		return ENOMEM;
+	}
+	
+	/* Initialize the filesystem  */
+	rc = ext2_filesystem_init(fs, service_id);
+	if (rc != EOK) {
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Do some sanity checking */
+	rc = ext2_filesystem_check_sanity(fs);
+	if (rc != EOK) {
+		ext2_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Check flags */
+	rc = ext2_filesystem_check_flags(fs, &read_only);
+	if (rc != EOK) {
+		ext2_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Initialize instance */
+	link_initialize(&inst->link);
+	inst->service_id = service_id;
+	inst->filesystem = fs;
+	inst->open_nodes_count = 0;
+	
+	/* Read root node */
+	fs_node_t *root_node;
+	rc = ext2fs_node_get_core(&root_node, inst, EXT2_INODE_ROOT_INDEX);
+	if (rc != EOK) {
+		ext2_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	ext2fs_node_t *enode = EXT2FS_NODE(root_node);
+		
+	/* Add instance to the list */
+	fibril_mutex_lock(&instance_list_mutex);
+	list_append(&inst->link, &instance_list);
+	fibril_mutex_unlock(&instance_list_mutex);
+	
+	*index = EXT2_INODE_ROOT_INDEX;
+	*size = 0;
+	*lnkcnt = ext2_inode_get_usage_count(enode->inode_ref->inode);
+	
+	ext2fs_node_put(root_node);
+
+	return EOK;
+}
+
+static int ext2fs_unmounted(service_id_t service_id)
+{
+	EXT2FS_DBG("");
+	ext2fs_instance_t *inst;
+	int rc;
+	
+	rc = ext2fs_instance_get(service_id, &inst);
+	
+	if (rc != EOK)
+		return rc;
+	
+	fibril_mutex_lock(&open_nodes_lock);
+
+	EXT2FS_DBG("open_nodes_count = %d", inst->open_nodes_count)
+	if (inst->open_nodes_count != 0) {
+		fibril_mutex_unlock(&open_nodes_lock);
+		return EBUSY;
+	}
+	
+	/* Remove the instance from the list */
+	fibril_mutex_lock(&instance_list_mutex);
+	list_remove(&inst->link);
+	fibril_mutex_unlock(&instance_list_mutex);
+
+	fibril_mutex_unlock(&open_nodes_lock);
+	
+	ext2_filesystem_fini(inst->filesystem);
+	
+	return EOK;
+}
+
+static int
+ext2fs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
+	EXT2FS_DBG("");
+	
+	ext2fs_instance_t *inst;
+	ext2_inode_ref_t *inode_ref;
+	int rc;
+	
+	/*
+	 * Receive the read request.
+	 */
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	rc = ext2fs_instance_get(service_id, &inst);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
+	    EXT2_INODE_MODE_FILE)) {
+		rc = ext2fs_read_file(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else if (ext2_inode_is_type(inst->filesystem->superblock,
+	    inode_ref->inode, EXT2_INODE_MODE_DIRECTORY)) {
+		rc = ext2fs_read_directory(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else {
+		/* Other inode types not supported */
+		async_answer_0(callid, ENOTSUP);
+		rc = ENOTSUP;
+	}
+	
+	ext2_filesystem_put_inode_ref(inode_ref);
+	
+	return rc;
+}
+
+/**
+ * Determine whether given directory entry name is . or ..
+ */
+bool ext2fs_is_dots(const uint8_t *name, size_t name_size) {
+	if (name_size == 1 && name[0] == '.') {
+		return true;
+	}
+	
+	if (name_size == 2 && name[0] == '.' && name[1] == '.') {
+		return true;
+	}
+	
+	return false;
+}
+
+int ext2fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
+{
+	ext2_directory_iterator_t it;
+	aoff64_t next;
+	uint8_t *buf;
+	size_t name_size;
+	int rc;
+	bool found = false;
+	
+	rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref, pos);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/* Find next interesting directory entry.
+	 * We want to skip . and .. entries
+	 * as these are not used in HelenOS
+	 */
+	while (it.current != NULL) {
+		if (it.current->inode == 0) {
+			goto skip;
+		}
+		
+		name_size = ext2_directory_entry_ll_get_name_length(
+		    inst->filesystem->superblock, it.current);
+		
+		/* skip . and .. */
+		if (ext2fs_is_dots(&it.current->name, name_size)) {
+			goto skip;
+		}
+		
+		/* The on-disk entry does not contain \0 at the end
+		 * end of entry name, so we copy it to new buffer
+		 * and add the \0 at the end
+		 */
+		buf = malloc(name_size+1);
+		if (buf == NULL) {
+			ext2_directory_iterator_fini(&it);
+			async_answer_0(callid, ENOMEM);
+			return ENOMEM;
+		}
+		memcpy(buf, &it.current->name, name_size);
+		*(buf + name_size) = 0;
+		found = true;
+		(void) async_data_read_finalize(callid, buf, name_size + 1);
+		free(buf);
+		break;
+		
+skip:
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK) {
+			ext2_directory_iterator_fini(&it);
+			async_answer_0(callid, rc);
+			return rc;
+		}
+	}
+	
+	if (found) {
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK)
+			return rc;
+		next = it.current_offset;
+	}
+	
+	rc = ext2_directory_iterator_fini(&it);
+	if (rc != EOK)
+		return rc;
+	
+	if (found) {
+		*rbytes = next - pos;
+		return EOK;
+	} else {
+		async_answer_0(callid, ENOENT);
+		return ENOENT;
+	}
+}
+
+int ext2fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
+{
+	int rc;
+	uint32_t block_size;
+	aoff64_t file_block;
+	uint64_t file_size;
+	uint32_t fs_block;
+	size_t offset_in_block;
+	size_t bytes;
+	block_t *block;
+	uint8_t *buffer;
+	
+	file_size = ext2_inode_get_size(inst->filesystem->superblock,
+		inode_ref->inode);
+	
+	if (pos >= file_size) {
+		/* Read 0 bytes successfully */
+		async_data_read_finalize(callid, NULL, 0);
+		*rbytes = 0;
+		return EOK;
+	}
+	
+	/* For now, we only read data from one block at a time */
+	block_size = ext2_superblock_get_block_size(inst->filesystem->superblock);
+	file_block = pos / block_size;
+	offset_in_block = pos % block_size;
+	bytes = min(block_size - offset_in_block, size);
+	
+	/* Handle end of file */
+	if (pos + bytes > file_size) {
+		bytes = file_size - pos;
+	}
+	
+	/* Get the real block number */
+	rc = ext2_filesystem_get_inode_data_block_index(inst->filesystem,
+		inode_ref->inode, file_block, &fs_block);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/* Check for sparse file
+	 * If ext2_filesystem_get_inode_data_block_index returned
+	 * fs_block == 0, it means that the given block is not allocated for the 
+	 * file and we need to return a buffer of zeros
+	 */
+	if (fs_block == 0) {
+		buffer = malloc(bytes);
+		if (buffer == NULL) {
+			async_answer_0(callid, ENOMEM);
+			return ENOMEM;
+		}
+		
+		memset(buffer, 0, bytes);
+		
+		async_data_read_finalize(callid, buffer, bytes);
+		*rbytes = bytes;
+		
+		free(buffer);
+		
+		return EOK;
+	}
+	
+	/* Usual case - we need to read a block from device */
+	rc = block_get(&block, inst->service_id, fs_block, BLOCK_FLAGS_NONE);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	assert(offset_in_block + bytes <= block_size);
+	async_data_read_finalize(callid, block->data + offset_in_block, bytes);
+	
+	rc = block_put(block);
+	if (rc != EOK)
+		return rc;
+	
+	*rbytes = bytes;
+	return EOK;
+}
+
+static int
+ext2fs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int
+ext2fs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int ext2fs_close(service_id_t service_id, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return EOK;
+}
+
+static int ext2fs_destroy(service_id_t service_id, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int ext2fs_sync(service_id_t service_id, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+vfs_out_ops_t ext2fs_ops = {
+	.mounted = ext2fs_mounted,
+	.unmounted = ext2fs_unmounted,
+	.read = ext2fs_read,
+	.write = ext2fs_write,
+	.truncate = ext2fs_truncate,
+	.close = ext2fs_close,
+	.destroy = ext2fs_destroy,
+	.sync = ext2fs_sync,
+};
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/fat/Makefile
===================================================================
--- uspace/srv/fs/fat/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/fat/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,4 +32,5 @@
 EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX)
 BINARY = fat
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/fat/fat.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,5 +39,5 @@
 #include "fat.h"
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <errno.h>
@@ -56,108 +56,20 @@
 };
 
-fs_reg_t fat_reg;
-
-/**
- * This connection fibril processes VFS requests from VFS.
- *
- * In order to support simultaneous VFS requests, our design is as follows.
- * The connection fibril accepts VFS requests from VFS. If there is only one
- * instance of the fibril, VFS will need to serialize all VFS requests it sends
- * to FAT. To overcome this bottleneck, VFS can send FAT the IPC_M_CONNECT_ME_TO
- * call. In that case, a new connection fibril will be created, which in turn
- * will accept the call. Thus, a new phone will be opened for VFS.
- *
- * There are few issues with this arrangement. First, VFS can run out of
- * available phones. In that case, VFS can close some other phones or use one
- * phone for more serialized requests. Similarily, FAT can refuse to duplicate
- * the connection. VFS should then just make use of already existing phones and
- * route its requests through them. To avoid paying the fibril creation price 
- * upon each request, FAT might want to keep the connections open after the
- * request has been completed.
- */
-static void fat_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (iid) {
-		/*
-		 * This only happens for connections opened by
-		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
-		 * created by IPC_M_CONNECT_TO_ME.
-		 */
-		async_answer_0(iid, EOK);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	while (1) {
-		ipc_callid_t callid;
-		ipc_call_t call;
-	
-		callid = async_get_call(&call);
-		switch  (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			return;
-		case VFS_OUT_MOUNTED:
-			fat_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			fat_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			fat_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			fat_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			fat_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			fat_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			fat_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			fat_truncate(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			fat_stat(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			fat_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			fat_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			fat_open_node(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			fat_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
-	int vfs_phone;
-	int rc;
-
 	printf(NAME ": HelenOS FAT file system server\n");
-
-	rc = fat_idx_init();
+	
+	int rc = fat_idx_init();
 	if (rc != EOK)
 		goto err;
-
-	vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
-	if (vfs_phone < EOK) {
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
 		printf(NAME ": failed to connect to VFS\n");
 		return -1;
 	}
 	
-	rc = fs_register(vfs_phone, &fat_reg, &fat_vfs_info, fat_connection);
+	rc = fs_register(vfs_sess, &fat_vfs_info, &fat_ops, &fat_libfs_ops);
 	if (rc != EOK) {
 		fat_idx_fini();
@@ -168,7 +80,8 @@
 	task_retval(0);
 	async_manager();
-	/* not reached */
+	
+	/* Not reached */
 	return 0;
-
+	
 err:
 	printf(NAME ": Failed to register file system (%d)\n", rc);
@@ -178,3 +91,3 @@
 /**
  * @}
- */ 
+ */
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/fat/fat.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -175,5 +175,5 @@
 
 	fibril_mutex_t	lock;
-	devmap_handle_t	devmap_handle;
+	service_id_t	service_id;
 	fs_index_t	index;
 	/**
@@ -224,24 +224,10 @@
 } fat_node_t;
 
-extern fs_reg_t fat_reg;
-
-extern void fat_mounted(ipc_callid_t, ipc_call_t *);
-extern void fat_mount(ipc_callid_t, ipc_call_t *);
-extern void fat_unmounted(ipc_callid_t, ipc_call_t *);
-extern void fat_unmount(ipc_callid_t, ipc_call_t *);
-extern void fat_lookup(ipc_callid_t, ipc_call_t *);
-extern void fat_read(ipc_callid_t, ipc_call_t *);
-extern void fat_write(ipc_callid_t, ipc_call_t *);
-extern void fat_truncate(ipc_callid_t, ipc_call_t *);
-extern void fat_stat(ipc_callid_t, ipc_call_t *);
-extern void fat_close(ipc_callid_t, ipc_call_t *);
-extern void fat_destroy(ipc_callid_t, ipc_call_t *);
-extern void fat_open_node(ipc_callid_t, ipc_call_t *);
-extern void fat_stat(ipc_callid_t, ipc_call_t *);
-extern void fat_sync(ipc_callid_t, ipc_call_t *);
-
-extern int fat_idx_get_new(fat_idx_t **, devmap_handle_t);
-extern fat_idx_t *fat_idx_get_by_pos(devmap_handle_t, fat_cluster_t, unsigned);
-extern fat_idx_t *fat_idx_get_by_index(devmap_handle_t, fs_index_t);
+extern vfs_out_ops_t fat_ops;
+extern libfs_ops_t fat_libfs_ops;
+
+extern int fat_idx_get_new(fat_idx_t **, service_id_t);
+extern fat_idx_t *fat_idx_get_by_pos(service_id_t, fat_cluster_t, unsigned);
+extern fat_idx_t *fat_idx_get_by_index(service_id_t, fs_index_t);
 extern void fat_idx_destroy(fat_idx_t *);
 extern void fat_idx_hashin(fat_idx_t *);
@@ -250,6 +236,6 @@
 extern int fat_idx_init(void);
 extern void fat_idx_fini(void);
-extern int fat_idx_init_by_devmap_handle(devmap_handle_t);
-extern void fat_idx_fini_by_devmap_handle(devmap_handle_t);
+extern int fat_idx_init_by_service_id(service_id_t);
+extern void fat_idx_fini_by_service_id(service_id_t);
 
 #endif
Index: uspace/srv/fs/fat/fat_fat.c
===================================================================
--- uspace/srv/fs/fat/fat_fat.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/fat/fat_fat.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -47,4 +47,5 @@
 #include <assert.h>
 #include <fibril_synch.h>
+#include <malloc.h>
 #include <mem.h>
 
@@ -70,5 +71,5 @@
  *
  * @param bs		Buffer holding the boot sector for the file.
- * @param devmap_handle	Device handle of the device with the file.
+ * @param service_id	Service ID of the device with the file.
  * @param firstc	First cluster to start the walk with.
  * @param lastc		If non-NULL, output argument hodling the last cluster
@@ -81,5 +82,5 @@
  */
 int 
-fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
+fat_cluster_walk(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc,
     fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
 {
@@ -108,5 +109,5 @@
 		fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
 		/* read FAT1 */
-		rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec,
+		rc = block_get(&b, service_id, RSCNT(bs) + fsec,
 		    BLOCK_FLAGS_NONE);
 		if (rc != EOK)
@@ -159,5 +160,5 @@
 		 * when fortunately we have the last cluster number cached.
 		 */
-		return block_get(block, nodep->idx->devmap_handle,
+		return block_get(block, nodep->idx->service_id,
 		    CLBN2PBN(bs, nodep->lastc_cached_value, bn), flags);
 	}
@@ -173,5 +174,5 @@
 
 fall_through:
-	rc = _fat_block_get(block, bs, nodep->idx->devmap_handle, firstc,
+	rc = _fat_block_get(block, bs, nodep->idx->service_id, firstc,
 	    &currc, relbn, flags);
 	if (rc != EOK)
@@ -192,5 +193,5 @@
  * @param block		Pointer to a block pointer for storing result.
  * @param bs		Buffer holding the boot sector of the file system.
- * @param devmap_handle	Device handle of the file system.
+ * @param service_id	Service ID handle of the file system.
  * @param fcl		First cluster used by the file. Can be zero if the file
  *			is empty.
@@ -204,5 +205,5 @@
  */
 int
-_fat_block_get(block_t **block, fat_bs_t *bs, devmap_handle_t devmap_handle,
+_fat_block_get(block_t **block, fat_bs_t *bs, service_id_t service_id,
     fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
 {
@@ -221,5 +222,5 @@
 		/* root directory special case */
 		assert(bn < RDS(bs));
-		rc = block_get(block, devmap_handle,
+		rc = block_get(block, service_id,
 		    RSCNT(bs) + FATCNT(bs) * SF(bs) + bn, flags);
 		return rc;
@@ -227,10 +228,10 @@
 
 	max_clusters = bn / SPC(bs);
-	rc = fat_cluster_walk(bs, devmap_handle, fcl, &c, &clusters, max_clusters);
+	rc = fat_cluster_walk(bs, service_id, fcl, &c, &clusters, max_clusters);
 	if (rc != EOK)
 		return rc;
 	assert(clusters == max_clusters);
 
-	rc = block_get(block, devmap_handle, CLBN2PBN(bs, c, bn), flags);
+	rc = block_get(block, service_id, CLBN2PBN(bs, c, bn), flags);
 
 	if (clp)
@@ -280,5 +281,5 @@
 	/* zero out the initial part of the new cluster chain */
 	for (o = boundary; o < pos; o += BPS(bs)) {
-		rc = _fat_block_get(&b, bs, nodep->idx->devmap_handle, mcl,
+		rc = _fat_block_get(&b, bs, nodep->idx->service_id, mcl,
 		    NULL, (o - boundary) / BPS(bs), BLOCK_FLAGS_NOREAD);
 		if (rc != EOK)
@@ -297,5 +298,5 @@
  *
  * @param bs		Buffer holding the boot sector for the file system.
- * @param devmap_handle	Device handle for the file system.
+ * @param service_id	Service ID for the file system.
  * @param clst		Cluster which to get.
  * @param value		Output argument holding the value of the cluster.
@@ -304,5 +305,5 @@
  */
 int
-fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
+fat_get_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     fat_cluster_t clst, fat_cluster_t *value)
 {
@@ -311,5 +312,5 @@
 	int rc;
 
-	rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
+	rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
 	    (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
 	if (rc != EOK)
@@ -326,5 +327,5 @@
  *
  * @param bs		Buffer holding the boot sector for the file system.
- * @param devmap_handle	Device handle for the file system.
+ * @param service_id	Device service ID for the file system.
  * @param fatno		Number of the FAT instance where to make the change.
  * @param clst		Cluster which is to be set.
@@ -334,5 +335,5 @@
  */
 int
-fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
+fat_set_cluster(fat_bs_t *bs, service_id_t service_id, unsigned fatno,
     fat_cluster_t clst, fat_cluster_t value)
 {
@@ -342,5 +343,5 @@
 
 	assert(fatno < FATCNT(bs));
-	rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
+	rc = block_get(&b, service_id, RSCNT(bs) + SF(bs) * fatno +
 	    (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
 	if (rc != EOK)
@@ -357,5 +358,5 @@
  *
  * @param bs		Buffer holding the boot sector of the file system.
- * @param devmap_handle	Device handle of the file system.
+ * @param service_id	Service ID of the file system.
  * @param lifo		Chain of allocated clusters.
  * @param nclsts	Number of clusters in the lifo chain.
@@ -363,5 +364,5 @@
  * @return		EOK on success or a negative error code.
  */
-int fat_alloc_shadow_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle,
+int fat_alloc_shadow_clusters(fat_bs_t *bs, service_id_t service_id,
     fat_cluster_t *lifo, unsigned nclsts)
 {
@@ -372,5 +373,5 @@
 	for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
 		for (c = 0; c < nclsts; c++) {
-			rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
+			rc = fat_set_cluster(bs, service_id, fatno, lifo[c],
 			    c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
 			if (rc != EOK)
@@ -390,5 +391,5 @@
  *
  * @param bs		Buffer holding the boot sector of the file system.
- * @param devmap_handle	Device handle of the file system.
+ * @param service_id	Device service ID of the file system.
  * @param nclsts	Number of clusters to allocate.
  * @param mcl		Output parameter where the first cluster in the chain
@@ -400,5 +401,5 @@
  */
 int
-fat_alloc_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned nclsts,
+fat_alloc_clusters(fat_bs_t *bs, service_id_t service_id, unsigned nclsts,
     fat_cluster_t *mcl, fat_cluster_t *lcl)
 {
@@ -418,5 +419,5 @@
 	fibril_mutex_lock(&fat_alloc_lock);
 	for (b = 0, cl = 0; b < SF(bs); b++) {
-		rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
+		rc = block_get(&blk, service_id, RSCNT(bs) + b,
 		    BLOCK_FLAGS_NONE);
 		if (rc != EOK)
@@ -457,5 +458,5 @@
 					/* update the shadow copies of FAT */
 					rc = fat_alloc_shadow_clusters(bs,
-					    devmap_handle, lifo, nclsts);
+					    service_id, lifo, nclsts);
 					if (rc != EOK)
 						goto error;
@@ -484,5 +485,5 @@
 	 */
 	while (found--) {
-		rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
+		rc = fat_set_cluster(bs, service_id, FAT1, lifo[found],
 		    FAT_CLST_RES0);
 		if (rc != EOK) {
@@ -499,5 +500,5 @@
  *
  * @param bs		Buffer hodling the boot sector of the file system.
- * @param devmap_handle	Device handle of the file system.
+ * @param service_id	Device service ID of the file system.
  * @param firstc	First cluster in the chain which is to be freed.
  *
@@ -505,5 +506,5 @@
  */
 int
-fat_free_clusters(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc)
+fat_free_clusters(fat_bs_t *bs, service_id_t service_id, fat_cluster_t firstc)
 {
 	unsigned fatno;
@@ -514,9 +515,9 @@
 	while (firstc < FAT_CLST_LAST1) {
 		assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
-		rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
+		rc = fat_get_cluster(bs, service_id, FAT1, firstc, &nextc);
 		if (rc != EOK)
 			return rc;
 		for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
-			rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
+			rc = fat_set_cluster(bs, service_id, fatno, firstc,
 			    FAT_CLST_RES0);
 			if (rc != EOK)
@@ -543,5 +544,5 @@
     fat_cluster_t lcl)
 {
-	devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
+	service_id_t service_id = nodep->idx->service_id;
 	fat_cluster_t lastc;
 	uint8_t fatno;
@@ -557,5 +558,5 @@
 			nodep->lastc_cached_valid = false;
 		} else {
-			rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
+			rc = fat_cluster_walk(bs, service_id, nodep->firstc,
 			    &lastc, NULL, (uint16_t) -1);
 			if (rc != EOK)
@@ -564,5 +565,5 @@
 
 		for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
-			rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
+			rc = fat_set_cluster(bs, nodep->idx->service_id, fatno,
 			    lastc, mcl);
 			if (rc != EOK)
@@ -590,5 +591,5 @@
 {
 	int rc;
-	devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
+	service_id_t service_id = nodep->idx->service_id;
 
 	/*
@@ -601,5 +602,5 @@
 	if (lcl == FAT_CLST_RES0) {
 		/* The node will have zero size and no clusters allocated. */
-		rc = fat_free_clusters(bs, devmap_handle, nodep->firstc);
+		rc = fat_free_clusters(bs, service_id, nodep->firstc);
 		if (rc != EOK)
 			return rc;
@@ -610,5 +611,5 @@
 		unsigned fatno;
 
-		rc = fat_get_cluster(bs, devmap_handle, FAT1, lcl, &nextc);
+		rc = fat_get_cluster(bs, service_id, FAT1, lcl, &nextc);
 		if (rc != EOK)
 			return rc;
@@ -616,5 +617,5 @@
 		/* Terminate the cluster chain in all copies of FAT. */
 		for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
-			rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
+			rc = fat_set_cluster(bs, service_id, fatno, lcl,
 			    FAT_CLST_LAST1);
 			if (rc != EOK)
@@ -623,5 +624,5 @@
 
 		/* Free all following clusters. */
-		rc = fat_free_clusters(bs, devmap_handle, nextc);
+		rc = fat_free_clusters(bs, service_id, nextc);
 		if (rc != EOK)
 			return rc;
@@ -638,5 +639,5 @@
 
 int
-fat_zero_cluster(struct fat_bs *bs, devmap_handle_t devmap_handle, fat_cluster_t c)
+fat_zero_cluster(struct fat_bs *bs, service_id_t service_id, fat_cluster_t c)
 {
 	int i;
@@ -645,5 +646,5 @@
 
 	for (i = 0; i < SPC(bs); i++) {
-		rc = _fat_block_get(&b, bs, devmap_handle, c, NULL, i,
+		rc = _fat_block_get(&b, bs, service_id, c, NULL, i,
 		    BLOCK_FLAGS_NOREAD);
 		if (rc != EOK)
@@ -665,5 +666,5 @@
  * does not contain a fat file system.
  */
-int fat_sanity_check(fat_bs_t *bs, devmap_handle_t devmap_handle)
+int fat_sanity_check(fat_bs_t *bs, service_id_t service_id)
 {
 	fat_cluster_t e0, e1;
@@ -706,9 +707,9 @@
 
 	for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
-		rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
+		rc = fat_get_cluster(bs, service_id, fat_no, 0, &e0);
 		if (rc != EOK)
 			return EIO;
 
-		rc = fat_get_cluster(bs, devmap_handle, fat_no, 1, &e1);
+		rc = fat_get_cluster(bs, service_id, fat_no, 1, &e1);
 		if (rc != EOK)
 			return EIO;
Index: uspace/srv/fs/fat/fat_fat.h
===================================================================
--- uspace/srv/fs/fat/fat_fat.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/fat/fat_fat.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -61,10 +61,10 @@
 #define fat_clusters_get(numc, bs, dh, fc) \
     fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1)
-extern int fat_cluster_walk(struct fat_bs *, devmap_handle_t, fat_cluster_t,
+extern int fat_cluster_walk(struct fat_bs *, service_id_t, fat_cluster_t,
     fat_cluster_t *, uint16_t *, uint16_t);
 
 extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *,
     aoff64_t, int);
-extern int _fat_block_get(block_t **, struct fat_bs *, devmap_handle_t,
+extern int _fat_block_get(block_t **, struct fat_bs *, service_id_t,
     fat_cluster_t, fat_cluster_t *, aoff64_t, int);
 
@@ -73,17 +73,17 @@
 extern int fat_chop_clusters(struct fat_bs *, struct fat_node *,
     fat_cluster_t);
-extern int fat_alloc_clusters(struct fat_bs *, devmap_handle_t, unsigned,
+extern int fat_alloc_clusters(struct fat_bs *, service_id_t, unsigned,
     fat_cluster_t *, fat_cluster_t *);
-extern int fat_free_clusters(struct fat_bs *, devmap_handle_t, fat_cluster_t);
-extern int fat_alloc_shadow_clusters(struct fat_bs *, devmap_handle_t,
+extern int fat_free_clusters(struct fat_bs *, service_id_t, fat_cluster_t);
+extern int fat_alloc_shadow_clusters(struct fat_bs *, service_id_t,
     fat_cluster_t *, unsigned);
-extern int fat_get_cluster(struct fat_bs *, devmap_handle_t, unsigned,
+extern int fat_get_cluster(struct fat_bs *, service_id_t, unsigned,
     fat_cluster_t, fat_cluster_t *);
-extern int fat_set_cluster(struct fat_bs *, devmap_handle_t, unsigned,
+extern int fat_set_cluster(struct fat_bs *, service_id_t, unsigned,
     fat_cluster_t, fat_cluster_t);
 extern int fat_fill_gap(struct fat_bs *, struct fat_node *, fat_cluster_t,
     aoff64_t);
-extern int fat_zero_cluster(struct fat_bs *, devmap_handle_t, fat_cluster_t);
-extern int fat_sanity_check(struct fat_bs *, devmap_handle_t);
+extern int fat_zero_cluster(struct fat_bs *, service_id_t, fat_cluster_t);
+extern int fat_sanity_check(struct fat_bs *, service_id_t);
 
 #endif
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/fat/fat_idx.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,4 +44,5 @@
 #include <assert.h>
 #include <fibril_synch.h>
+#include <malloc.h>
 
 /** Each instance of this type describes one interval of freed VFS indices. */
@@ -58,13 +59,13 @@
 typedef struct {
 	link_t		link;
-	devmap_handle_t	devmap_handle;
+	service_id_t	service_id;
 
 	/** Next unassigned index. */
-	fs_index_t	next;
+	fs_index_t next;
 	/** Number of remaining unassigned indices. */
-	uint64_t	remaining;
+	uint64_t remaining;
 
 	/** Sorted list of intervals of freed indices. */
-	link_t		freed_head;
+	list_t freed_list;
 } unused_t;
 
@@ -73,27 +74,28 @@
 
 /** List of unused structures. */
-static LIST_INITIALIZE(unused_head);
-
-static void unused_initialize(unused_t *u, devmap_handle_t devmap_handle)
+static LIST_INITIALIZE(unused_list);
+
+static void unused_initialize(unused_t *u, service_id_t service_id)
 {
 	link_initialize(&u->link);
-	u->devmap_handle = devmap_handle;
+	u->service_id = service_id;
 	u->next = 0;
 	u->remaining = ((uint64_t)((fs_index_t)-1)) + 1;
-	list_initialize(&u->freed_head);
-}
-
-static unused_t *unused_find(devmap_handle_t devmap_handle, bool lock)
+	list_initialize(&u->freed_list);
+}
+
+static unused_t *unused_find(service_id_t service_id, bool lock)
 {
 	unused_t *u;
-	link_t *l;
 
 	if (lock)
 		fibril_mutex_lock(&unused_lock);
-	for (l = unused_head.next; l != &unused_head; l = l->next) {
+
+	list_foreach(unused_list, l) {
 		u = list_get_instance(l, unused_t, link);
-		if (u->devmap_handle == devmap_handle) 
+		if (u->service_id == service_id) 
 			return u;
 	}
+	
 	if (lock)
 		fibril_mutex_unlock(&unused_lock);
@@ -106,5 +108,5 @@
 /**
  * Global hash table of all used fat_idx_t structures.
- * The index structures are hashed by the devmap_handle, parent node's first
+ * The index structures are hashed by the service_id, parent node's first
  * cluster and index within the parent directory.
  */ 
@@ -120,5 +122,5 @@
 static hash_index_t pos_hash(unsigned long key[])
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t)key[UPH_DH_KEY];
+	service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
 	fat_cluster_t pfc = (fat_cluster_t)key[UPH_PFC_KEY];
 	unsigned pdi = (unsigned)key[UPH_PDI_KEY];
@@ -140,5 +142,5 @@
 	h |= (pdi & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
 	    (UPH_BUCKETS_LOG / 2); 
-	h |= (devmap_handle & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
+	h |= (service_id & ((1 << (UPH_BUCKETS_LOG / 4)) - 1)) <<
 	    (3 * (UPH_BUCKETS_LOG / 4));
 
@@ -148,5 +150,5 @@
 static int pos_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t)key[UPH_DH_KEY];
+	service_id_t service_id = (service_id_t)key[UPH_DH_KEY];
 	fat_cluster_t pfc;
 	unsigned pdi;
@@ -155,9 +157,9 @@
 	switch (keys) {
 	case 1:
-		return (devmap_handle == fidx->devmap_handle);
+		return (service_id == fidx->service_id);
 	case 3:
 		pfc = (fat_cluster_t) key[UPH_PFC_KEY];
 		pdi = (unsigned) key[UPH_PDI_KEY];
-		return (devmap_handle == fidx->devmap_handle) && (pfc == fidx->pfc) &&
+		return (service_id == fidx->service_id) && (pfc == fidx->pfc) &&
 		    (pdi == fidx->pdi);
 	default:
@@ -181,5 +183,5 @@
 /**
  * Global hash table of all used fat_idx_t structures.
- * The index structures are hashed by the devmap_handle and index.
+ * The index structures are hashed by the service_id and index.
  */
 static hash_table_t ui_hash;
@@ -193,10 +195,10 @@
 static hash_index_t idx_hash(unsigned long key[])
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t)key[UIH_DH_KEY];
+	service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
 	fs_index_t index = (fs_index_t)key[UIH_INDEX_KEY];
 
 	hash_index_t h;
 
-	h = devmap_handle & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
+	h = service_id & ((1 << (UIH_BUCKETS_LOG / 2)) - 1);
 	h |= (index & ((1 << (UIH_BUCKETS_LOG / 2)) - 1)) <<
 	    (UIH_BUCKETS_LOG / 2);
@@ -207,5 +209,5 @@
 static int idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
-	devmap_handle_t devmap_handle = (devmap_handle_t)key[UIH_DH_KEY];
+	service_id_t service_id = (service_id_t)key[UIH_DH_KEY];
 	fs_index_t index;
 	fat_idx_t *fidx = list_get_instance(item, fat_idx_t, uih_link);
@@ -213,8 +215,8 @@
 	switch (keys) {
 	case 1:
-		return (devmap_handle == fidx->devmap_handle);
+		return (service_id == fidx->service_id);
 	case 2:
 		index = (fs_index_t) key[UIH_INDEX_KEY];
-		return (devmap_handle == fidx->devmap_handle) &&
+		return (service_id == fidx->service_id) &&
 		    (index == fidx->index);
 	default:
@@ -239,14 +241,14 @@
 
 /** Allocate a VFS index which is not currently in use. */
-static bool fat_index_alloc(devmap_handle_t devmap_handle, fs_index_t *index)
+static bool fat_index_alloc(service_id_t service_id, fs_index_t *index)
 {
 	unused_t *u;
 	
 	assert(index);
-	u = unused_find(devmap_handle, true);
+	u = unused_find(service_id, true);
 	if (!u)
 		return false;	
 
-	if (list_empty(&u->freed_head)) {
+	if (list_empty(&u->freed_list)) {
 		if (u->remaining) { 
 			/*
@@ -261,6 +263,6 @@
 	} else {
 		/* There are some freed indices which we can reuse. */
-		freed_t *f = list_get_instance(u->freed_head.next, freed_t,
-		    link);
+		freed_t *f = list_get_instance(list_first(&u->freed_list),
+		    freed_t, link);
 		*index = f->first;
 		if (f->first++ == f->last) {
@@ -301,9 +303,9 @@
 
 /** Free a VFS index, which is no longer in use. */
-static void fat_index_free(devmap_handle_t devmap_handle, fs_index_t index)
+static void fat_index_free(service_id_t service_id, fs_index_t index)
 {
 	unused_t *u;
 
-	u = unused_find(devmap_handle, true);
+	u = unused_find(service_id, true);
 	assert(u);
 
@@ -319,10 +321,10 @@
 		link_t *lnk;
 		freed_t *n;
-		for (lnk = u->freed_head.next; lnk != &u->freed_head;
+		for (lnk = u->freed_list.head.next; lnk != &u->freed_list.head;
 		    lnk = lnk->next) {
 			freed_t *f = list_get_instance(lnk, freed_t, link);
 			if (f->first == index + 1) {
 				f->first--;
-				if (lnk->prev != &u->freed_head)
+				if (lnk->prev != &u->freed_list.head)
 					try_coalesce_intervals(lnk->prev, lnk,
 					    lnk);
@@ -332,5 +334,5 @@
 			if (f->last == index - 1) {
 				f->last++;
-				if (lnk->next != &u->freed_head)
+				if (lnk->next != &u->freed_list.head)
 					try_coalesce_intervals(lnk, lnk->next,
 					    lnk);
@@ -358,10 +360,10 @@
 		n->first = index;
 		n->last = index;
-		list_append(&n->link, &u->freed_head);
+		list_append(&n->link, &u->freed_list);
 	}
 	fibril_mutex_unlock(&unused_lock);
 }
 
-static int fat_idx_create(fat_idx_t **fidxp, devmap_handle_t devmap_handle)
+static int fat_idx_create(fat_idx_t **fidxp, service_id_t service_id)
 {
 	fat_idx_t *fidx;
@@ -370,5 +372,5 @@
 	if (!fidx) 
 		return ENOMEM;
-	if (!fat_index_alloc(devmap_handle, &fidx->index)) {
+	if (!fat_index_alloc(service_id, &fidx->index)) {
 		free(fidx);
 		return ENOSPC;
@@ -378,5 +380,5 @@
 	link_initialize(&fidx->uih_link);
 	fibril_mutex_initialize(&fidx->lock);
-	fidx->devmap_handle = devmap_handle;
+	fidx->service_id = service_id;
 	fidx->pfc = FAT_CLST_RES0;	/* no parent yet */
 	fidx->pdi = 0;
@@ -387,5 +389,5 @@
 }
 
-int fat_idx_get_new(fat_idx_t **fidxp, devmap_handle_t devmap_handle)
+int fat_idx_get_new(fat_idx_t **fidxp, service_id_t service_id)
 {
 	fat_idx_t *fidx;
@@ -393,5 +395,5 @@
 
 	fibril_mutex_lock(&used_lock);
-	rc = fat_idx_create(&fidx, devmap_handle);
+	rc = fat_idx_create(&fidx, service_id);
 	if (rc != EOK) {
 		fibril_mutex_unlock(&used_lock);
@@ -400,5 +402,5 @@
 		
 	unsigned long ikey[] = {
-		[UIH_DH_KEY] = devmap_handle,
+		[UIH_DH_KEY] = service_id,
 		[UIH_INDEX_KEY] = fidx->index,
 	};
@@ -413,10 +415,10 @@
 
 fat_idx_t *
-fat_idx_get_by_pos(devmap_handle_t devmap_handle, fat_cluster_t pfc, unsigned pdi)
+fat_idx_get_by_pos(service_id_t service_id, fat_cluster_t pfc, unsigned pdi)
 {
 	fat_idx_t *fidx;
 	link_t *l;
 	unsigned long pkey[] = {
-		[UPH_DH_KEY] = devmap_handle,
+		[UPH_DH_KEY] = service_id,
 		[UPH_PFC_KEY] = pfc,
 		[UPH_PDI_KEY] = pdi,
@@ -430,5 +432,5 @@
 		int rc;
 
-		rc = fat_idx_create(&fidx, devmap_handle);
+		rc = fat_idx_create(&fidx, service_id);
 		if (rc != EOK) {
 			fibril_mutex_unlock(&used_lock);
@@ -437,5 +439,5 @@
 		
 		unsigned long ikey[] = {
-			[UIH_DH_KEY] = devmap_handle,
+			[UIH_DH_KEY] = service_id,
 			[UIH_INDEX_KEY] = fidx->index,
 		};
@@ -456,5 +458,5 @@
 {
 	unsigned long pkey[] = {
-		[UPH_DH_KEY] = idx->devmap_handle,
+		[UPH_DH_KEY] = idx->service_id,
 		[UPH_PFC_KEY] = idx->pfc,
 		[UPH_PDI_KEY] = idx->pdi,
@@ -469,5 +471,5 @@
 {
 	unsigned long pkey[] = {
-		[UPH_DH_KEY] = idx->devmap_handle,
+		[UPH_DH_KEY] = idx->service_id,
 		[UPH_PFC_KEY] = idx->pfc,
 		[UPH_PDI_KEY] = idx->pdi,
@@ -480,10 +482,10 @@
 
 fat_idx_t *
-fat_idx_get_by_index(devmap_handle_t devmap_handle, fs_index_t index)
+fat_idx_get_by_index(service_id_t service_id, fs_index_t index)
 {
 	fat_idx_t *fidx = NULL;
 	link_t *l;
 	unsigned long ikey[] = {
-		[UIH_DH_KEY] = devmap_handle,
+		[UIH_DH_KEY] = service_id,
 		[UIH_INDEX_KEY] = index,
 	};
@@ -507,8 +509,8 @@
 {
 	unsigned long ikey[] = {
-		[UIH_DH_KEY] = idx->devmap_handle,
+		[UIH_DH_KEY] = idx->service_id,
 		[UIH_INDEX_KEY] = idx->index,
 	};
-	devmap_handle_t devmap_handle = idx->devmap_handle;
+	service_id_t service_id = idx->service_id;
 	fs_index_t index = idx->index;
 
@@ -524,5 +526,5 @@
 	fibril_mutex_unlock(&used_lock);
 	/* Release the VFS index. */
-	fat_index_free(devmap_handle, index);
+	fat_index_free(service_id, index);
 	/* The index structure itself is freed in idx_remove_callback(). */
 }
@@ -546,5 +548,5 @@
 }
 
-int fat_idx_init_by_devmap_handle(devmap_handle_t devmap_handle)
+int fat_idx_init_by_service_id(service_id_t service_id)
 {
 	unused_t *u;
@@ -554,8 +556,8 @@
 	if (!u)
 		return ENOMEM;
-	unused_initialize(u, devmap_handle);
+	unused_initialize(u, service_id);
 	fibril_mutex_lock(&unused_lock);
-	if (!unused_find(devmap_handle, false)) {
-		list_append(&u->link, &unused_head);
+	if (!unused_find(service_id, false)) {
+		list_append(&u->link, &unused_list);
 	} else {
 		free(u);
@@ -566,11 +568,11 @@
 }
 
-void fat_idx_fini_by_devmap_handle(devmap_handle_t devmap_handle)
+void fat_idx_fini_by_service_id(service_id_t service_id)
 {
 	unsigned long ikey[] = {
-		[UIH_DH_KEY] = devmap_handle
+		[UIH_DH_KEY] = service_id
 	};
 	unsigned long pkey[] = {
-		[UPH_DH_KEY] = devmap_handle
+		[UPH_DH_KEY] = service_id
 	};
 
@@ -588,12 +590,12 @@
 	 * Free the unused and freed structures for this instance.
 	 */
-	unused_t *u = unused_find(devmap_handle, true);
+	unused_t *u = unused_find(service_id, true);
 	assert(u);
 	list_remove(&u->link);
 	fibril_mutex_unlock(&unused_lock);
 
-	while (!list_empty(&u->freed_head)) {
+	while (!list_empty(&u->freed_list)) {
 		freed_t *f;
-		f = list_get_instance(u->freed_head.next, freed_t, link);
+		f = list_get_instance(list_first(&u->freed_list), freed_t, link);
 		list_remove(&f->link);
 		free(f);
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/fat/fat_ops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,5 +43,5 @@
 #include <libblock.h>
 #include <ipc/services.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <macros.h>
 #include <async.h>
@@ -55,4 +55,5 @@
 #include <sys/mman.h>
 #include <align.h>
+#include <malloc.h>
 
 #define FAT_NODE(node)	((node) ? (fat_node_t *) (node)->data : NULL)
@@ -66,15 +67,15 @@
 
 /** List of cached free FAT nodes. */
-static LIST_INITIALIZE(ffn_head);
+static LIST_INITIALIZE(ffn_list);
 
 /*
  * Forward declarations of FAT libfs operations.
  */
-static int fat_root_get(fs_node_t **, devmap_handle_t);
+static int fat_root_get(fs_node_t **, service_id_t);
 static int fat_match(fs_node_t **, fs_node_t *, const char *);
-static int fat_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
+static int fat_node_get(fs_node_t **, service_id_t, fs_index_t);
 static int fat_node_open(fs_node_t *);
 static int fat_node_put(fs_node_t *);
-static int fat_create_node(fs_node_t **, devmap_handle_t, int);
+static int fat_create_node(fs_node_t **, service_id_t, int);
 static int fat_destroy_node(fs_node_t *);
 static int fat_link(fs_node_t *, fs_node_t *, const char *);
@@ -84,8 +85,7 @@
 static aoff64_t fat_size_get(fs_node_t *);
 static unsigned fat_lnkcnt_get(fs_node_t *);
-static char fat_plb_get_char(unsigned);
 static bool fat_is_directory(fs_node_t *);
 static bool fat_is_file(fs_node_t *node);
-static devmap_handle_t fat_device_get(fs_node_t *node);
+static service_id_t fat_device_get(fs_node_t *node);
 
 /*
@@ -119,8 +119,8 @@
 	assert(node->dirty);
 
-	bs = block_bb_get(node->idx->devmap_handle);
+	bs = block_bb_get(node->idx->service_id);
 	
 	/* Read the block that contains the dentry of interest. */
-	rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc,
+	rc = _fat_block_get(&b, bs, node->idx->service_id, node->idx->pfc,
 	    NULL, (node->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
 	    BLOCK_FLAGS_NONE);
@@ -144,7 +144,6 @@
 }
 
-static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
-{
-	link_t *lnk;
+static int fat_node_fini_by_service_id(service_id_t service_id)
+{
 	fat_node_t *nodep;
 	int rc;
@@ -158,5 +157,5 @@
 restart:
 	fibril_mutex_lock(&ffn_mutex);
-	for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
+	list_foreach(ffn_list, lnk) {
 		nodep = list_get_instance(lnk, fat_node_t, ffn_link);
 		if (!fibril_mutex_trylock(&nodep->lock)) {
@@ -169,5 +168,5 @@
 			goto restart;
 		}
-		if (nodep->idx->devmap_handle != devmap_handle) {
+		if (nodep->idx->service_id != service_id) {
 			fibril_mutex_unlock(&nodep->idx->lock);
 			fibril_mutex_unlock(&nodep->lock);
@@ -195,5 +194,5 @@
 		free(nodep);
 
-		/* Need to restart because we changed the ffn_head list. */
+		/* Need to restart because we changed ffn_list. */
 		goto restart;
 	}
@@ -210,8 +209,9 @@
 
 	fibril_mutex_lock(&ffn_mutex);
-	if (!list_empty(&ffn_head)) {
+	if (!list_empty(&ffn_list)) {
 		/* Try to use a cached free node structure. */
 		fat_idx_t *idxp_tmp;
-		nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
+		nodep = list_get_instance(list_first(&ffn_list), fat_node_t,
+		    ffn_link);
 		if (!fibril_mutex_trylock(&nodep->lock))
 			goto skip_cache;
@@ -298,8 +298,8 @@
 		return rc;
 
-	bs = block_bb_get(idxp->devmap_handle);
+	bs = block_bb_get(idxp->service_id);
 
 	/* Read the block that contains the dentry of interest. */
-	rc = _fat_block_get(&b, bs, idxp->devmap_handle, idxp->pfc, NULL,
+	rc = _fat_block_get(&b, bs, idxp->service_id, idxp->pfc, NULL,
 	    (idxp->pdi * sizeof(fat_dentry_t)) / BPS(bs), BLOCK_FLAGS_NONE);
 	if (rc != EOK) {
@@ -322,5 +322,5 @@
 		 */
 		uint16_t clusters;
-		rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle,
+		rc = fat_clusters_get(&clusters, bs, idxp->service_id,
 		    uint16_t_le2host(d->firstc));
 		if (rc != EOK) {
@@ -356,7 +356,7 @@
  */
 
-int fat_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
-{
-	return fat_node_get(rfn, devmap_handle, 0);
+int fat_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	return fat_node_get(rfn, service_id, 0);
 }
 
@@ -369,13 +369,13 @@
 	unsigned blocks;
 	fat_dentry_t *d;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	block_t *b;
 	int rc;
 
 	fibril_mutex_lock(&parentp->idx->lock);
-	devmap_handle = parentp->idx->devmap_handle;
+	service_id = parentp->idx->service_id;
 	fibril_mutex_unlock(&parentp->idx->lock);
 
-	bs = block_bb_get(devmap_handle);
+	bs = block_bb_get(service_id);
 	blocks = parentp->size / BPS(bs);
 	for (i = 0; i < blocks; i++) {
@@ -402,5 +402,5 @@
 				/* hit */
 				fat_node_t *nodep;
-				fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle,
+				fat_idx_t *idx = fat_idx_get_by_pos(service_id,
 				    parentp->firstc, i * DPS(bs) + j);
 				if (!idx) {
@@ -435,5 +435,5 @@
 
 /** Instantiate a FAT in-core node. */
-int fat_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
+int fat_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
 {
 	fat_node_t *nodep;
@@ -441,5 +441,5 @@
 	int rc;
 
-	idxp = fat_idx_get_by_index(devmap_handle, index);
+	idxp = fat_idx_get_by_index(service_id, index);
 	if (!idxp) {
 		*rfn = NULL;
@@ -472,5 +472,5 @@
 		if (nodep->idx) {
 			fibril_mutex_lock(&ffn_mutex);
-			list_append(&nodep->ffn_link, &ffn_head);
+			list_append(&nodep->ffn_link, &ffn_list);
 			fibril_mutex_unlock(&ffn_mutex);
 		} else {
@@ -492,5 +492,5 @@
 }
 
-int fat_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
+int fat_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
 {
 	fat_idx_t *idxp;
@@ -500,14 +500,14 @@
 	int rc;
 
-	bs = block_bb_get(devmap_handle);
+	bs = block_bb_get(service_id);
 	if (flags & L_DIRECTORY) {
 		/* allocate a cluster */
-		rc = fat_alloc_clusters(bs, devmap_handle, 1, &mcl, &lcl);
+		rc = fat_alloc_clusters(bs, service_id, 1, &mcl, &lcl);
 		if (rc != EOK)
 			return rc;
 		/* populate the new cluster with unused dentries */
-		rc = fat_zero_cluster(bs, devmap_handle, mcl);
+		rc = fat_zero_cluster(bs, service_id, mcl);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			return rc;
 		}
@@ -516,10 +516,10 @@
 	rc = fat_node_get_new(&nodep);
 	if (rc != EOK) {
-		(void) fat_free_clusters(bs, devmap_handle, mcl);
-		return rc;
-	}
-	rc = fat_idx_get_new(&idxp, devmap_handle);
+		(void) fat_free_clusters(bs, service_id, mcl);
+		return rc;
+	}
+	rc = fat_idx_get_new(&idxp, service_id);
 	if (rc != EOK) {
-		(void) fat_free_clusters(bs, devmap_handle, mcl);	
+		(void) fat_free_clusters(bs, service_id, mcl);	
 		(void) fat_node_put(FS_NODE(nodep));
 		return rc;
@@ -570,9 +570,9 @@
 	assert(!has_children);
 
-	bs = block_bb_get(nodep->idx->devmap_handle);
+	bs = block_bb_get(nodep->idx->service_id);
 	if (nodep->firstc != FAT_CLST_RES0) {
 		assert(nodep->size);
 		/* Free all clusters allocated to the node. */
-		rc = fat_free_clusters(bs, nodep->idx->devmap_handle,
+		rc = fat_free_clusters(bs, nodep->idx->service_id,
 		    nodep->firstc);
 	}
@@ -620,5 +620,5 @@
 	
 	fibril_mutex_lock(&parentp->idx->lock);
-	bs = block_bb_get(parentp->idx->devmap_handle);
+	bs = block_bb_get(parentp->idx->service_id);
 
 	blocks = parentp->size / BPS(bs);
@@ -659,12 +659,12 @@
 		return ENOSPC;
 	}
-	rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl);
+	rc = fat_alloc_clusters(bs, parentp->idx->service_id, 1, &mcl, &lcl);
 	if (rc != EOK) {
 		fibril_mutex_unlock(&parentp->idx->lock);
 		return rc;
 	}
-	rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl);
+	rc = fat_zero_cluster(bs, parentp->idx->service_id, mcl);
 	if (rc != EOK) {
-		(void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
+		(void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
 		fibril_mutex_unlock(&parentp->idx->lock);
 		return rc;
@@ -672,5 +672,5 @@
 	rc = fat_append_clusters(bs, parentp, mcl, lcl);
 	if (rc != EOK) {
-		(void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
+		(void) fat_free_clusters(bs, parentp->idx->service_id, mcl);
 		fibril_mutex_unlock(&parentp->idx->lock);
 		return rc;
@@ -722,6 +722,6 @@
 		    (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
 			memset(d, 0, sizeof(fat_dentry_t));
-			str_cpy((char *) d->name, 8, FAT_NAME_DOT);
-			str_cpy((char *) d->ext, 3, FAT_EXT_PAD);
+			memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
+			memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
 			d->attr = FAT_ATTR_SUBDIR;
 			d->firstc = host2uint16_t_le(childp->firstc);
@@ -732,6 +732,6 @@
 		    (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
 			memset(d, 0, sizeof(fat_dentry_t));
-			str_cpy((char *) d->name, 8, FAT_NAME_DOT_DOT);
-			str_cpy((char *) d->ext, 3, FAT_EXT_PAD);
+			memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
+			memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
 			d->attr = FAT_ATTR_SUBDIR;
 			d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
@@ -789,7 +789,7 @@
 	assert(childp->lnkcnt == 1);
 	fibril_mutex_lock(&childp->idx->lock);
-	bs = block_bb_get(childp->idx->devmap_handle);
-
-	rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc,
+	bs = block_bb_get(childp->idx->service_id);
+
+	rc = _fat_block_get(&b, bs, childp->idx->service_id, childp->idx->pfc,
 	    NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
 	    BLOCK_FLAGS_NONE);
@@ -841,5 +841,5 @@
 	
 	fibril_mutex_lock(&nodep->idx->lock);
-	bs = block_bb_get(nodep->idx->devmap_handle);
+	bs = block_bb_get(nodep->idx->service_id);
 
 	blocks = nodep->size / BPS(bs);
@@ -900,9 +900,4 @@
 }
 
-char fat_plb_get_char(unsigned pos)
-{
-	return fat_reg.plb_ro[pos % PLB_SIZE];
-}
-
 bool fat_is_directory(fs_node_t *fn)
 {
@@ -915,5 +910,5 @@
 }
 
-devmap_handle_t fat_device_get(fs_node_t *node)
+service_id_t fat_device_get(fs_node_t *node)
 {
 	return 0;
@@ -935,5 +930,4 @@
 	.size_get = fat_size_get,
 	.lnkcnt_get = fat_lnkcnt_get,
-	.plb_get_char = fat_plb_get_char,
 	.is_directory = fat_is_directory,
 	.is_file = fat_is_file,
@@ -942,22 +936,15 @@
 
 /*
- * VFS operations.
+ * FAT VFS_OUT operations.
  */
 
-void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+static int
+fat_mounted(service_id_t service_id, const char *opts, fs_index_t *index,
+    aoff64_t *size, unsigned *linkcnt)
+{
 	enum cache_mode cmode;
 	fat_bs_t *bs;
-	
-	/* Accept the mount options */
-	char *opts;
-	int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
+	int rc;
+	
 	/* Check for option enabling write through. */
 	if (str_cmp(opts, "wtcache") == 0)
@@ -966,53 +953,44 @@
 		cmode = CACHE_MODE_WB;
 
-	free(opts);
-
 	/* initialize libblock */
-	rc = block_init(devmap_handle, BS_SIZE);
+	rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE);
+	if (rc != EOK)
+		return rc;
+
+	/* prepare the boot block */
+	rc = block_bb_read(service_id, BS_BLOCK);
 	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	/* prepare the boot block */
-	rc = block_bb_read(devmap_handle, BS_BLOCK);
+		block_fini(service_id);
+		return rc;
+	}
+
+	/* get the buffer with the boot sector */
+	bs = block_bb_get(service_id);
+	
+	if (BPS(bs) != BS_SIZE) {
+		block_fini(service_id);
+		return ENOTSUP;
+	}
+
+	/* Initialize the block cache */
+	rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
 	if (rc != EOK) {
-		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	/* get the buffer with the boot sector */
-	bs = block_bb_get(devmap_handle);
-	
-	if (BPS(bs) != BS_SIZE) {
-		block_fini(devmap_handle);
-		async_answer_0(rid, ENOTSUP);
-		return;
-	}
-
-	/* Initialize the block cache */
-	rc = block_cache_init(devmap_handle, BPS(bs), 0 /* XXX */, cmode);
+		block_fini(service_id);
+		return rc;
+	}
+
+	/* Do some simple sanity checks on the file system. */
+	rc = fat_sanity_check(bs, service_id);
 	if (rc != EOK) {
-		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	/* Do some simple sanity checks on the file system. */
-	rc = fat_sanity_check(bs, devmap_handle);
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
+	}
+
+	rc = fat_idx_init_by_service_id(service_id);
 	if (rc != EOK) {
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
-	}
-
-	rc = fat_idx_init_by_devmap_handle(devmap_handle);
-	if (rc != EOK) {
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
 	}
 
@@ -1020,9 +998,8 @@
 	fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
 	if (!rfn) {
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		fat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
 	}
 	fs_node_initialize(rfn);
@@ -1030,21 +1007,19 @@
 	if (!rootp) {
 		free(rfn);
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		fat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
 	}
 	fat_node_initialize(rootp);
 
-	fat_idx_t *ridxp = fat_idx_get_by_pos(devmap_handle, FAT_CLST_ROOTPAR, 0);
+	fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0);
 	if (!ridxp) {
 		free(rfn);
 		free(rootp);
-		(void) block_cache_fini(devmap_handle);
-		block_fini(devmap_handle);
-		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		(void) block_cache_fini(service_id);
+		block_fini(service_id);
+		fat_idx_fini_by_service_id(service_id);
+		return ENOMEM;
 	}
 	assert(ridxp->index == 0);
@@ -1063,24 +1038,20 @@
 	fibril_mutex_unlock(&ridxp->lock);
 
-	async_answer_3(rid, EOK, ridxp->index, rootp->size, rootp->lnkcnt);
-}
-
-void fat_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	*index = ridxp->index;
+	*size = rootp->size;
+	*linkcnt = rootp->lnkcnt;
+
+	return EOK;
+}
+
+static int fat_unmounted(service_id_t service_id)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
 	int rc;
 
-	rc = fat_root_get(&fn, devmap_handle);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	rc = fat_root_get(&fn, service_id);
+	if (rc != EOK)
+		return rc;
 	nodep = FAT_NODE(fn);
 
@@ -1091,6 +1062,5 @@
 	if (nodep->refcnt != 2) {
 		(void) fat_node_put(fn);
-		async_answer_0(rid, EBUSY);
-		return;
+		return EBUSY;
 	}
 	
@@ -1106,28 +1076,16 @@
 	 * stop using libblock for this instance.
 	 */
-	(void) fat_node_fini_by_devmap_handle(devmap_handle);
-	fat_idx_fini_by_devmap_handle(devmap_handle);
-	(void) block_cache_fini(devmap_handle);
-	block_fini(devmap_handle);
-
-	async_answer_0(rid, EOK);
-}
-
-void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&fat_libfs_ops, rid, request);
-}
-
-void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	(void) fat_node_fini_by_service_id(service_id);
+	fat_idx_fini_by_service_id(service_id);
+	(void) block_cache_fini(service_id);
+	block_fini(service_id);
+
+	return EOK;
+}
+
+static int
+fat_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1137,13 +1095,9 @@
 	int rc;
 
-	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1153,9 +1107,8 @@
 		fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
-	}
-
-	bs = block_bb_get(devmap_handle);
+		return EINVAL;
+	}
+
+	bs = block_bb_get(service_id);
 
 	if (nodep->type == FAT_FILE) {
@@ -1177,6 +1130,5 @@
 				fat_node_put(fn);
 				async_answer_0(callid, rc);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 			(void) async_data_read_finalize(callid,
@@ -1185,6 +1137,5 @@
 			if (rc != EOK) {
 				fat_node_put(fn);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 		}
@@ -1243,12 +1194,11 @@
 		rc = fat_node_put(fn);
 		async_answer_0(callid, rc != EOK ? rc : ENOENT);
-		async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
-		return;
+		*rbytes = 0;
+		return rc != EOK ? rc : ENOENT;
 
 err:
 		(void) fat_node_put(fn);
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 
 hit:
@@ -1258,17 +1208,16 @@
 
 	rc = fat_node_put(fn);
-	async_answer_1(rid, rc, (sysarg_t)bytes);
-}
-
-void fat_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	*rbytes = bytes;
+	return rc;
+}
+
+static int
+fat_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
 	fat_bs_t *bs;
-	size_t bytes, size;
+	size_t bytes;
 	block_t *b;
 	aoff64_t boundary;
@@ -1276,13 +1225,9 @@
 	int rc;
 	
-	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 	
@@ -1292,9 +1237,8 @@
 		(void) fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
-	}
-
-	bs = block_bb_get(devmap_handle);
+		return EINVAL;
+	}
+
+	bs = block_bb_get(service_id);
 
 	/*
@@ -1321,6 +1265,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		rc = fat_block_get(&b, bs, nodep, pos / BPS(bs), flags);
@@ -1328,6 +1271,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		(void) async_data_write_finalize(callid,
@@ -1337,6 +1279,5 @@
 		if (rc != EOK) {
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		if (pos + bytes > nodep->size) {
@@ -1344,8 +1285,8 @@
 			nodep->dirty = true;	/* need to sync node */
 		}
-		size = nodep->size;
+		*wbytes = bytes;
+		*nsize = nodep->size;
 		rc = fat_node_put(fn);
-		async_answer_2(rid, rc, bytes, nodep->size);
-		return;
+		return rc;
 	} else {
 		/*
@@ -1358,29 +1299,26 @@
 		nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
 		/* create an independent chain of nclsts clusters in all FATs */
-		rc = fat_alloc_clusters(bs, devmap_handle, nclsts, &mcl, &lcl);
+		rc = fat_alloc_clusters(bs, service_id, nclsts, &mcl, &lcl);
 		if (rc != EOK) {
 			/* could not allocate a chain of nclsts clusters */
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/* zero fill any gaps */
 		rc = fat_fill_gap(bs, nodep, mcl, pos);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
-		}
-		rc = _fat_block_get(&b, bs, devmap_handle, lcl, NULL,
+			return rc;
+		}
+		rc = _fat_block_get(&b, bs, service_id, lcl, NULL,
 		    (pos / BPS(bs)) % SPC(bs), flags);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		(void) async_data_write_finalize(callid,
@@ -1389,8 +1327,7 @@
 		rc = block_put(b);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/*
@@ -1400,23 +1337,19 @@
 		rc = fat_append_clusters(bs, nodep, mcl, lcl);
 		if (rc != EOK) {
-			(void) fat_free_clusters(bs, devmap_handle, mcl);
+			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
-		}
-		nodep->size = size = pos + bytes;
+			return rc;
+		}
+		*nsize = nodep->size = pos + bytes;
+		rc = fat_node_put(fn);
 		nodep->dirty = true;		/* need to sync node */
-		rc = fat_node_put(fn);
-		async_answer_2(rid, rc, bytes, size);
-		return;
-	}
-}
-
-void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t size =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+		*wbytes = bytes;
+		return rc;
+	}
+}
+
+static int
+fat_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1424,16 +1357,12 @@
 	int rc;
 
-	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
-	bs = block_bb_get(devmap_handle);
+	bs = block_bb_get(service_id);
 
 	if (nodep->size == size) {
@@ -1462,5 +1391,5 @@
 		} else {
 			fat_cluster_t lastc;
-			rc = fat_cluster_walk(bs, devmap_handle, nodep->firstc,
+			rc = fat_cluster_walk(bs, service_id, nodep->firstc,
 			    &lastc, NULL, (size - 1) / BPC(bs));
 			if (rc != EOK)
@@ -1476,30 +1405,23 @@
 out:
 	fat_node_put(fn);
-	async_answer_0(rid, rc);
-	return;
-}
-
-void fat_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, EOK);
-}
-
-void fat_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
+	return rc;
+}
+
+static int fat_close(service_id_t service_id, fs_index_t index)
+{
+	return EOK;
+}
+
+static int fat_destroy(service_id_t service_id, fs_index_t index)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
 	int rc;
 
-	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 
 	nodep = FAT_NODE(fn);
@@ -1511,32 +1433,15 @@
 
 	rc = fat_destroy_node(fn);
-	async_answer_0(rid, rc);
-}
-
-void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
+	return rc;
+}
+
+static int fat_sync(service_id_t service_id, fs_index_t index)
+{
 	fs_node_t *fn;
-	int rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	int rc = fat_node_get(&fn, service_id, index);
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	
 	fat_node_t *nodep = FAT_NODE(fn);
@@ -1546,6 +1451,17 @@
 	
 	fat_node_put(fn);
-	async_answer_0(rid, rc);
-}
+	return rc;
+}
+
+vfs_out_ops_t fat_ops = {
+	.mounted = fat_mounted,
+	.unmounted = fat_unmounted,
+	.read = fat_read,
+	.write = fat_write,
+	.truncate = fat_truncate,
+	.close = fat_close,
+	.destroy = fat_destroy,
+	.sync = fat_sync,
+};
 
 /**
Index: uspace/srv/fs/locfs/Makefile
===================================================================
--- uspace/srv/fs/locfs/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/locfs/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBFS_PREFIX)/libfs.a
+EXTRA_CFLAGS += -I$(LIBFS_PREFIX)
+BINARY = locfs
+STATIC_NEEDED = y
+
+SOURCES = \
+	locfs.c \
+	locfs_ops.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/locfs/locfs.c
===================================================================
--- uspace/srv/fs/locfs/locfs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/locfs/locfs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+/**
+ * @file locfs.c
+ * @brief Location-service file system.
+ *
+ * Every service registered with location service is represented as a file in this
+ * file system.
+ */
+
+#include <stdio.h>
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <task.h>
+#include <libfs.h>
+#include "locfs.h"
+#include "locfs_ops.h"
+
+#define NAME  "locfs"
+
+static vfs_info_t locfs_vfs_info = {
+	.name = NAME,
+	.concurrent_read_write = false,
+	.write_retains_size = false,
+};
+
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS Device Filesystem\n", NAME);
+	
+	if (!locfs_init()) {
+		printf("%s: failed to initialize locfs\n", NAME);
+		return -1;
+	}
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
+		printf("%s: Unable to connect to VFS\n", NAME);
+		return -1;
+	}
+	
+	int rc = fs_register(vfs_sess, &locfs_vfs_info, &locfs_ops,
+	    &locfs_libfs_ops);
+	if (rc != EOK) {
+		printf("%s: Failed to register file system (%d)\n", NAME, rc);
+		return rc;
+	}
+	
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
+	async_manager();
+	
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/locfs/locfs.h
===================================================================
--- uspace/srv/fs/locfs/locfs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/locfs/locfs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+/** @addtogroup fs
+ * @{
+ */ 
+
+#ifndef LOCFS_LOCFS_H_
+#define LOCFS_LOCFS_H_
+
+#include <libfs.h>
+
+extern vfs_out_ops_t locfs_ops;
+extern libfs_ops_t locfs_libfs_ops;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/locfs/locfs_ops.c
===================================================================
--- uspace/srv/fs/locfs/locfs_ops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/locfs/locfs_ops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+/**
+ * @file locfs_ops.c
+ * @brief Implementation of VFS operations for the locfs file system server.
+ */
+
+#include <macros.h>
+#include <bool.h>
+#include <errno.h>
+#include <malloc.h>
+#include <str.h>
+#include <libfs.h>
+#include <fibril_synch.h>
+#include <adt/hash_table.h>
+#include <ipc/loc.h>
+#include <sys/stat.h>
+#include <libfs.h>
+#include <assert.h>
+#include "locfs.h"
+#include "locfs_ops.h"
+
+typedef struct {
+	loc_object_type_t type;
+	service_id_t service_id;
+} locfs_node_t;
+
+/** Opened services structure */
+typedef struct {
+	service_id_t service_id;
+	async_sess_t *sess;       /**< If NULL, the structure is incomplete. */
+	size_t refcount;
+	link_t link;
+	fibril_condvar_t cv;      /**< Broadcast when completed. */
+} service_t;
+
+/** Hash table of opened services */
+static hash_table_t services;
+
+/** Hash table mutex */
+static FIBRIL_MUTEX_INITIALIZE(services_mutex);
+
+#define SERVICES_KEYS        1
+#define SERVICES_KEY_HANDLE  0
+#define SERVICES_BUCKETS     256
+
+/* Implementation of hash table interface for the nodes hash table. */
+static hash_index_t services_hash(unsigned long key[])
+{
+	return key[SERVICES_KEY_HANDLE] % SERVICES_BUCKETS;
+}
+
+static int services_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	service_t *dev = hash_table_get_instance(item, service_t, link);
+	return (dev->service_id == (service_id_t) key[SERVICES_KEY_HANDLE]);
+}
+
+static void services_remove_callback(link_t *item)
+{
+	free(hash_table_get_instance(item, service_t, link));
+}
+
+static hash_table_operations_t services_ops = {
+	.hash = services_hash,
+	.compare = services_compare,
+	.remove_callback = services_remove_callback
+};
+
+static int locfs_node_get_internal(fs_node_t **rfn, loc_object_type_t type,
+    service_id_t service_id)
+{
+	locfs_node_t *node = (locfs_node_t *) malloc(sizeof(locfs_node_t));
+	if (node == NULL) {
+		*rfn = NULL;
+		return ENOMEM;
+	}
+	
+	*rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
+	if (*rfn == NULL) {
+		free(node);
+		*rfn = NULL;
+		return ENOMEM;
+	}
+	
+	fs_node_initialize(*rfn);
+	node->type = type;
+	node->service_id = service_id;
+	
+	(*rfn)->data = node;
+	return EOK;
+}
+
+static int locfs_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	return locfs_node_get_internal(rfn, LOC_OBJECT_NONE, 0);
+}
+
+static int locfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+	locfs_node_t *node = (locfs_node_t *) pfn->data;
+	int ret;
+	
+	if (node->service_id == 0) {
+		/* Root directory */
+		
+		loc_sdesc_t *nspaces;
+		size_t count = loc_get_namespaces(&nspaces);
+		
+		if (count > 0) {
+			size_t pos;
+			for (pos = 0; pos < count; pos++) {
+				/* Ignore root namespace */
+				if (str_cmp(nspaces[pos].name, "") == 0)
+					continue;
+				
+				if (str_cmp(nspaces[pos].name, component) == 0) {
+					ret = locfs_node_get_internal(rfn, LOC_OBJECT_NAMESPACE, nspaces[pos].id);
+					free(nspaces);
+					return ret;
+				}
+			}
+			
+			free(nspaces);
+		}
+		
+		/* Search root namespace */
+		service_id_t namespace;
+		loc_sdesc_t *svcs;
+		if (loc_namespace_get_id("", &namespace, 0) == EOK) {
+			count = loc_get_services(namespace, &svcs);
+			
+			if (count > 0) {
+				size_t pos;
+				for (pos = 0; pos < count; pos++) {
+					if (str_cmp(svcs[pos].name, component) == 0) {
+						ret = locfs_node_get_internal(rfn, LOC_OBJECT_SERVICE, svcs[pos].id);
+						free(svcs);
+						return ret;
+					}
+				}
+				
+				free(svcs);
+			}
+		}
+		
+		*rfn = NULL;
+		return EOK;
+	}
+	
+	if (node->type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		
+		loc_sdesc_t *svcs;
+		size_t count = loc_get_services(node->service_id, &svcs);
+		if (count > 0) {
+			size_t pos;
+			for (pos = 0; pos < count; pos++) {
+				if (str_cmp(svcs[pos].name, component) == 0) {
+					ret = locfs_node_get_internal(rfn, LOC_OBJECT_SERVICE, svcs[pos].id);
+					free(svcs);
+					return ret;
+				}
+			}
+			
+			free(svcs);
+		}
+		
+		*rfn = NULL;
+		return EOK;
+	}
+	
+	*rfn = NULL;
+	return EOK;
+}
+
+static int locfs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
+{
+	return locfs_node_get_internal(rfn, loc_id_probe(index), index);
+}
+
+static int locfs_node_open(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	if (node->service_id == 0) {
+		/* Root directory */
+		return EOK;
+	}
+	
+	loc_object_type_t type = loc_id_probe(node->service_id);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		return EOK;
+	}
+	
+	if (type == LOC_OBJECT_SERVICE) {
+		/* Device node */
+		
+		unsigned long key[] = {
+			[SERVICES_KEY_HANDLE] = (unsigned long) node->service_id
+		};
+		link_t *lnk;
+		
+		fibril_mutex_lock(&services_mutex);
+restart:
+		lnk = hash_table_find(&services, key);
+		if (lnk == NULL) {
+			service_t *dev = (service_t *) malloc(sizeof(service_t));
+			if (dev == NULL) {
+				fibril_mutex_unlock(&services_mutex);
+				return ENOMEM;
+			}
+			
+			dev->service_id = node->service_id;
+			
+			/* Mark as incomplete */
+			dev->sess = NULL;
+			dev->refcount = 1;
+			fibril_condvar_initialize(&dev->cv);
+			
+			/*
+			 * Insert the incomplete device structure so that other
+			 * fibrils will not race with us when we drop the mutex
+			 * below.
+			 */
+			hash_table_insert(&services, key, &dev->link);
+			
+			/*
+			 * Drop the mutex to allow recursive locfs requests.
+			 */
+			fibril_mutex_unlock(&services_mutex);
+			
+			async_sess_t *sess = loc_service_connect(
+			    EXCHANGE_SERIALIZE, node->service_id, 0);
+			
+			fibril_mutex_lock(&services_mutex);
+			
+			/*
+			 * Notify possible waiters about this device structure
+			 * being completed (or destroyed).
+			 */
+			fibril_condvar_broadcast(&dev->cv);
+			
+			if (!sess) {
+				/*
+				 * Connecting failed, need to remove the
+				 * entry and free the device structure.
+				 */
+				hash_table_remove(&services, key, SERVICES_KEYS);
+				fibril_mutex_unlock(&services_mutex);
+				
+				return ENOENT;
+			}
+			
+			/* Set the correct session. */
+			dev->sess = sess;
+		} else {
+			service_t *dev = hash_table_get_instance(lnk, service_t, link);
+			
+			if (!dev->sess) {
+				/*
+				 * Wait until the device structure is completed
+				 * and start from the beginning as the device
+				 * structure might have entirely disappeared
+				 * while we were not holding the mutex in
+				 * fibril_condvar_wait().
+				 */
+				fibril_condvar_wait(&dev->cv, &services_mutex);
+				goto restart;
+			}
+
+			dev->refcount++;
+		}
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		return EOK;
+	}
+	
+	return ENOENT;
+}
+
+static int locfs_node_put(fs_node_t *fn)
+{
+	free(fn->data);
+	free(fn);
+	return EOK;
+}
+
+static int locfs_create_node(fs_node_t **rfn, service_id_t service_id, int lflag)
+{
+	assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
+	
+	*rfn = NULL;
+	return ENOTSUP;
+}
+
+static int locfs_destroy_node(fs_node_t *fn)
+{
+	return ENOTSUP;
+}
+
+static int locfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+	return ENOTSUP;
+}
+
+static int locfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+	return ENOTSUP;
+}
+
+static int locfs_has_children(bool *has_children, fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	if (node->service_id == 0) {
+		size_t count = loc_count_namespaces();
+		if (count > 0) {
+			*has_children = true;
+			return EOK;
+		}
+		
+		/* Root namespace */
+		service_id_t namespace;
+		if (loc_namespace_get_id("", &namespace, 0) == EOK) {
+			count = loc_count_services(namespace);
+			if (count > 0) {
+				*has_children = true;
+				return EOK;
+			}
+		}
+		
+		*has_children = false;
+		return EOK;
+	}
+	
+	if (node->type == LOC_OBJECT_NAMESPACE) {
+		size_t count = loc_count_services(node->service_id);
+		if (count > 0) {
+			*has_children = true;
+			return EOK;
+		}
+		
+		*has_children = false;
+		return EOK;
+	}
+	
+	*has_children = false;
+	return EOK;
+}
+
+static fs_index_t locfs_index_get(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	return node->service_id;
+}
+
+static aoff64_t locfs_size_get(fs_node_t *fn)
+{
+	return 0;
+}
+
+static unsigned int locfs_lnkcnt_get(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	if (node->service_id == 0)
+		return 0;
+	
+	return 1;
+}
+
+static bool locfs_is_directory(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	return ((node->type == LOC_OBJECT_NONE) || (node->type == LOC_OBJECT_NAMESPACE));
+}
+
+static bool locfs_is_file(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	return (node->type == LOC_OBJECT_SERVICE);
+}
+
+static service_id_t locfs_device_get(fs_node_t *fn)
+{
+	locfs_node_t *node = (locfs_node_t *) fn->data;
+	
+	if (node->type == LOC_OBJECT_SERVICE)
+		return node->service_id;
+	
+	return 0;
+}
+
+/** libfs operations */
+libfs_ops_t locfs_libfs_ops = {
+	.root_get = locfs_root_get,
+	.match = locfs_match,
+	.node_get = locfs_node_get,
+	.node_open = locfs_node_open,
+	.node_put = locfs_node_put,
+	.create = locfs_create_node,
+	.destroy = locfs_destroy_node,
+	.link = locfs_link_node,
+	.unlink = locfs_unlink_node,
+	.has_children = locfs_has_children,
+	.index_get = locfs_index_get,
+	.size_get = locfs_size_get,
+	.lnkcnt_get = locfs_lnkcnt_get,
+	.is_directory = locfs_is_directory,
+	.is_file = locfs_is_file,
+	.device_get = locfs_device_get
+};
+
+bool locfs_init(void)
+{
+	if (!hash_table_create(&services, SERVICES_BUCKETS,
+	    SERVICES_KEYS, &services_ops))
+		return false;
+	
+	return true;
+}
+
+static int locfs_mounted(service_id_t service_id, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	*index = 0;
+	*size = 0;
+	*lnkcnt = 0;
+	return EOK;
+}
+
+static int locfs_unmounted(service_id_t service_id)
+{
+	return ENOTSUP;
+}
+
+static int
+locfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
+	if (index == 0) {
+		ipc_callid_t callid;
+		size_t size;
+		if (!async_data_read_receive(&callid, &size)) {
+			async_answer_0(callid, EINVAL);
+			return EINVAL;
+		}
+		
+		loc_sdesc_t *desc;
+		size_t count = loc_get_namespaces(&desc);
+		
+		/* Get rid of root namespace */
+		size_t i;
+		for (i = 0; i < count; i++) {
+			if (str_cmp(desc[i].name, "") == 0) {
+				if (pos >= i)
+					pos++;
+				
+				break;
+			}
+		}
+		
+		if (pos < count) {
+			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+			free(desc);
+			*rbytes = 1;
+			return EOK;
+		}
+		
+		free(desc);
+		pos -= count;
+		
+		/* Search root namespace */
+		service_id_t namespace;
+		if (loc_namespace_get_id("", &namespace, 0) == EOK) {
+			count = loc_get_services(namespace, &desc);
+			
+			if (pos < count) {
+				async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+				free(desc);
+				*rbytes = 1;
+				return EOK;
+			}
+			
+			free(desc);
+		}
+		
+		async_answer_0(callid, ENOENT);
+		return ENOENT;
+	}
+	
+	loc_object_type_t type = loc_id_probe(index);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		ipc_callid_t callid;
+		size_t size;
+		if (!async_data_read_receive(&callid, &size)) {
+			async_answer_0(callid, EINVAL);
+			return EINVAL;
+		}
+		
+		loc_sdesc_t *desc;
+		size_t count = loc_get_services(index, &desc);
+		
+		if (pos < count) {
+			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
+			free(desc);
+			*rbytes = 1;
+			return EOK;
+		}
+		
+		free(desc);
+		async_answer_0(callid, ENOENT);
+		return ENOENT;
+	}
+	
+	if (type == LOC_OBJECT_SERVICE) {
+		/* Device node */
+		
+		unsigned long key[] = {
+			[SERVICES_KEY_HANDLE] = (unsigned long) index
+		};
+		
+		fibril_mutex_lock(&services_mutex);
+		link_t *lnk = hash_table_find(&services, key);
+		if (lnk == NULL) {
+			fibril_mutex_unlock(&services_mutex);
+			return ENOENT;
+		}
+		
+		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		assert(dev->sess);
+		
+		ipc_callid_t callid;
+		if (!async_data_read_receive(&callid, NULL)) {
+			fibril_mutex_unlock(&services_mutex);
+			async_answer_0(callid, EINVAL);
+			return EINVAL;
+		}
+		
+		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
+		ipc_call_t answer;
+		aid_t msg = async_send_4(exch, VFS_OUT_READ, service_id,
+		    index, LOWER32(pos), UPPER32(pos), &answer);
+		
+		/* Forward the IPC_M_DATA_READ request to the driver */
+		async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		
+		async_exchange_end(exch);
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		/* Wait for reply from the driver. */
+		sysarg_t rc;
+		async_wait_for(msg, &rc);
+		
+		*rbytes = IPC_GET_ARG1(answer);
+		return rc;
+	}
+	
+	return ENOENT;
+}
+
+static int
+locfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	if (index == 0)
+		return ENOTSUP;
+	
+	loc_object_type_t type = loc_id_probe(index);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		return ENOTSUP;
+	}
+	
+	if (type == LOC_OBJECT_SERVICE) {
+		/* Device node */
+		unsigned long key[] = {
+			[SERVICES_KEY_HANDLE] = (unsigned long) index
+		};
+		
+		fibril_mutex_lock(&services_mutex);
+		link_t *lnk = hash_table_find(&services, key);
+		if (lnk == NULL) {
+			fibril_mutex_unlock(&services_mutex);
+			return ENOENT;
+		}
+		
+		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		assert(dev->sess);
+		
+		ipc_callid_t callid;
+		if (!async_data_write_receive(&callid, NULL)) {
+			fibril_mutex_unlock(&services_mutex);
+			async_answer_0(callid, EINVAL);
+			return EINVAL;
+		}
+		
+		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
+		ipc_call_t answer;
+		aid_t msg = async_send_4(exch, VFS_OUT_WRITE, service_id,
+		    index, LOWER32(pos), UPPER32(pos), &answer);
+		
+		/* Forward the IPC_M_DATA_WRITE request to the driver */
+		async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		
+		async_exchange_end(exch);
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		/* Wait for reply from the driver. */
+		sysarg_t rc;
+		async_wait_for(msg, &rc);
+		
+		*wbytes = IPC_GET_ARG1(answer);
+		*nsize = 0;
+		return rc;
+	}
+	
+	return ENOENT;
+}
+
+static int
+locfs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
+{
+	return ENOTSUP;
+}
+
+static int locfs_close(service_id_t service_id, fs_index_t index)
+{
+	if (index == 0)
+		return EOK;
+	
+	loc_object_type_t type = loc_id_probe(index);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		return EOK;
+	}
+	
+	if (type == LOC_OBJECT_SERVICE) {
+		unsigned long key[] = {
+			[SERVICES_KEY_HANDLE] = (unsigned long) index
+		};
+		
+		fibril_mutex_lock(&services_mutex);
+		link_t *lnk = hash_table_find(&services, key);
+		if (lnk == NULL) {
+			fibril_mutex_unlock(&services_mutex);
+			return ENOENT;
+		}
+		
+		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		assert(dev->sess);
+		dev->refcount--;
+		
+		if (dev->refcount == 0) {
+			async_hangup(dev->sess);
+			hash_table_remove(&services, key, SERVICES_KEYS);
+		}
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		return EOK;
+	}
+	
+	return ENOENT;
+}
+
+static int locfs_sync(service_id_t service_id, fs_index_t index)
+{
+	if (index == 0)
+		return EOK;
+	
+	loc_object_type_t type = loc_id_probe(index);
+	
+	if (type == LOC_OBJECT_NAMESPACE) {
+		/* Namespace directory */
+		return EOK;
+	}
+	
+	if (type == LOC_OBJECT_SERVICE) {
+		unsigned long key[] = {
+			[SERVICES_KEY_HANDLE] = (unsigned long) index
+		};
+		
+		fibril_mutex_lock(&services_mutex);
+		link_t *lnk = hash_table_find(&services, key);
+		if (lnk == NULL) {
+			fibril_mutex_unlock(&services_mutex);
+			return ENOENT;
+		}
+		
+		service_t *dev = hash_table_get_instance(lnk, service_t, link);
+		assert(dev->sess);
+		
+		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
+		ipc_call_t answer;
+		aid_t msg = async_send_2(exch, VFS_OUT_SYNC, service_id,
+		    index, &answer);
+		
+		async_exchange_end(exch);
+		
+		fibril_mutex_unlock(&services_mutex);
+		
+		/* Wait for reply from the driver */
+		sysarg_t rc;
+		async_wait_for(msg, &rc);
+		
+		return rc;
+	}
+	
+	return  ENOENT;
+}
+
+static int locfs_destroy(service_id_t service_id, fs_index_t index)
+{
+	return ENOTSUP;
+}
+
+vfs_out_ops_t locfs_ops = {
+	.mounted = locfs_mounted,
+	.unmounted = locfs_unmounted,
+	.read = locfs_read,
+	.write = locfs_write,
+	.truncate = locfs_truncate,
+	.close = locfs_close,
+	.destroy = locfs_destroy,
+	.sync = locfs_sync,
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/locfs/locfs_ops.h
===================================================================
--- uspace/srv/fs/locfs/locfs_ops.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/fs/locfs/locfs_ops.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2009 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.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#ifndef LOCFS_LOCFS_OPS_H_
+#define LOCFS_LOCFS_OPS_H_
+
+#include <bool.h>
+
+extern bool locfs_init(void);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/tmpfs/Makefile
===================================================================
--- uspace/srv/fs/tmpfs/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/tmpfs/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,4 +32,5 @@
 EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX)
 BINARY = tmpfs
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,5 +30,5 @@
 /** @addtogroup fs
  * @{
- */ 
+ */
 
 /**
@@ -43,5 +43,5 @@
 #include "tmpfs.h"
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <errno.h>
@@ -61,117 +61,32 @@
 };
 
-fs_reg_t tmpfs_reg;
-
-/**
- * This connection fibril processes VFS requests from VFS.
- *
- * In order to support simultaneous VFS requests, our design is as follows.
- * The connection fibril accepts VFS requests from VFS. If there is only one
- * instance of the fibril, VFS will need to serialize all VFS requests it sends
- * to FAT. To overcome this bottleneck, VFS can send TMPFS the
- * IPC_M_CONNECT_ME_TO call. In that case, a new connection fibril will be
- * created, which in turn will accept the call. Thus, a new phone will be
- * opened for VFS.
- *
- * There are few issues with this arrangement. First, VFS can run out of
- * available phones. In that case, VFS can close some other phones or use one
- * phone for more serialized requests. Similarily, TMPFS can refuse to duplicate
- * the connection. VFS should then just make use of already existing phones and
- * route its requests through them. To avoid paying the fibril creation price 
- * upon each request, TMPFS might want to keep the connections open after the
- * request has been completed.
- */
-static void tmpfs_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (iid) {
-		/*
-		 * This only happens for connections opened by
-		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
-		 * created by IPC_M_CONNECT_TO_ME.
-		 */
-		async_answer_0(iid, EOK);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	while (1) {
-		ipc_callid_t callid;
-		ipc_call_t call;
-	
-		callid = async_get_call(&call);
-		switch  (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			return;
-		case VFS_OUT_MOUNTED:
-			tmpfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			tmpfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			tmpfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			tmpfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			tmpfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			tmpfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			tmpfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			tmpfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			tmpfs_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			tmpfs_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			tmpfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			tmpfs_stat(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			tmpfs_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
 	printf(NAME ": HelenOS TMPFS file system server\n");
-
+	
 	if (!tmpfs_init()) {
 		printf(NAME ": failed to initialize TMPFS\n");
 		return -1;
 	}
-
-	int vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
-	if (vfs_phone < EOK) {
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
 		printf(NAME ": Unable to connect to VFS\n");
 		return -1;
 	}
-
-	int rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info,
-	    tmpfs_connection);
+	
+	int rc = fs_register(vfs_sess, &tmpfs_vfs_info, &tmpfs_ops,
+	    &tmpfs_libfs_ops);
 	if (rc != EOK) {
 		printf(NAME ": Failed to register file system (%d)\n", rc);
 		return rc;
 	}
-
+	
 	printf(NAME ": Accepting connections\n");
 	task_retval(0);
 	async_manager();
-	/* not reached */
+	
+	/* Not reached */
 	return 0;
 }
@@ -179,3 +94,3 @@
 /**
  * @}
- */ 
+ */
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -61,5 +61,5 @@
 	fs_node_t *bp;		/**< Back pointer to the FS node. */
 	fs_index_t index;	/**< TMPFS node index. */
-	devmap_handle_t devmap_handle;/**< Device handle. */
+	service_id_t service_id;/**< Service ID of block device. */
 	link_t nh_link;		/**< Nodes hash table link. */
 	tmpfs_dentry_type_t type;
@@ -67,28 +67,12 @@
 	size_t size;		/**< File size if type is TMPFS_FILE. */
 	void *data;		/**< File content's if type is TMPFS_FILE. */
-	link_t cs_head;		/**< Head of child's siblings list. */
+	list_t cs_list;		/**< Child's siblings list. */
 } tmpfs_node_t;
 
-extern fs_reg_t tmpfs_reg;
-
+extern vfs_out_ops_t tmpfs_ops;
 extern libfs_ops_t tmpfs_libfs_ops;
 
 extern bool tmpfs_init(void);
-
-extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_mount(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_stat(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
-
-extern bool tmpfs_restore(devmap_handle_t);
+extern bool tmpfs_restore(service_id_t);
 
 #endif
Index: uspace/srv/fs/tmpfs/tmpfs_dump.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -55,5 +55,5 @@
 
 static bool
-tmpfs_restore_recursion(devmap_handle_t dev, size_t *bufpos, size_t *buflen,
+tmpfs_restore_recursion(service_id_t dsid, size_t *bufpos, size_t *buflen,
     aoff64_t *pos, fs_node_t *pfn)
 {
@@ -68,5 +68,5 @@
 		uint32_t size;
 		
-		if (block_seqread(dev, bufpos, buflen, pos, &entry,
+		if (block_seqread(dsid, bufpos, buflen, pos, &entry,
 		    sizeof(entry)) != EOK)
 			return false;
@@ -82,5 +82,5 @@
 				return false;
 			
-			rc = ops->create(&fn, dev, L_FILE);
+			rc = ops->create(&fn, dsid, L_FILE);
 			if (rc != EOK || fn == NULL) {
 				free(fname);
@@ -88,5 +88,5 @@
 			}
 			
-			if (block_seqread(dev, bufpos, buflen, pos, fname,
+			if (block_seqread(dsid, bufpos, buflen, pos, fname,
 			    entry.len) != EOK) {
 				(void) ops->destroy(fn);
@@ -104,5 +104,5 @@
 			free(fname);
 			
-			if (block_seqread(dev, bufpos, buflen, pos, &size,
+			if (block_seqread(dsid, bufpos, buflen, pos, &size,
 			    sizeof(size)) != EOK)
 				return false;
@@ -116,5 +116,5 @@
 			
 			nodep->size = size;
-			if (block_seqread(dev, bufpos, buflen, pos, nodep->data,
+			if (block_seqread(dsid, bufpos, buflen, pos, nodep->data,
 			    size) != EOK)
 				return false;
@@ -126,5 +126,5 @@
 				return false;
 			
-			rc = ops->create(&fn, dev, L_DIRECTORY);
+			rc = ops->create(&fn, dsid, L_DIRECTORY);
 			if (rc != EOK || fn == NULL) {
 				free(fname);
@@ -132,5 +132,5 @@
 			}
 			
-			if (block_seqread(dev, bufpos, buflen, pos, fname,
+			if (block_seqread(dsid, bufpos, buflen, pos, fname,
 			    entry.len) != EOK) {
 				(void) ops->destroy(fn);
@@ -148,5 +148,5 @@
 			free(fname);
 			
-			if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos,
+			if (!tmpfs_restore_recursion(dsid, bufpos, buflen, pos,
 			    fn))
 				return false;
@@ -161,5 +161,5 @@
 }
 
-bool tmpfs_restore(devmap_handle_t dev)
+bool tmpfs_restore(service_id_t dsid)
 {
 	libfs_ops_t *ops = &tmpfs_libfs_ops;
@@ -167,5 +167,5 @@
 	int rc;
 
-	rc = block_init(dev, TMPFS_COMM_SIZE);
+	rc = block_init(EXCHANGE_SERIALIZE, dsid, TMPFS_COMM_SIZE);
 	if (rc != EOK)
 		return false; 
@@ -176,5 +176,5 @@
 	
 	char tag[6];
-	if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5) != EOK)
+	if (block_seqread(dsid, &bufpos, &buflen, &pos, tag, 5) != EOK)
 		goto error;
 	
@@ -183,16 +183,16 @@
 		goto error;
 	
-	rc = ops->root_get(&fn, dev);
+	rc = ops->root_get(&fn, dsid);
 	if (rc != EOK)
 		goto error;
 
-	if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, fn))
-		goto error;
-		
-	block_fini(dev);
+	if (!tmpfs_restore_recursion(dsid, &bufpos, &buflen, &pos, fn))
+		goto error;
+		
+	block_fini(dsid);
 	return true;
 	
 error:
-	block_fini(dev);
+	block_fini(dsid);
 	return false;
 }
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -69,8 +69,8 @@
 /* Forward declarations of static functions. */
 static int tmpfs_match(fs_node_t **, fs_node_t *, const char *);
-static int tmpfs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
+static int tmpfs_node_get(fs_node_t **, service_id_t, fs_index_t);
 static int tmpfs_node_open(fs_node_t *);
 static int tmpfs_node_put(fs_node_t *);
-static int tmpfs_create_node(fs_node_t **, devmap_handle_t, int);
+static int tmpfs_create_node(fs_node_t **, service_id_t, int);
 static int tmpfs_destroy_node(fs_node_t *);
 static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *);
@@ -78,12 +78,12 @@
 
 /* Implementation of helper functions. */
-static int tmpfs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
-{
-	return tmpfs_node_get(rfn, devmap_handle, TMPFS_SOME_ROOT); 
+static int tmpfs_root_get(fs_node_t **rfn, service_id_t service_id)
+{
+	return tmpfs_node_get(rfn, service_id, TMPFS_SOME_ROOT); 
 }
 
 static int tmpfs_has_children(bool *has_children, fs_node_t *fn)
 {
-	*has_children = !list_empty(&TMPFS_NODE(fn)->cs_head);
+	*has_children = !list_empty(&TMPFS_NODE(fn)->cs_list);
 	return EOK;
 }
@@ -104,9 +104,4 @@
 }
 
-static char tmpfs_plb_get_char(unsigned pos)
-{
-	return tmpfs_reg.plb_ro[pos % PLB_SIZE];
-}
-
 static bool tmpfs_is_directory(fs_node_t *fn)
 {
@@ -119,5 +114,5 @@
 }
 
-static devmap_handle_t tmpfs_device_get(fs_node_t *fn)
+static service_id_t tmpfs_device_get(fs_node_t *fn)
 {
 	return 0;
@@ -139,5 +134,4 @@
 	.size_get = tmpfs_size_get,
 	.lnkcnt_get = tmpfs_lnkcnt_get,
-	.plb_get_char = tmpfs_plb_get_char,
 	.is_directory = tmpfs_is_directory,
 	.is_file = tmpfs_is_file,
@@ -164,7 +158,7 @@
 	switch (keys) {
 	case 1:
-		return (nodep->devmap_handle == key[NODES_KEY_DEV]);
+		return (nodep->service_id == key[NODES_KEY_DEV]);
 	case 2:	
-		return ((nodep->devmap_handle == key[NODES_KEY_DEV]) &&
+		return ((nodep->service_id == key[NODES_KEY_DEV]) &&
 		    (nodep->index == key[NODES_KEY_INDEX]));
 	default:
@@ -180,7 +174,7 @@
 	    nh_link);
 
-	while (!list_empty(&nodep->cs_head)) {
-		tmpfs_dentry_t *dentryp = list_get_instance(nodep->cs_head.next,
-		    tmpfs_dentry_t, link);
+	while (!list_empty(&nodep->cs_list)) {
+		tmpfs_dentry_t *dentryp = list_get_instance(
+		    list_first(&nodep->cs_list), tmpfs_dentry_t, link);
 
 		assert(nodep->type == TMPFS_DIRECTORY);
@@ -208,5 +202,5 @@
 	nodep->bp = NULL;
 	nodep->index = 0;
-	nodep->devmap_handle = 0;
+	nodep->service_id = 0;
 	nodep->type = TMPFS_NONE;
 	nodep->lnkcnt = 0;
@@ -214,5 +208,5 @@
 	nodep->data = NULL;
 	link_initialize(&nodep->nh_link);
-	list_initialize(&nodep->cs_head);
+	list_initialize(&nodep->cs_list);
 }
 
@@ -232,10 +226,10 @@
 }
 
-static bool tmpfs_instance_init(devmap_handle_t devmap_handle)
+static bool tmpfs_instance_init(service_id_t service_id)
 {
 	fs_node_t *rfn;
 	int rc;
 	
-	rc = tmpfs_create_node(&rfn, devmap_handle, L_DIRECTORY);
+	rc = tmpfs_create_node(&rfn, service_id, L_DIRECTORY);
 	if (rc != EOK || !rfn)
 		return false;
@@ -244,8 +238,8 @@
 }
 
-static void tmpfs_instance_done(devmap_handle_t devmap_handle)
-{
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle
+static void tmpfs_instance_done(service_id_t service_id)
+{
+	unsigned long key[] = {
+		[NODES_KEY_DEV] = service_id
 	};
 	/*
@@ -262,8 +256,6 @@
 {
 	tmpfs_node_t *parentp = TMPFS_NODE(pfn);
-	link_t *lnk;
-
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+
+	list_foreach(parentp->cs_list, lnk) {
 		tmpfs_dentry_t *dentryp;
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
@@ -278,8 +270,8 @@
 }
 
-int tmpfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
-{
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+int tmpfs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
+{
+	unsigned long key[] = {
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
@@ -307,5 +299,5 @@
 }
 
-int tmpfs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int lflag)
+int tmpfs_create_node(fs_node_t **rfn, service_id_t service_id, int lflag)
 {
 	fs_node_t *rootfn;
@@ -326,5 +318,5 @@
 	nodep->bp->data = nodep;	/* link the FS and TMPFS nodes */
 
-	rc = tmpfs_root_get(&rootfn, devmap_handle);
+	rc = tmpfs_root_get(&rootfn, service_id);
 	assert(rc == EOK);
 	if (!rootfn)
@@ -332,5 +324,5 @@
 	else
 		nodep->index = tmpfs_next_index++;
-	nodep->devmap_handle = devmap_handle;
+	nodep->service_id = service_id;
 	if (lflag & L_DIRECTORY) 
 		nodep->type = TMPFS_DIRECTORY;
@@ -340,5 +332,5 @@
 	/* Insert the new node into the nodes hash table. */
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = nodep->devmap_handle,
+		[NODES_KEY_DEV] = nodep->service_id,
 		[NODES_KEY_INDEX] = nodep->index
 	};
@@ -353,8 +345,8 @@
 	
 	assert(!nodep->lnkcnt);
-	assert(list_empty(&nodep->cs_head));
-
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = nodep->devmap_handle,
+	assert(list_empty(&nodep->cs_list));
+
+	unsigned long key[] = {
+		[NODES_KEY_DEV] = nodep->service_id,
 		[NODES_KEY_INDEX] = nodep->index
 	};
@@ -373,11 +365,9 @@
 	tmpfs_node_t *childp = TMPFS_NODE(cfn);
 	tmpfs_dentry_t *dentryp;
-	link_t *lnk;
 
 	assert(parentp->type == TMPFS_DIRECTORY);
 
 	/* Check for duplicit entries. */
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+	list_foreach(parentp->cs_list, lnk) {
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);	
 		if (!str_cmp(dentryp->name, nm))
@@ -401,5 +391,5 @@
 	dentryp->node = childp;
 	childp->lnkcnt++;
-	list_append(&dentryp->link, &parentp->cs_head);
+	list_append(&dentryp->link, &parentp->cs_list);
 
 	return EOK;
@@ -411,11 +401,9 @@
 	tmpfs_node_t *childp = NULL;
 	tmpfs_dentry_t *dentryp;
-	link_t *lnk;
 
 	if (!parentp)
 		return EBUSY;
 	
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+	list_foreach(parentp->cs_list, lnk) {
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
 		if (!str_cmp(dentryp->name, nm)) {
@@ -423,5 +411,5 @@
 			assert(FS_NODE(childp) == cfn);
 			break;
-		}	
+		}
 	}
 
@@ -429,5 +417,5 @@
 		return ENOENT;
 		
-	if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_head))
+	if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_list))
 		return ENOTEMPTY;
 
@@ -439,80 +427,50 @@
 }
 
-void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+/*
+ * Implementation of the VFS_OUT interface.
+ */
+
+static int
+tmpfs_mounted(service_id_t service_id, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
 	fs_node_t *rootfn;
 	int rc;
 	
-	/* Accept the mount options. */
-	char *opts;
-	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
 	/* Check if this device is not already mounted. */
-	rc = tmpfs_root_get(&rootfn, devmap_handle);
+	rc = tmpfs_root_get(&rootfn, service_id);
 	if ((rc == EOK) && (rootfn)) {
 		(void) tmpfs_node_put(rootfn);
-		free(opts);
-		async_answer_0(rid, EEXIST);
-		return;
+		return EEXIST;
 	}
 
 	/* Initialize TMPFS instance. */
-	if (!tmpfs_instance_init(devmap_handle)) {
-		free(opts);
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
-
-	rc = tmpfs_root_get(&rootfn, devmap_handle);
+	if (!tmpfs_instance_init(service_id))
+		return ENOMEM;
+
+	rc = tmpfs_root_get(&rootfn, service_id);
 	assert(rc == EOK);
 	tmpfs_node_t *rootp = TMPFS_NODE(rootfn);
 	if (str_cmp(opts, "restore") == 0) {
-		if (tmpfs_restore(devmap_handle))
-			async_answer_3(rid, EOK, rootp->index, rootp->size,
-			    rootp->lnkcnt);
-		else
-			async_answer_0(rid, ELIMIT);
-	} else {
-		async_answer_3(rid, EOK, rootp->index, rootp->size,
-		    rootp->lnkcnt);
-	}
-	free(opts);
-}
-
-void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-
-	tmpfs_instance_done(devmap_handle);
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&tmpfs_libfs_ops, rid, request);
-}
-
-void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+		if (!tmpfs_restore(service_id))
+			return ELIMIT;
+	}
+
+	*index = rootp->index;
+	*size = rootp->size;
+	*lnkcnt = rootp->lnkcnt;
+
+	return EOK;
+}
+
+static int tmpfs_unmounted(service_id_t service_id)
+{
+	tmpfs_instance_done(service_id);
+	return EOK;
+}
+
+static int tmpfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -520,12 +478,10 @@
 	link_t *hlp;
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
@@ -538,6 +494,5 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -550,5 +505,4 @@
 		tmpfs_dentry_t *dentryp;
 		link_t *lnk;
-		aoff64_t i;
 		
 		assert(nodep->type == TMPFS_DIRECTORY);
@@ -559,13 +513,9 @@
 		 * hash table.
 		 */
-		for (i = 0, lnk = nodep->cs_head.next;
-		    (i < pos) && (lnk != &nodep->cs_head);
-		    i++, lnk = lnk->next)
-			;
-
-		if (lnk == &nodep->cs_head) {
+		lnk = list_nth(&nodep->cs_list, pos);
+		
+		if (lnk == NULL) {
 			async_answer_0(callid, ENOENT);
-			async_answer_1(rid, ENOENT, 0);
-			return;
+			return ENOENT;
 		}
 
@@ -577,17 +527,12 @@
 	}
 
-	/*
-	 * Answer the VFS_READ call.
-	 */
-	async_answer_1(rid, EOK, bytes);
-}
-
-void tmpfs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+	*rbytes = bytes;
+	return EOK;
+}
+
+static int
+tmpfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -595,12 +540,10 @@
 	link_t *hlp;
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
@@ -613,6 +556,5 @@
 	if (!async_data_write_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);	
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -622,7 +564,7 @@
 	if (pos + size <= nodep->size) {
 		/* The file size is not changing. */
-		(void) async_data_write_finalize(callid, nodep->data + pos, size);
-		async_answer_2(rid, EOK, size, nodep->size);
-		return;
+		(void) async_data_write_finalize(callid, nodep->data + pos,
+		    size);
+		goto out;
 	}
 	size_t delta = (pos + size) - nodep->size;
@@ -637,6 +579,6 @@
 	if (!newdata) {
 		async_answer_0(callid, ENOMEM);
-		async_answer_2(rid, EOK, 0, nodep->size);
-		return;
+		size = 0;
+		goto out;
 	}
 	/* Clear any newly allocated memory in order to emulate gaps. */
@@ -645,44 +587,35 @@
 	nodep->data = newdata;
 	(void) async_data_write_finalize(callid, nodep->data + pos, size);
-	async_answer_2(rid, EOK, size, nodep->size);
-}
-
-void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t size =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+
+out:
+	*wbytes = size;
+	*nsize = nodep->size;
+	return EOK;
+}
+
+static int tmpfs_truncate(service_id_t service_id, fs_index_t index,
+    aoff64_t size)
+{
 	/*
 	 * Lookup the respective TMPFS node.
 	 */
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
 	link_t *hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
-	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
-	    nh_link);
-	
-	if (size == nodep->size) {
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	if (size > SIZE_MAX) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
+	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t, nh_link);
+	
+	if (size == nodep->size)
+		return EOK;
+	
+	if (size > SIZE_MAX)
+		return ENOMEM;
 	
 	void *newdata = realloc(nodep->data, size);
-	if (!newdata) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!newdata)
+		return ENOMEM;
 	
 	if (size > nodep->size) {
@@ -693,45 +626,28 @@
 	nodep->size = size;
 	nodep->data = newdata;
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	int rc;
-
+	return EOK;
+}
+
+static int tmpfs_close(service_id_t service_id, fs_index_t index)
+{
+	return EOK;
+}
+
+static int tmpfs_destroy(service_id_t service_id, fs_index_t index)
+{
 	link_t *hlp;
 	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
+		[NODES_KEY_DEV] = service_id,
 		[NODES_KEY_INDEX] = index
 	};
 	hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (!hlp)
+		return ENOENT;
 	tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
 	    nh_link);
-	rc = tmpfs_destroy_node(FS_NODE(nodep));
-	async_answer_0(rid, rc);
-}
-
-void tmpfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_sync(ipc_callid_t rid, ipc_call_t *request)
+	return tmpfs_destroy_node(FS_NODE(nodep));
+}
+
+static int tmpfs_sync(service_id_t service_id, fs_index_t index)
 {
 	/*
@@ -739,8 +655,20 @@
 	 * thus the sync operation is a no-op.
 	 */
-	async_answer_0(rid, EOK);
-}
+	return EOK;
+}
+
+vfs_out_ops_t tmpfs_ops = {
+	.mounted = tmpfs_mounted,
+	.unmounted = tmpfs_unmounted,
+	.read = tmpfs_read,
+	.write = tmpfs_write,
+	.truncate = tmpfs_truncate,
+	.close = tmpfs_close,
+	.destroy = tmpfs_destroy,
+	.sync = tmpfs_sync,
+};
 
 /**
  * @}
  */
+
Index: pace/srv/hid/adb_mouse/Makefile
===================================================================
--- uspace/srv/hid/adb_mouse/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-EXTRA_CFLAGS = -Iinclude
-BINARY = adb_ms
-
-SOURCES = \
-	adb_mouse.c \
-	adb_dev.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hid/adb_mouse/adb_dev.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_dev.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,103 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @{
- */ 
-/** @file
- * @brief
- */
-
-#include <ipc/adb.h>
-#include <async.h>
-#include <vfs/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "adb_mouse.h"
-#include "adb_dev.h"
-
-static void adb_dev_events(ipc_callid_t iid, ipc_call_t *icall);
-
-static int dev_phone;
-
-int adb_dev_init(void)
-{
-	const char *input = "/dev/adb/mouse";
-	int input_fd;
-
-	printf(NAME ": open %s\n", input);
-
-	input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s (%d)\n", input, input_fd);
-		return false;
-	}
-
-	dev_phone = fd_phone(input_fd);
-	if (dev_phone < 0) {
-		printf(NAME ": Failed to connect to device\n");
-		return false;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(dev_phone, 0, 0, 0, adb_dev_events) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return false;
-	}
-	
-	return 0;
-}
-
-static void adb_dev_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case IPC_FIRST_USER_METHOD:
-			mouse_handle_data(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/adb_mouse/adb_dev.h
===================================================================
--- uspace/srv/hid/adb_mouse/adb_dev.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef ADBDEV_H_
-#define ADBDEV_H_
-
-#include <sys/types.h>
-
-extern int adb_dev_init(void);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: pace/srv/hid/adb_mouse/adb_mouse.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_mouse.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,172 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup mouse
- * @brief ADB Apple classic mouse driver.
- *
- * This driver handles a mouse connected to Apple Desktop Bus speaking
- * the Apple classic protocol. It connects to an ADB driver.
- *
- * @{
- */
-/** @file
- */
-
-#include <ipc/mouse.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <async.h>
-#include <errno.h>
-#include <devmap.h>
-
-#include "adb_mouse.h"
-#include "adb_dev.h"
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall);
-static void mouse_ev_btn(int button, int press);
-static void mouse_ev_move(int dx, int dy);
-
-static int client_phone = -1;
-static bool b1_pressed, b2_pressed;
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": Chardev mouse driver\n");
-
-	/* Initialize device. */
-	if (adb_dev_init() != 0)
-		return -1;
-
-	b1_pressed = false;
-	b2_pressed = false; 
-
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
-	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
-		return -1;
-	}
-
-	char dev_path[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(dev_path, DEVMAP_NAME_MAXLEN, "%s/mouse", NAMESPACE);
-
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(dev_path, &devmap_handle) != EOK) {
-		printf(NAME ": Unable to register device %s\n", dev_path);
-		return -1;
-	}
-
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached. */
-	return 0;
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			if (client_phone != -1) {
-				async_hangup(client_phone);
-				client_phone = -1;
-			}
-
-			async_answer_0(callid, EOK);
-			return;
-		case IPC_M_CONNECT_TO_ME:
-			if (client_phone != -1) {
-				retval = ELIMIT;
-				break;
-			}
-			client_phone = IPC_GET_ARG5(call);
-			retval = 0;
-			break;
-		default:
-			retval = EINVAL;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-void mouse_handle_data(uint16_t data)
-{
-	bool b1, b2;
-	uint16_t udx, udy;
-	int dx, dy;
-
-	/* Extract fields. */
-	b1 = ((data >> 15) & 1) == 0;
-	udy = (data >> 8) & 0x7f;
-	b2 = ((data >> 7) & 1) == 0;
-	udx = data & 0x7f;
-
-	/* Decode 7-bit two's complement signed values. */
-	dx = (udx & 0x40) ? (udx - 0x80) : udx;
-	dy = (udy & 0x40) ? (udy - 0x80) : udy;
-
-	if (b1 != b1_pressed) {
-		mouse_ev_btn(1, b1);
-		b1_pressed = b1;
-	}
-
-	if (b2 != b2_pressed) {
-		mouse_ev_btn(2, b2);
-		b1_pressed = b1;
-	}
-
-	if (dx != 0 || dy != 0)
-		mouse_ev_move(dx, dy);
-}
-
-static void mouse_ev_btn(int button, int press)
-{
-	if (client_phone != -1) {
-		async_msg_2(client_phone, MEVENT_BUTTON, button, press);
-	}
-}
-
-static void mouse_ev_move(int dx, int dy)
-{
-	if (client_phone != -1)
-		async_msg_2(client_phone, MEVENT_MOVE, dx, dy);
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/adb_mouse/adb_mouse.h
===================================================================
--- uspace/srv/hid/adb_mouse/adb_mouse.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef ADB_MOUSE_H_
-#define ADB_MOUSE_H_
-
-#include <sys/types.h>
-
-#define NAME       "adb_ms"
-#define NAMESPACE  "hid_in"
-
-extern void mouse_handle_data(uint16_t);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/Makefile
===================================================================
--- uspace/srv/hid/char_mouse/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,39 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-EXTRA_CFLAGS = -Iinclude
-BINARY = char_ms
-
-SOURCES = \
-	proto/ps2.c \
-	char_mouse.c \
-	chardev.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hid/char_mouse/char_mouse.c
===================================================================
--- uspace/srv/hid/char_mouse/char_mouse.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,151 +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 mouse
- * @brief Chardev mouse driver.
- *
- * This is a common driver for mice attached to simple character devices
- * (PS/2 mice, serial mice).
- *
- * @{
- */
-/** @file
- */
-
-#include <ipc/mouse.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <async.h>
-#include <errno.h>
-#include <devmap.h>
-
-#include <char_mouse.h>
-#include <mouse_port.h>
-#include <mouse_proto.h>
-
-#define NAME       "mouse"
-#define NAMESPACE  "hid_in"
-
-int client_phone = -1;
-
-void mouse_handle_byte(int byte)
-{
-/*	printf("mouse byte: 0x%x\n", byte);*/
-	mouse_proto_parse_byte(byte);
-}
-
-void mouse_ev_btn(int button, int press)
-{
-/*	printf("ev_btn: button %d, press %d\n", button, press);*/
-	if (client_phone != -1) {
-		async_msg_2(client_phone, MEVENT_BUTTON, button, press);
-	}
-}
-
-void mouse_ev_move(int dx, int dy)
-{
-/*	printf("ev_move: dx %d, dy %d\n", dx, dy);*/
-	if (client_phone != -1)
-		async_msg_2(client_phone, MEVENT_MOVE, dx, dy);
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			if (client_phone != -1) {
-				async_hangup(client_phone);
-				client_phone = -1;
-			}
-
-			async_answer_0(callid, EOK);
-			return;
-		case IPC_M_CONNECT_TO_ME:
-			if (client_phone != -1) {
-				retval = ELIMIT;
-				break;
-			}
-			client_phone = IPC_GET_ARG5(call);
-			retval = 0;
-			break;
-		default:
-			retval = EINVAL;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": Chardev mouse driver\n");
-
-	/* Initialize port. */
-	if (mouse_port_init() != 0)
-		return -1;
-
-	/* Initialize protocol driver. */
-	if (mouse_proto_init() != 0)
-		return -1;
-
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
-	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
-		return -1;
-	}
-
-	char dev_path[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(dev_path, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
-
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(dev_path, &devmap_handle) != EOK) {
-		printf(NAME ": Unable to register device %s\n", dev_path);
-		return -1;
-	}
-
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached. */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/chardev.c
===================================================================
--- uspace/srv/hid/char_mouse/chardev.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,118 +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 mouse
- * @{
- */ 
-/** @file
- * @brief
- */
-
-#include <ipc/char.h>
-#include <async.h>
-#include <vfs/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <char_mouse.h>
-#include <mouse_port.h>
-
-static void chardev_events(ipc_callid_t iid, ipc_call_t *icall);
-
-static int dev_phone;
-
-#define NAME "char_mouse"
-
-int mouse_port_init(void)
-{
-	const char *input = "/dev/char/ps2b";
-	int input_fd;
-
-	printf(NAME ": open %s\n", input);
-
-	input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s (%d)\n", input, input_fd);
-		return false;
-	}
-
-	dev_phone = fd_phone(input_fd);
-	if (dev_phone < 0) {
-		printf(NAME ": Failed to connect to device\n");
-		return false;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(dev_phone, 0, 0, 0, chardev_events) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return false;
-	}
-
-	return 0;
-}
-
-void mouse_port_yield(void)
-{
-}
-
-void mouse_port_reclaim(void)
-{
-}
-
-void mouse_port_write(uint8_t data)
-{
-	async_msg_1(dev_phone, CHAR_WRITE_BYTE, data);
-}
-
-static void chardev_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case IPC_FIRST_USER_METHOD:
-			mouse_handle_byte(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/include/char_mouse.h
===================================================================
--- uspace/srv/hid/char_mouse/include/char_mouse.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,47 +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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef CHAR_MOUSE_H_
-#define CHAR_MOUSE_H_
-
-extern void mouse_handle_byte(int);
-extern void mouse_ev_btn(int button, int press);
-extern void mouse_ev_move(int dx, int dy);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/include/mouse_port.h
===================================================================
--- uspace/srv/hid/char_mouse/include/mouse_port.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,51 +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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_PORT_H_
-#define MOUSE_PORT_H_
-
-#include <sys/types.h>
-
-extern int mouse_port_init(void);
-extern void mouse_port_yield(void);
-extern void mouse_port_reclaim(void);
-extern void mouse_port_write(uint8_t);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: pace/srv/hid/char_mouse/include/mouse_proto.h
===================================================================
--- uspace/srv/hid/char_mouse/include/mouse_proto.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,46 +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 mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_PROTO_H_
-#define MOUSE_PROTO_H_
-
-extern void mouse_proto_parse_byte(int);
-extern int mouse_proto_init(void);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/char_mouse/proto/ps2.c
===================================================================
--- uspace/srv/hid/char_mouse/proto/ps2.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @{
- */
-/**
- * @file
- * @brief PS/2 mouse protocol driver.
- */
-
-#include <stdio.h>
-#include <mouse_port.h>
-#include <char_mouse.h>
-#include <mouse_proto.h>
-
-#define BUFSIZE 3
-
-#define PS2_MOUSE_OUT_INIT  0xf4
-#define PS2_MOUSE_ACK       0xfa
-
-typedef struct {
-	union {
-		unsigned char data[BUFSIZE];
-		struct {
-			unsigned leftbtn : 1;
-			unsigned rightbtn : 1;
-			unsigned middlebtn : 1;
-			unsigned isone : 1; /* Always one */
-			unsigned xsign : 1;
-			unsigned ysign : 1;
-			unsigned xovfl : 1;
-			unsigned yovfl : 1;
-			unsigned char x;
-			unsigned char y;
-		} val;
-	} u;
-} ps2packet_t;
-
-static ps2packet_t buf;
-static int bufpos = 0;
-static int leftbtn = 0;
-static int rightbtn = 0;
-static int middlebtn = 0;
-
-int mouse_proto_init(void)
-{
-	mouse_port_write(PS2_MOUSE_OUT_INIT);
-	return 0;
-}
-
-/** Convert 9-bit 2-complement signed number to integer */
-static int bit9toint(int sign, unsigned char data)
-{
-	int tmp;
-
-	if (!sign)
-		return data;
-
-	tmp = ((unsigned char)~data) + 1;
-	return -tmp;
-}
-
-/** Process mouse data */
-void mouse_proto_parse_byte(int data)
-{
-	int x, y;
-
-	/* Check that we have not lost synchronization */
-	if (bufpos == 0 && !(data & 0x8))
-		return; /* Synchro lost, ignore byte */
-
-	buf.u.data[bufpos++] = data;
-	if (bufpos == BUFSIZE) {
-		bufpos = 0;
-
-		if (buf.u.val.leftbtn ^ leftbtn) {
-			leftbtn = buf.u.val.leftbtn;
-			mouse_ev_btn(1, leftbtn);
-		}
-
-		if (buf.u.val.rightbtn ^ rightbtn) {
-			rightbtn = buf.u.val.rightbtn;
-			mouse_ev_btn(2, rightbtn);
-		}
-
-		if (buf.u.val.middlebtn ^ middlebtn) {
-			middlebtn = buf.u.val.middlebtn;
-			mouse_ev_btn(3, middlebtn);
-		}
-
-		x =   bit9toint(buf.u.val.xsign, buf.u.val.x);
-		y = - bit9toint(buf.u.val.ysign, buf.u.val.y);
-
-		if (x != 0 || y != 0) {
-			mouse_ev_move(x, y);
-		}
-	}
-
-	return;
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/console/Makefile
===================================================================
--- uspace/srv/hid/console/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/console/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,29 +29,31 @@
 
 USPACE_PREFIX = ../../..
+LIBS = $(LIBIMGMAP_PREFIX)/libimgmap.a
+EXTRA_CFLAGS += -I$(LIBIMGMAP_PREFIX)
 BINARY = console
 
-GENERIC_SOURCES = \
+SOURCES = \
 	console.c \
 	keybuffer.c \
+	images.c \
 	gcons.c
 
 IMAGES = \
-	gfx/helenos.ppm \
-	gfx/nameic.ppm \
-	gfx/cons_selected.ppm \
-	gfx/cons_idle.ppm \
-	gfx/cons_has_data.ppm \
-	gfx/cons_kernel.ppm \
-	gfx/anim_1.ppm \
-	gfx/anim_2.ppm \
-	gfx/anim_3.ppm \
-	gfx/anim_4.ppm
+	gfx/helenos.tga \
+	gfx/nameic.tga \
+	gfx/cons_selected.tga \
+	gfx/cons_idle.tga \
+	gfx/cons_has_data.tga \
+	gfx/cons_kernel.tga \
+	gfx/anim_1.tga \
+	gfx/anim_2.tga \
+	gfx/anim_3.tga \
+	gfx/anim_4.tga
 
-SOURCES = \
-	$(GENERIC_SOURCES) \
-	$(IMAGES)
+PRE_DEPEND = images.c images.h
+EXTRA_CLEAN = images.c images.h
 
 include $(USPACE_PREFIX)/Makefile.common
 
-%.o: %.ppm
-	$(OBJCOPY) -I binary -O $(BFD_NAME) -B $(BFD_ARCH) $< $@
+images.c images.h: $(IMAGES)
+	$(ROOT_PATH)/tools/mkarray.py images CONSOLE_IMAGES $^
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/console/console.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,14 +35,16 @@
 
 #include <libc.h>
-#include <ipc/kbd.h>
+#include <ipc/input.h>
 #include <io/keycode.h>
-#include <ipc/mouse.h>
 #include <ipc/fb.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
+#include <ns_obsolete.h>
 #include <errno.h>
+#include <str_error.h>
 #include <ipc/console.h>
 #include <unistd.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <adt/fifo.h>
 #include <sys/mman.h>
@@ -50,5 +53,5 @@
 #include <sysinfo.h>
 #include <event.h>
-#include <devmap.h>
+#include <loc.h>
 #include <fcntl.h>
 #include <vfs/vfs.h>
@@ -61,13 +64,9 @@
 #include "keybuffer.h"
 
-
 #define NAME       "console"
 #define NAMESPACE  "term"
 
-/** Phone to the keyboard driver. */
-static int kbd_phone;
-
-/** Phone to the mouse driver. */
-static int mouse_phone;
+/** Session with the input server. */
+static async_sess_t *input_sess;
 
 /** Information about framebuffer */
@@ -82,5 +81,5 @@
 	size_t index;             /**< Console index */
 	size_t refcount;          /**< Connection reference count */
-	devmap_handle_t devmap_handle;  /**< Device handle */
+	service_id_t service_id;  /**< Service ID */
 	keybuffer_t keybuffer;    /**< Buffer for incoming keys. */
 	screenbuffer_t scr;       /**< Screenbuffer for saving screen
@@ -109,57 +108,85 @@
 static FIBRIL_CONDVAR_INITIALIZE(input_cv);
 
+static FIBRIL_MUTEX_INITIALIZE(big_console_lock);
+
+static void console_serialize_start(void)
+{
+	fibril_mutex_lock(&big_console_lock);
+}
+
+static void console_serialize_end(void)
+{
+	fibril_mutex_unlock(&big_console_lock);
+}
+
 static void curs_visibility(bool visible)
 {
-	async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 
+	async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 
 }
 
 static void curs_hide_sync(void)
 {
-	async_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 
+	async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 
 }
 
 static void curs_goto(sysarg_t x, sysarg_t y)
 {
-	async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
+	async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
 }
 
 static void screen_clear(void)
 {
-	async_msg_0(fb_info.phone, FB_CLEAR);
+	async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
 }
 
 static void screen_yield(void)
 {
-	async_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
+	async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
 }
 
 static void screen_reclaim(void)
 {
-	async_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
-}
-
-static void kbd_yield(void)
-{
-	async_req_0_0(kbd_phone, KBD_YIELD);
-}
-
-static void kbd_reclaim(void)
-{
-	async_req_0_0(kbd_phone, KBD_RECLAIM);
+	async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
+}
+
+static void input_yield(void)
+{
+	async_exch_t *exch = async_exchange_begin(input_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with input device.\n",
+		    NAME);
+		return;
+	}
+	
+	async_req_0_0(exch, INPUT_YIELD);
+	async_exchange_end(exch);
+}
+
+static void input_reclaim(void)
+{
+	async_exch_t *exch = async_exchange_begin(input_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with input device.\n",
+		    NAME);
+		return;
+	}
+	
+	async_req_0_0(exch, INPUT_RECLAIM);
+	async_exchange_end(exch);
 }
 
 static void set_style(uint8_t style)
 {
-	async_msg_1(fb_info.phone, FB_SET_STYLE, style);
+	async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style);
 }
 
 static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags)
 {
-	async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
+	async_obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
 }
 
 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
 {
-	async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 
+	async_obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 
 }
 
@@ -216,5 +243,5 @@
 		}
 		
-		async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
+		async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
 		    x0, y0, width, height);
 	}
@@ -257,5 +284,5 @@
 static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row)
 {
-	async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
+	async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
 }
 
@@ -306,5 +333,5 @@
 		
 		if (cons == active_console)
-			async_msg_1(fb_info.phone, FB_SCROLL, 1);
+			async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1);
 	}
 	
@@ -323,12 +350,12 @@
 	
 	if (cons == kernel_console) {
-		async_serialize_start();
+		console_serialize_start();
 		curs_hide_sync();
 		gcons_in_kernel();
 		screen_yield();
-		kbd_yield();
-		async_serialize_end();
-		
-		if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
+		input_yield();
+		console_serialize_end();
+		
+		if (console_kcon()) {
 			prev_console = active_console;
 			active_console = kernel_console;
@@ -338,9 +365,9 @@
 	
 	if (cons != kernel_console) {
-		async_serialize_start();
+		console_serialize_start();
 		
 		if (active_console == kernel_console) {
 			screen_reclaim();
-			kbd_reclaim();
+			input_reclaim();
 			gcons_redraw_console();
 		}
@@ -365,5 +392,5 @@
 			
 			/* This call can preempt, but we are already at the end */
-			rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
+			rc = async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
 			    0, 0, cons->scr.size_x,
 			    cons->scr.size_y);
@@ -393,10 +420,10 @@
 		curs_visibility(cons->scr.is_cursor_visible);
 		
-		async_serialize_end();
-	}
-}
-
-/** Handler for keyboard */
-static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
+		console_serialize_end();
+	}
+}
+
+/** Handler for input events */
+static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	/* Ignore parameters, the connection is already opened */
@@ -406,12 +433,15 @@
 		
 		int retval;
-		console_event_t ev;
+		kbd_event_t ev;
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			async_hangup(input_sess);
+			return;
+		}
 		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case KBD_EVENT:
-			/* Got event from keyboard driver. */
+		case INPUT_EVENT_KEY:
+			/* Got key press/release event */
 			retval = 0;
 			ev.type = IPC_GET_ARG1(call);
@@ -434,26 +464,12 @@
 			fibril_mutex_unlock(&input_mutex);
 			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-/** Handler for mouse events */
-static void mouse_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		int retval;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case MEVENT_BUTTON:
+		case INPUT_EVENT_MOVE:
+			/* Got pointer move event */
+			gcons_mouse_move((int) IPC_GET_ARG1(call),
+			    (int) IPC_GET_ARG2(call));
+			retval = 0;
+			break;
+		case INPUT_EVENT_BUTTON:
+			/* Got pointer button press/release event */
 			if (IPC_GET_ARG1(call) == 1) {
 				int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
@@ -463,9 +479,4 @@
 			retval = 0;
 			break;
-		case MEVENT_MOVE:
-			gcons_mouse_move((int) IPC_GET_ARG1(call),
-			    (int) IPC_GET_ARG2(call));
-			retval = 0;
-			break;
 		default:
 			retval = ENOENT;
@@ -487,5 +498,5 @@
 	}
 	
-	async_serialize_start();
+	console_serialize_start();
 	
 	size_t off = 0;
@@ -495,5 +506,5 @@
 	}
 	
-	async_serialize_end();
+	console_serialize_end();
 	
 	gcons_notify_char(cons->index);
@@ -521,5 +532,5 @@
 	
 	size_t pos = 0;
-	console_event_t ev;
+	kbd_event_t ev;
 	fibril_mutex_lock(&input_mutex);
 	
@@ -546,5 +557,5 @@
 static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
 {
-	console_event_t ev;
+	kbd_event_t ev;
 	
 	fibril_mutex_lock(&input_mutex);
@@ -562,5 +573,5 @@
 
 /** Default thread for new connections */
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	console_t *cons = NULL;
@@ -571,5 +582,5 @@
 			continue;
 		
-		if (consoles[i].devmap_handle == (devmap_handle_t) IPC_GET_ARG1(*icall)) {
+		if (consoles[i].service_id == (service_id_t) IPC_GET_ARG1(*icall)) {
 			cons = &consoles[i];
 			break;
@@ -590,5 +601,5 @@
 	int rc;
 	
-	async_serialize_start();
+	console_serialize_start();
 	if (cons->refcount == 0)
 		gcons_notify_connect(cons->index);
@@ -600,7 +611,7 @@
 	
 	while (true) {
-		async_serialize_end();
+		console_serialize_end();
 		callid = async_get_call(&call);
-		async_serialize_start();
+		console_serialize_start();
 		
 		arg1 = 0;
@@ -608,24 +619,27 @@
 		arg3 = 0;
 		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		if (!IPC_GET_IMETHOD(call)) {
 			cons->refcount--;
 			if (cons->refcount == 0)
 				gcons_notify_disconnect(cons->index);
+			console_serialize_end();
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case VFS_OUT_READ:
-			async_serialize_end();
+			console_serialize_end();
 			cons_read(cons, callid, &call);
-			async_serialize_start();
+			console_serialize_start();
 			continue;
 		case VFS_OUT_WRITE:
-			async_serialize_end();
+			console_serialize_end();
 			cons_write(cons, callid, &call);
-			async_serialize_start();
+			console_serialize_start();
 			continue;
 		case VFS_OUT_SYNC:
 			fb_pending_flush();
 			if (cons == active_console) {
-				async_req_0_0(fb_info.phone, FB_FLUSH);
+				async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
 				curs_goto(cons->scr.position_x, cons->scr.position_y);
 			}
@@ -634,5 +648,5 @@
 			/* Send message to fb */
 			if (cons == active_console)
-				async_msg_0(fb_info.phone, FB_CLEAR);
+				async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
 			
 			screenbuffer_clear(&cons->scr);
@@ -693,11 +707,8 @@
 			break;
 		case CONSOLE_GET_EVENT:
-			async_serialize_end();
+			console_serialize_end();
 			cons_get_event(cons, callid, &call);
-			async_serialize_start();
+			console_serialize_start();
 			continue;
-		case CONSOLE_KCON_ENABLE:
-			change_console(kernel_console);
-			break;
 		}
 		async_answer_3(callid, EOK, arg1, arg2, arg3);
@@ -710,61 +721,60 @@
 }
 
-static bool console_init(char *input)
-{
-	/* Connect to input device */
-	int input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s\n", input);
+static async_sess_t *connect_input(const char *svc_path)
+{
+	async_sess_t *sess;
+	async_exch_t *exch;
+	service_id_t service_id;
+	
+	int rc = loc_service_get_id(svc_path, &service_id, 0);
+	if (rc == EOK) {
+		sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0);
+		if (sess == NULL) {
+			printf("%s: Failed to connect to input server\n", NAME);
+			return NULL;
+		}
+	} else {
+		return NULL;
+	}
+	
+	exch = async_exchange_begin(sess);
+	if (exch == NULL) {
+		printf("%s: Failed to create callback from input server.\n", NAME);
+		return NULL;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
+
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_hangup(sess);
+		printf("%s: Failed to create callback from input server (%s).\n",
+		    NAME, str_error(rc));
+		return NULL;
+	}
+	
+	return sess;
+}
+
+static bool console_srv_init(char *input_dev)
+{
+	/* Connect to input server */
+	input_sess = connect_input(input_dev);
+	if (input_sess == NULL)
 		return false;
-	}
-	
-	kbd_phone = fd_phone(input_fd);
-	if (kbd_phone < 0) {
-		printf(NAME ": Failed to connect to input device\n");
+	
+	/* Connect to framebuffer driver */
+	fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0);
+	if (fb_info.phone < 0) {
+		printf("%s: Failed to connect to video service\n", NAME);
 		return false;
 	}
 	
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, keyboard_events)
-	    != 0) {
-		printf(NAME ": Failed to create callback from input device\n");
-		return false;
-	}
-	
-	/* Connect to mouse device */
-	mouse_phone = -1;
-	int mouse_fd = open("/dev/hid_in/mouse", O_RDONLY);
-	
-	if (mouse_fd < 0) {
-		printf(NAME ": Notice - failed opening %s\n", "/dev/hid_in/mouse");
-		goto skip_mouse;
-	}
-	
-	mouse_phone = fd_phone(mouse_fd);
-	if (mouse_phone < 0) {
-		printf(NAME ": Failed to connect to mouse device\n");
-		goto skip_mouse;
-	}
-	
-	if (async_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, mouse_events)
-	    != 0) {
-		printf(NAME ": Failed to create callback from mouse device\n");
-		mouse_phone = -1;
-		goto skip_mouse;
-	}
-	
-skip_mouse:
-	
-	/* Connect to framebuffer driver */
-	fb_info.phone = service_connect_blocking(SERVICE_VIDEO, 0, 0);
-	if (fb_info.phone < 0) {
-		printf(NAME ": Failed to connect to video service\n");
-		return -1;
-	}
-	
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
+	/* Register server */
+	int rc = loc_server_register(NAME, client_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
+		printf("%s: Unable to register server (%d)\n", NAME, rc);
 		return false;
 	}
@@ -774,7 +784,7 @@
 	
 	/* Synchronize, the gcons could put something in queue */
-	async_req_0_0(fb_info.phone, FB_FLUSH);
-	async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
-	async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
+	async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
+	async_obsolete_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
+	async_obsolete_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
 	
 	/* Set up shared memory buffer. */
@@ -787,5 +797,5 @@
 	
 	if (interbuffer) {
-		if (async_share_out_start(fb_info.phone, interbuffer,
+		if (async_obsolete_share_out_start(fb_info.phone, interbuffer,
 		    AS_AREA_READ) != EOK) {
 			as_area_destroy(interbuffer);
@@ -802,5 +812,5 @@
 			if (screenbuffer_init(&consoles[i].scr,
 			    fb_info.cols, fb_info.rows) == NULL) {
-				printf(NAME ": Unable to allocate screen buffer %zu\n", i);
+				printf("%s: Unable to allocate screen buffer %zu\n", NAME, i);
 				return false;
 			}
@@ -810,9 +820,9 @@
 			consoles[i].refcount = 0;
 			
-			char vc[DEVMAP_NAME_MAXLEN + 1];
-			snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
+			char vc[LOC_NAME_MAXLEN + 1];
+			snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i);
 			
-			if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {
-				printf(NAME ": Unable to register device %s\n", vc);
+			if (loc_service_register(vc, &consoles[i].service_id) != EOK) {
+				printf("%s: Unable to register service %s\n", NAME, vc);
 				return false;
 			}
@@ -820,9 +830,6 @@
 	}
 	
-	/* Disable kernel output to the console */
-	__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
-	
 	/* Initialize the screen */
-	async_serialize_start();
+	console_serialize_start();
 	gcons_redraw_console();
 	set_style(STYLE_NORMAL);
@@ -830,10 +837,10 @@
 	curs_goto(0, 0);
 	curs_visibility(active_console->scr.is_cursor_visible);
-	async_serialize_end();
+	console_serialize_end();
 	
 	/* Receive kernel notifications */
 	async_set_interrupt_received(interrupt_received);
 	if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
-		printf(NAME ": Error registering kconsole notifications\n");
+		printf("%s: Error registering kconsole notifications\n", NAME);
 	
 	return true;
@@ -842,5 +849,5 @@
 static void usage(void)
 {
-	printf("Usage: console <input>\n");
+	printf("Usage: console <input_dev>\n");
 }
 
@@ -854,5 +861,5 @@
 	printf(NAME ": HelenOS Console service\n");
 	
-	if (!console_init(argv[1]))
+	if (!console_srv_init(argv[1]))
 		return -1;
 	
Index: uspace/srv/hid/console/gcons.c
===================================================================
--- uspace/srv/hid/console/gcons.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/console/gcons.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,4 +35,5 @@
 #include <ipc/fb.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <stdio.h>
 #include <sys/mman.h>
@@ -40,7 +41,9 @@
 #include <align.h>
 #include <bool.h>
+#include <imgmap.h>
 
 #include "console.h"
 #include "gcons.h"
+#include "images.h"
 
 #define CONSOLE_TOP     66
@@ -57,30 +60,20 @@
 #define COLOR_BACKGROUND  0xffffff
 
-extern char _binary_gfx_helenos_ppm_start[0];
-extern int _binary_gfx_helenos_ppm_size;
-extern char _binary_gfx_nameic_ppm_start[0];
-extern int _binary_gfx_nameic_ppm_size;
-
-extern char _binary_gfx_anim_1_ppm_start[0];
-extern int _binary_gfx_anim_1_ppm_size;
-extern char _binary_gfx_anim_2_ppm_start[0];
-extern int _binary_gfx_anim_2_ppm_size;
-extern char _binary_gfx_anim_3_ppm_start[0];
-extern int _binary_gfx_anim_3_ppm_size;
-extern char _binary_gfx_anim_4_ppm_start[0];
-extern int _binary_gfx_anim_4_ppm_size;
-
-extern char _binary_gfx_cons_selected_ppm_start[0];
-extern int _binary_gfx_cons_selected_ppm_size;
-extern char _binary_gfx_cons_idle_ppm_start[0];
-extern int _binary_gfx_cons_idle_ppm_size;
-extern char _binary_gfx_cons_has_data_ppm_start[0];
-extern int _binary_gfx_cons_has_data_ppm_size;
-extern char _binary_gfx_cons_kernel_ppm_start[0];
-extern int _binary_gfx_cons_kernel_ppm_size;
-
 static bool use_gcons = false;
 static sysarg_t xres;
 static sysarg_t yres;
+
+static imgmap_t *helenos_img;
+static imgmap_t *nameic_img;
+
+static imgmap_t *anim_1_img;
+static imgmap_t *anim_2_img;
+static imgmap_t *anim_3_img;
+static imgmap_t *anim_4_img;
+
+static imgmap_t *cons_has_data_img;
+static imgmap_t *cons_idle_img;
+static imgmap_t *cons_kernel_img;
+static imgmap_t *cons_selected_img;
 
 enum butstate {
@@ -100,6 +93,6 @@
 static int fbphone;
 
-/** List of pixmaps identifying these icons */
-static int ic_pixmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
+/** List of image maps identifying these icons */
+static int ic_imgmaps[CONS_LAST] = {-1, -1, -1, -1, -1, -1};
 static int animation = -1;
 
@@ -115,5 +108,5 @@
 static void vp_switch(int vp)
 {
-	async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
+	async_obsolete_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
 }
 
@@ -121,5 +114,5 @@
 static int vp_create(sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height)
 {
-	return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
+	return async_obsolete_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
 	    (width << 16) | height);
 }
@@ -127,10 +120,10 @@
 static void clear(void)
 {
-	async_msg_0(fbphone, FB_CLEAR);
+	async_obsolete_msg_0(fbphone, FB_CLEAR);
 }
 
 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
 {
-	async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
+	async_obsolete_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
 }
 
@@ -138,5 +131,5 @@
 static void tran_putch(wchar_t ch, sysarg_t col, sysarg_t row)
 {
-	async_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
+	async_obsolete_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
 }
 
@@ -148,7 +141,7 @@
 	enum butstate state = console_state[index];
 	
-	if (ic_pixmaps[state] != -1)
-		async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index],
-		    ic_pixmaps[state]);
+	if (ic_imgmaps[state] != -1)
+		async_obsolete_msg_2(fbphone, FB_VP_DRAW_IMGMAP, cstatus_vp[index],
+		    ic_imgmaps[state]);
 	
 	if ((state != CONS_DISCONNECTED) && (state != CONS_KERNEL)
@@ -167,6 +160,8 @@
 void gcons_change_console(size_t index)
 {
-	if (!use_gcons)
-		return;
+	if (!use_gcons) {
+		active_console = index;
+		return;
+	}
 	
 	if (active_console == KERNEL_CONSOLE) {
@@ -177,5 +172,5 @@
 		
 		if (animation != -1)
-			async_msg_1(fbphone, FB_ANIM_START, animation);
+			async_obsolete_msg_1(fbphone, FB_ANIM_START, animation);
 	} else {
 		if (console_state[active_console] == CONS_DISCONNECTED_SEL)
@@ -258,5 +253,5 @@
 {
 	if (animation != -1)
-		async_msg_1(fbphone, FB_ANIM_STOP, animation);
+		async_obsolete_msg_1(fbphone, FB_ANIM_STOP, animation);
 	
 	active_console = KERNEL_CONSOLE;
@@ -294,5 +289,5 @@
 	
 	if (active_console != KERNEL_CONSOLE)
-		async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
+		async_obsolete_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
 }
 
@@ -355,41 +350,43 @@
 }
 
-/** Draw a PPM pixmap to framebuffer
- *
- * @param logo Pointer to PPM data
- * @param size Size of PPM data
- * @param x Coordinate of upper left corner
- * @param y Coordinate of upper left corner
- *
- */
-static void draw_pixmap(char *logo, size_t size, sysarg_t x, sysarg_t y)
-{
+/** Draw an image map to framebuffer
+ *
+ * @param img  Image map
+ * @param x    Coordinate of upper left corner
+ * @param y    Coordinate of upper left corner
+ *
+ */
+static void draw_imgmap(imgmap_t *img, sysarg_t x, sysarg_t y)
+{
+	if (img == NULL)
+		return;
+	
 	/* Create area */
-	char *shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
+	char *shm = mmap(NULL, img->size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
 	    MAP_ANONYMOUS, 0, 0);
 	if (shm == MAP_FAILED)
 		return;
 	
-	memcpy(shm, logo, size);
+	memcpy(shm, img, img->size);
 	
 	/* Send area */
-	int rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
+	int rc = async_obsolete_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
 	if (rc)
 		goto exit;
 	
-	rc = async_share_out_start(fbphone, shm, PROTO_READ);
+	rc = async_obsolete_share_out_start(fbphone, shm, PROTO_READ);
 	if (rc)
 		goto drop;
 	
 	/* Draw logo */
-	async_msg_2(fbphone, FB_DRAW_PPM, x, y);
+	async_obsolete_msg_2(fbphone, FB_DRAW_IMGMAP, x, y);
 	
 drop:
 	/* Drop area */
-	async_msg_0(fbphone, FB_DROP_SHM);
+	async_obsolete_msg_0(fbphone, FB_DROP_SHM);
 	
 exit:
 	/* Remove area */
-	munmap(shm, size);
+	munmap(shm, img->size);
 }
 
@@ -403,8 +400,6 @@
 	set_rgb_color(COLOR_MAIN, COLOR_MAIN);
 	clear();
-	draw_pixmap(_binary_gfx_helenos_ppm_start,
-	    (size_t) &_binary_gfx_helenos_ppm_size, xres - 66, 2);
-	draw_pixmap(_binary_gfx_nameic_ppm_start,
-	    (size_t) &_binary_gfx_nameic_ppm_size, 5, 17);
+	draw_imgmap(helenos_img, xres - 66, 2);
+	draw_imgmap(nameic_img, 5, 17);
 	
 	unsigned int i;
@@ -415,75 +410,73 @@
 }
 
-/** Creates a pixmap on framebuffer
- *
- * @param data PPM data
- * @param size PPM data size
- *
- * @return Pixmap identification
- *
- */
-static int make_pixmap(char *data, size_t size)
-{
+/** Create an image map on framebuffer
+ *
+ * @param img Image map.
+ *
+ * @return Image map identification
+ *
+ */
+static int make_imgmap(imgmap_t *img)
+{
+	if (img == NULL)
+		return -1;
+	
 	/* Create area */
-	char *shm = mmap(NULL, size, PROTO_READ | PROTO_WRITE, MAP_SHARED |
-	    MAP_ANONYMOUS, 0, 0);
+	char *shm = mmap(NULL, img->size, PROTO_READ | PROTO_WRITE,
+	    MAP_SHARED | MAP_ANONYMOUS, 0, 0);
 	if (shm == MAP_FAILED)
 		return -1;
 	
-	memcpy(shm, data, size);
-	
-	int pxid = -1;
+	memcpy(shm, img, img->size);
+	
+	int id = -1;
 	
 	/* Send area */
-	int rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
+	int rc = async_obsolete_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
 	if (rc)
 		goto exit;
 	
-	rc = async_share_out_start(fbphone, shm, PROTO_READ);
+	rc = async_obsolete_share_out_start(fbphone, shm, PROTO_READ);
 	if (rc)
 		goto drop;
 	
-	/* Obtain pixmap */
-	rc = async_req_0_0(fbphone, FB_SHM2PIXMAP);
+	/* Obtain image map identifier */
+	rc = async_obsolete_req_0_0(fbphone, FB_SHM2IMGMAP);
 	if (rc < 0)
 		goto drop;
 	
-	pxid = rc;
+	id = rc;
 	
 drop:
 	/* Drop area */
-	async_msg_0(fbphone, FB_DROP_SHM);
+	async_obsolete_msg_0(fbphone, FB_DROP_SHM);
 	
 exit:
 	/* Remove area */
-	munmap(shm, size);
-	
-	return pxid;
+	munmap(shm, img->size);
+	
+	return id;
 }
 
 static void make_anim(void)
 {
-	int an = async_req_1_0(fbphone, FB_ANIM_CREATE,
+	int an = async_obsolete_req_1_0(fbphone, FB_ANIM_CREATE,
 	    cstatus_vp[KERNEL_CONSOLE]);
 	if (an < 0)
 		return;
 	
-	int pm = make_pixmap(_binary_gfx_anim_1_ppm_start,
-	    (size_t) &_binary_gfx_anim_1_ppm_size);
-	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
-	
-	pm = make_pixmap(_binary_gfx_anim_2_ppm_start,
-	    (size_t) &_binary_gfx_anim_2_ppm_size);
-	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
-	
-	pm = make_pixmap(_binary_gfx_anim_3_ppm_start,
-	    (size_t) &_binary_gfx_anim_3_ppm_size);
-	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
-	
-	pm = make_pixmap(_binary_gfx_anim_4_ppm_start,
-	    (size_t) &_binary_gfx_anim_4_ppm_size);
-	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
-	
-	async_msg_1(fbphone, FB_ANIM_START, an);
+	int pm = make_imgmap(anim_1_img);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
+	
+	pm = make_imgmap(anim_2_img);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
+	
+	pm = make_imgmap(anim_3_img);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
+	
+	pm = make_imgmap(anim_4_img);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDIMGMAP, an, pm);
+	
+	async_obsolete_msg_1(fbphone, FB_ANIM_START, an);
 	
 	animation = an;
@@ -495,5 +488,5 @@
 	fbphone = phone;
 	
-	int rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
+	int rc = async_obsolete_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
 	if (rc)
 		return;
@@ -501,4 +494,28 @@
 	if ((xres < 800) || (yres < 600))
 		return;
+	
+	/* Create image maps */
+	helenos_img = imgmap_decode_tga((void *) helenos_tga,
+	    helenos_tga_size);
+	nameic_img = imgmap_decode_tga((void *) nameic_tga,
+	    nameic_tga_size);
+	
+	anim_1_img = imgmap_decode_tga((void *) anim_1_tga,
+	    anim_1_tga_size);
+	anim_2_img = imgmap_decode_tga((void *) anim_2_tga,
+	    anim_2_tga_size);
+	anim_3_img = imgmap_decode_tga((void *) anim_3_tga,
+	    anim_3_tga_size);
+	anim_4_img = imgmap_decode_tga((void *) anim_4_tga,
+	    anim_4_tga_size);
+	
+	cons_has_data_img = imgmap_decode_tga((void *) cons_has_data_tga,
+	    cons_has_data_tga_size);
+	cons_idle_img = imgmap_decode_tga((void *) cons_idle_tga,
+	    cons_idle_tga_size);
+	cons_kernel_img = imgmap_decode_tga((void *) cons_kernel_tga,
+	    cons_kernel_tga_size);
+	cons_selected_img = imgmap_decode_tga((void *) cons_selected_tga,
+	    cons_selected_tga_size);
 	
 	/* Create console viewport */
@@ -528,20 +545,10 @@
 	
 	/* Initialize icons */
-	ic_pixmaps[CONS_SELECTED] =
-	    make_pixmap(_binary_gfx_cons_selected_ppm_start,
-	    (size_t) &_binary_gfx_cons_selected_ppm_size);
-	ic_pixmaps[CONS_IDLE] =
-	    make_pixmap(_binary_gfx_cons_idle_ppm_start,
-	    (size_t) &_binary_gfx_cons_idle_ppm_size);
-	ic_pixmaps[CONS_HAS_DATA] =
-	    make_pixmap(_binary_gfx_cons_has_data_ppm_start,
-	    (size_t) &_binary_gfx_cons_has_data_ppm_size);
-	ic_pixmaps[CONS_DISCONNECTED] =
-	    make_pixmap(_binary_gfx_cons_idle_ppm_start,
-	    (size_t) &_binary_gfx_cons_idle_ppm_size);
-	ic_pixmaps[CONS_KERNEL] =
-	    make_pixmap(_binary_gfx_cons_kernel_ppm_start,
-	    (size_t) &_binary_gfx_cons_kernel_ppm_size);
-	ic_pixmaps[CONS_DISCONNECTED_SEL] = ic_pixmaps[CONS_SELECTED];
+	ic_imgmaps[CONS_SELECTED] = make_imgmap(cons_selected_img);
+	ic_imgmaps[CONS_IDLE] = make_imgmap(cons_idle_img);
+	ic_imgmaps[CONS_HAS_DATA] = make_imgmap(cons_has_data_img);
+	ic_imgmaps[CONS_DISCONNECTED] = make_imgmap(cons_idle_img);
+	ic_imgmaps[CONS_KERNEL] = make_imgmap(cons_kernel_img);
+	ic_imgmaps[CONS_DISCONNECTED_SEL] = ic_imgmaps[CONS_SELECTED];
 	
 	make_anim();
Index: pace/srv/hid/console/gfx/anim_1.ppm
===================================================================
--- uspace/srv/hid/console/gfx/anim_1.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ääääää÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeeee½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeddd½½½öööÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööããããããöööþþþÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑÏÏÏÆÆÆDDDZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ'''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ   ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××!!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊqqqÿÿÿþþþ$$$ÿÿÿþþþþþþ%%%üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚNNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô333ÿÿÿÿÿÿ'''ÿÿÿÿÿÿþþþ'''ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ
-
-
-²²²¨¨¨UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù111ÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß"""âââæææ___¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔgggÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôôÿÿÿÿÿÿÿÿÿ
-
-
-õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBBUUUÎÎÎüüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKKrrrÿÿÿqqqNNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/anim_2.ppm
===================================================================
--- uspace/srv/hid/console/gfx/anim_2.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ääääää÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeeee½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿööö½½½eeeddd½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿöööããããããöööþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑÏÏÏÆÆÆDDDZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ'''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ   ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××!!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊqqqÿÿÿþþþ$$$ÿÿÿþþþþþþ%%%üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚNNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô333ÿÿÿÿÿÿ'''ÿÿÿÿÿÿþþþ'''ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ
-
-
-²²²¨¨¨UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù111ÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß"""âââæææ___¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔgggÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôôÿÿÿÿÿÿÿÿÿ
-
-
-õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBBUUUÎÎÎüüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKKrrrÿÿÿqqqNNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/anim_3.ppm
===================================================================
--- uspace/srv/hid/console/gfx/anim_3.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑÏÏÏÆÆÆDDDZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ'''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ   ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××!!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊqqqÿÿÿþþþ$$$ÿÿÿþþþþþþ%%%üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚNNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô333ÿÿÿÿÿÿ'''ÿÿÿÿÿÿþþþ'''ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ
-
-
-²²²¨¨¨UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù111ÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß"""âââæææ___¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔgggÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôôÿÿÿÿÿÿÿÿÿ
-
-
-õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBBUUUÎÎÎüüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKKrrrÿÿÿqqqNNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿ÷÷÷ääääää÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿööö½½½eeeeee½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeddd½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööããããããöööþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/anim_4.ppm
===================================================================
--- uspace/srv/hid/console/gfx/anim_4.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑÏÏÏÆÆÆDDDZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ'''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ   ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××!!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊqqqÿÿÿþþþ$$$ÿÿÿþþþþþþ%%%üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚNNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô333ÿÿÿÿÿÿ'''ÿÿÿÿÿÿþþþ'''ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ
-
-
-²²²¨¨¨UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù111ÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß"""âââæææ___¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔgggÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôôÿÿÿÿÿÿÿÿÿ
-
-
-õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBBUUUÎÎÎüüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKKrrrÿÿÿqqqNNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ääääää÷÷÷ÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeeee½½½öööÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãããeeedddãããÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿööö½½½eeeddd½½½öööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööããããããöööþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/cons_has_data.ppm
===================================================================
--- uspace/srv/hid/console/gfx/cons_has_data.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,5 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþúúþúúþúúþúúþûûþûûþûûþûûþûûþûûþüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþùùþøøþõõþêêþèèþèèþééþêêþëëþììþííþîîþîîþððþøøþúúþûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþ÷÷þññþááþÞÞþÞÞþÜÜþÞÞþßßþááþããþääþååþææþççþèèþééþëëþêêþììþ÷÷þúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþõõþîîþ××þÒÒþÏÏþÑÑþÒÒþÕÕþ××þÚÚþÜÜþÞÞþààþââþããþääþääþååþååþääþääþååþèèþõõþùùþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþííþÏÏþÇÇþÃÃþÃÃþÅÅþÈÈþËËþÎÎþÑÑþÕÕþØØþÛÛþÝÝþßßþààþááþââþââþââþââþááþßßþÞÞþßßþââþôôþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüþììþÇÇþ¸¸þ··þ¸¸þ»»þ¾¾þÂÂþÆÆþÊÊþÎÎþÒÒþÖÖþÙÙþÜÜþÞÞþààþááþââþââþââþââþààþßßþÜÜþÙÙþ××þÝÝþòòþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüþêêþÃÃþ±±þ¯¯þ°°þ²²þ¶¶þººþ¾¾þÃÃþÈÈþÍÍþÒÒþÖÖþÚÚþÝÝþßßþááþââþããþääþääþããþááþààþÝÝþÚÚþÖÖþÔÔþÚÚþòòþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüþëëþÁÁþ­­þ©©þ©©þ««þ¯¯þ³³þ¹¹þ¾¾þÄÄþÊÊþÏÏþÔÔþØØþÜÜþßßþââþääþååþææþççþççþææþääþââþààþÜÜþÙÙþÔÔþÑÑþØØþððþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþììþÃÃþ­­þ§§þ¦¦þ§§þªªþ®®þ´´þººþÁÁþÇÇþÍÍþÓÓþØØþÜÜþààþããþææþèèþééþêêþêêþêêþêêþèèþææþääþààþÝÝþØØþÓÓþÏÏþ××þððþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþííþÇÇþ±±þ©©þ¦¦þ¦¦þ¨¨þ¬¬þ±±þ··þ¾¾þÅÅþÌÌþÒÒþØØþÝÝþââþååþèèþêêþììþííþîîþîîþîîþîîþììþëëþèèþææþââþÞÞþØØþÓÓþÎÎþÕÕþððþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþööþÏÏþ¸¸þ¯¯þ©©þ§§þ¨¨þ««þ°°þ¶¶þ½½þÄÄþËËþÒÒþÙÙþÞÞþããþççþêêþííþïïþððþññþòòþòòþòòþòòþññþïïþííþëëþççþããþßßþÙÙþÓÓþÎÎþ××þ÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþîîþÇÇþ··þ°°þ««þªªþ¬¬þ°°þ¶¶þ½½þÄÄþÌÌþÓÓþÙÙþßßþååþééþììþïïþññþóóþôôþõõþõõþööþööþõõþõõþóóþòòþïïþííþééþååþààþÚÚþÔÔþÔÔþððþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ÷÷þØØþÂÂþ¸¸þ²²þ¯¯þ®®þ±±þ¶¶þ¼¼þÄÄþËËþÓÓþÚÚþààþææþëëþîîþññþóóþõõþööþ÷÷þøøþøøþùùþùùþøøþøøþ÷÷þõõþôôþññþïïþëëþççþááþÛÛþÕÕþÜÜþøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþòòþÒÒþÃÃþ»»þµµþ³³þ´´þ··þ½½þÄÄþËËþÓÓþÚÚþááþççþììþððþóóþõõþ÷÷þøøþùùþúúþúúþûûþûûþûûþûûþúúþúúþùùþ÷÷þööþóóþððþììþèèþââþÜÜþÛÛþóóþýýþþþÿÿÿÿÿÿÿÿÿÿÿÿþùùþààþÏÏþÅÅþ¾¾þººþ¹¹þººþ¾¾þÄÄþÌÌþÓÓþÚÚþááþèèþííþññþôôþööþøøþùùþúúþûûþüüþüüþüüþýýþýýþüüþüüþûûþûûþúúþøøþ÷÷þôôþññþííþèèþããþÞÞþããþùùþþþÿÿÿÿÿÿÿÿÿÿÿÿþøøþÝÝþÐÐþÈÈþÂÂþ¾¾þ¾¾þÁÁþÅÅþËËþÓÓþÚÚþááþèèþííþññþôôþ÷÷þùùþúúþûûþüüþüüþýýÿýýÿýýÿþþÿþþÿýýÿýýþýýþüüþüüþûûþùùþøøþõõþòòþîîþééþääþääþùùþþþÿÿÿÿÿÿÿÿÿþþþþõõþÞÞþÒÒþËËþÆÆþÃÃþÄÄþÇÇþÌÌþÒÒþÙÙþààþççþííþññþõõþ÷÷þùùþûûþüüþýýþýýÿýýÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿýýþýýþüüþûûþúúþøøþõõþòòþîîþêêþééþ÷÷þþþþþþÿÿÿÿÿÿþûûþééþÜÜþÕÕþÎÎþÊÊþÈÈþÊÊþÍÍþÒÒþÙÙþßßþææþììþññþôôþ÷÷þùùþûûþüüþýýÿýýÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿýýþýýþûûþúúþøøþööþóóþïïþììþîîþûûþþþÿÿÿÿÿÿþúúþèèþÝÝþ××þÑÑþÎÎþÍÍþÏÏþÓÓþØØþÞÞþååþëëþððþôôþ÷÷þùùþûûþüüþýýÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿýýþýýþüüþúúþùùþööþôôþððþððþûûþþþÿÿÿÿÿÿþúúþééþßßþÙÙþÔÔþÒÒþÒÒþÔÔþØØþÝÝþããþééþîîþóóþööþùùþûûþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýþýýþüüþúúþùùþ÷÷þôôþôôþüüþþþÿÿÿÿÿÿþûûþêêþááþÜÜþ××þÖÖþÖÖþØØþÜÜþââþççþììþññþõõþøøþúúþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýþýýþüüþûûþùùþøøþ÷÷þýýþþþÿÿÿÿÿÿþûûþëëþããþÞÞþÚÚþÙÙþÚÚþÜÜþààþååþêêþïïþóóþ÷÷þùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýþýýþüüþûûþúúþúúþýýþþþÿÿÿÿÿÿþûûþëëþääþààþÝÝþÜÜþÝÝþßßþããþèèþííþññþõõþøøþúúþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýþüüþüüþûûþþþþþþÿÿÿÿÿÿþûûþììþååþââþßßþÞÞþßßþââþææþêêþïïþóóþööþùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿýýþýýþýýþþþþþþÿÿÿÿÿÿþûûþííþææþããþààþààþááþääþèèþììþððþôôþ÷÷þúúþüüþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿþûûþííþççþääþááþááþââþååþééþííþññþõõþøøþúúþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿþûûþîîþççþääþââþââþããþææþêêþîîþòòþõõþøøþúúþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüþððþèèþääþââþââþääþææþêêþîîþòòþööþùùþûûþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþøøþêêþääþââþââþääþææþêêþîîþòòþööþùùþûûþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþúúþêêþääþââþââþããþææþééþîîþòòþõõþøøþúúþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþûûþííþääþááþààþááþääþèèþììþññþõõþøøþúúþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþööþååþßßþÞÞþßßþââþææþëëþïïþóóþ÷÷þùùþûûþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþúúþèèþÞÞþÜÜþÝÝþààþääþèèþííþòòþööþùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþõõþßßþÙÙþÚÚþÜÜþààþææþëëþððþôôþ÷÷þúúþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþøøþââþ××þÖÖþÙÙþÝÝþââþèèþííþòòþööþùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýþôôþÝÝþÓÓþÔÔþØØþÞÞþããþééþïïþóóþ÷÷þùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþýýþòòþÚÚþÐÐþÓÓþØØþßßþååþëëþððþôôþøøþúúþûûþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþññþØØþÏÏþÓÓþÙÙþààþççþììþññþõõþøøþúúþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþññþ××þÎÎþÓÓþÚÚþááþèèþííþòòþõõþøøþúúþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþððþÕÕþÎÎþÓÓþÛÛþââþèèþîîþòòþööþùùþûûþüüþýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþððþÖÖþÔÔþÕÕþÛÛþããþééþîîþóóþööþùùþûûþüüþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿýýÿüüÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþüüþööþððþÜÜþÛÛþÞÞþããþêêþïïþôôþ÷÷þùùþûûþüüÿýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿýýÿýýÿýýÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþüüþ÷÷þòòþããþääþééþììþððþôôþ÷÷þúúþüüþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþýýþùùþùùþ÷÷þîîþððþôôþ÷÷þùùþûûþýýÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþýýþûûþûûþüüþüüþýýþýýþþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/cons_idle.ppm
===================================================================
--- uspace/srv/hid/console/gfx/cons_idle.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,5 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùàààÏÏÏÅÅÅ¾¾¾ººº¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝÐÐÐÈÈÈÂÂÂ¾¾¾¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒËËËÆÆÆÃÃÃÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÎÎÎÊÊÊÈÈÈÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑÎÎÎÍÍÍÏÏÏÓÓÓØØØÞÞÞåååëëëðððôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýýýýüüüúúúùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔÒÒÒÒÒÒÔÔÔØØØÝÝÝãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüúúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××ÖÖÖÖÖÖØØØÜÜÜâââçççìììñññõõõøøøúúúûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚÙÙÙÚÚÚÜÜÜàààåååêêêïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝÜÜÜÝÝÝßßßãããèèèíííñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßßÞÞÞßßßâââæææêêêïïïóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããààààààáááäääèèèìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííçççäääááááááâââåååéééíííñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/cons_kernel.ppm
===================================================================
--- uspace/srv/hid/console/gfx/cons_kernel.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,23 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúúúúúúúúúúûûûûûûûûûûûûûûûûûûüüüþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýùùùøøøõõõêêêèèèèèèéééêêêëëëìììíííîîîîîîðððøøøúúúûûûþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷÷÷ñññáááÞÞÞÞÞÞÜÜÜÞÞÞßßßáááãããäääåååæææçççèèèéééëëëêêêììì÷÷÷úúúþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýõõõîîî×××ÒÒÒÏÏÏÑÑÑÒÒÒÕÕÕ×××ÚÚÚÜÜÜÞÞÞàààâââãããääääääååååååääääääåååèèèõõõùùùýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÏÏÏÇÇÇÃÃÃÃÃÃÅÅÅÈÈÈËËËÎÎÎÑÑÑÕÕÕØØØÛÛÛÝÝÝßßßàààáááââââââââââââáááßßßÞÞÞßßßâââôôôýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüìììÇÇÇ¸¸¸···¸¸¸»»»¾¾¾ÂÂÂÆÆÆÊÊÊÎÎÎÒÒÒÖÖÖÙÙÙÜÜÜÞÞÞàààáááââââââââââââàààßßßÜÜÜÙÙÙ×××ÝÝÝòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüêêêÃÃÃ±±±¯¯¯°°°²²²¶¶¶ººº¾¾¾ÃÃÃÈÈÈÍÍÍÒÒÒÖÖÖÚÚÚÝÝÝßßßáááâââãããääääääãããáááàààÝÝÝÚÚÚÖÖÖÔÔÔÚÚÚòòòýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëëëÁÁÁ­­­©©©©©©«««¯¯¯³³³¹¹¹¾¾¾ÄÄÄÊÊÊÏÏÏÔÔÔØØØÜÜÜßßßâââäääåååæææççççççæææäääâââàààÜÜÜÙÙÙÔÔÔÑÑÑØØØðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýìììÃÃÃ­­­§§§¦¦¦§§§ªªª®®®´´´ºººÁÁÁÇÇÇÍÍÍÓÓÓØØØÜÜÜàààãããæææèèèéééêêêêêêêêêêêêèèèæææäääàààÝÝÝØØØÓÓÓÏÏÏ×××ðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýíííÇÇÇ±±±©©©¦¦¦¦¦¦¨¨¨¬¬¬±±±···¾¾¾ÅÅÅÌÌÌÒÒÒØØØÝÝÝâââåååèèèêêêìììíííîîîîîîîîîîîîìììëëëèèèæææâââÞÞÞØØØÓÓÓÎÎÎÕÕÕðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööÏÏÏ¸¸¸¯¯¯©©©§§§¨¨¨«««°°°¶¶¶½½½ÄÄÄËËËÒÒÒÙÙÙÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòòòòñññïïïíííëëëçççãããßßßÙÙÙÓÓÓÎÎÎ×××÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýîîîÇÇÇ···°°°«««ªªª¬¬¬°°°¶¶¶½½½ÄÄÄÌÌÌÓÓÓÙÙÙßßßåååéééìììïïïñññóóóôôôõõõõõõööööööõõõõõõóóóòòòïïïíííéééåååàààÚÚÚÔÔÔÔÔÔðððýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ØØØÂÂÂ¸¸¸²²²¯¯¯®®®±±±¶¶¶¼¼¼ÄÄÄËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøùùùùùùøøøøøø÷÷÷õõõôôôñññïïïëëëçççáááÛÛÛÕÕÕÜÜÜøøøþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýòòòÒÒÒÃÃÃ»»»µµµ³³³´´´···½½½ÄÄÄËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúûûûûûûûûûûûûúúúúúúùùù÷÷÷öööóóóðððìììèèèâââÜÜÜÛÛÛóóóýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿùùùààà···yyyEEE777¹¹¹ººº¾¾¾ÄÄÄÌÌÌÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûüüüüüüüüüýýýýýýüüüüüüûûûûûûúúúøøø÷÷÷ôôôñññíííèèèãããÞÞÞãããùùùþþþÿÿÿÿÿÿÿÿÿÿÿÿøøøÝÝÝºººccc
-
-
-¾¾¾ÁÁÁÅÅÅËËËÓÓÓÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûüüüüüüýýýýýýýýýþþþþþþýýýýýýýýýüüüüüüûûûùùùøøøõõõòòòîîîéééääääääùùùþþþÿÿÿÿÿÿÿÿÿþþþõõõÞÞÞÒÒÒÅÅÅ
-
-
-ÄÄÄÇÇÇÌÌÌÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûúúúøøøõõõòòòîîîêêêééé÷÷÷þþþþþþÿÿÿÿÿÿûûûéééÜÜÜÕÕÕÍÍÍÊÊÊÍÍÍÒÒÒÙÙÙßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþýýýýýýûûûúúúøøøöööóóóïïïìììîîîûûûþþþÿÿÿÿÿÿúúúèèèÝÝÝ×××ÑÑÑÏÏÏÆÆÆDDDZZZáááôôô¯¯¯666MMM666VVVäääþþþþþþ···999GGG???KKKÔÔÔÿÿÿ'''ÐÐÐZZZªªªùùùöööôôôððððððûûûþþþÿÿÿÿÿÿúúúéééßßßÙÙÙÔÔÔ   ÔÔÔ×××^^^eeeâââîîîóóó¸¸¸üüüööö666þþþÂÂÂÿÿÿþþþXXXâââþþþÆÆÆ
-
-
-ùùùííí			úúúùùù÷÷÷ôôôôôôüüüþþþÿÿÿÿÿÿûûûêêêáááÜÜÜ×××!!!ÕÕÕSSS^^^çççìììñññõõõ???ñññüüüýýýCCC   ÿÿÿEEEñññÿÿÿÿÿÿÊÊÊqqqÿÿÿþþþ$$$ÿÿÿþþþþþþ%%%üüüûûûùùùøøø÷÷÷ýýýþþþÿÿÿÿÿÿûûûëëëãããÞÞÞÚÚÚNNNÙÙÙïïïóóó÷÷÷   üüüýýýþþþûûûúúúÿÿÿ
-
-
-ÿÿÿÿÿÿÿÿÿôôô333ÿÿÿÿÿÿ'''ÿÿÿÿÿÿþþþ'''ýýýüüüûûûúúúúúúýýýþþþÿÿÿÿÿÿûûûëëëäääàààÝÝÝ
-
-
-²²²¨¨¨UUUñññõõõøøø			ýýýþþþþþþþþþÿÿÿÿÿÿ			   ÿÿÿÿÿÿÿÿÿùùù111ÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''ýýýýýýüüüüüüûûûþþþþþþÿÿÿÿÿÿûûûìììåååâââßßß"""âââæææ___¨¨¨öööùùù>>>èèèþþþþþþÿÿÿöööÿÿÿ>>>ôôôÿÿÿÿÿÿÔÔÔgggÿÿÿÿÿÿ'''ÿÿÿÿÿÿÿÿÿ'''þþþþþþýýýýýýýýýþþþþþþÿÿÿÿÿÿûûûíííæææãããÖÖÖãããèèèßßßÖÖÖúúú½½½___ûûûÿÿÿîîîUUUôôô¾¾¾ÿÿÿþþþhhhÜÜÜÿÿÿôôôÿÿÿÿÿÿÿÿÿ
-
-
-õõõþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûíííççç···BBBUUUÎÎÎüüü»»»:::///^^^jjjâââÿÿÿÿÿÿ¾¾¾>>>KKKEEEJJJÓÓÓÿÿÿÍÍÍKKKrrrÿÿÿqqqNNNÍÍÍþþþþþþþþþþþþþþþÿÿÿÿÿÿûûûîîîçççäääââââââãããæææêêêîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüðððèèèäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøêêêäääââââââäääæææêêêîîîòòòöööùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúêêêäääââââââãããæææéééîîîòòòõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûíííäääáááàààáááäääèèèìììñññõõõøøøúúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþöööåååßßßÞÞÞßßßâââæææëëëïïïóóó÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúèèèÞÞÞÜÜÜÝÝÝàààäääèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþõõõßßßÙÙÙÚÚÚÜÜÜàààæææëëëðððôôô÷÷÷úúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþøøøâââ×××ÖÖÖÙÙÙÝÝÝâââèèèíííòòòöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýôôôÝÝÝÓÓÓÔÔÔØØØÞÞÞãããéééïïïóóó÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýòòòÚÚÚÐÐÐÓÓÓØØØßßßåååëëëðððôôôøøøúúúûûûýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññØØØÏÏÏÓÓÓÙÙÙàààçççìììñññõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüñññ×××ÎÎÎÓÓÓÚÚÚáááèèèíííòòòõõõøøøúúúüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÕÕÕÎÎÎÓÓÓÛÛÛâââèèèîîîòòòöööùùùûûûüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüðððÖÖÖÔÔÔÕÕÕÛÛÛãããéééîîîóóóöööùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýüüüýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüöööðððÜÜÜÛÛÛÞÞÞãããêêêïïïôôô÷÷÷ùùùûûûüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþýýýýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþüüü÷÷÷òòòãããäääéééìììðððôôô÷÷÷úúúüüüýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþýýýùùùùùù÷÷÷îîîðððôôô÷÷÷ùùùûûûýýýþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþýýýûûûûûûüüüüüüýýýýýýþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/cons_selected.ppm
===================================================================
--- uspace/srv/hid/console/gfx/cons_selected.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,29 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-48 48
-255
-ýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûû÷÷÷ïïïæææÝÝÝ×××ÓÓÓÓÓÓ×××ÝÝÝæææïïï÷÷÷ûûûüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûôôôåååÓÓÓÂÂÂ©©©tttaaaVVVVVVaaattt©©©ÁÁÁÒÒÒåååôôôûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûðððÙÙÙººº]]]LLL___zzz¬¬¬¸¸¸¹¹¹¯¯¯eee```]]]ºººÙÙÙðððûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüôôôÛÛÛ¬¬¬oooFFFfff   ³³³½½½ÈÈÈÒÒÒÛÛÛàààáááÞÞÞØØØÑÑÑÈÈÈÀÀÀ­­­tttdddnnn¬¬¬ÚÚÚôôôüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúèèèºººxxx@@@jjj···ËËËÑÑÑÔÔÔ×××ÚÚÚÜÜÜÞÞÞßßßáááâââââââââáááÝÝÝËËË²²²~~~kkkwww¹¹¹èèèúúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüøøøÜÜÜ555NNN¯¯¯ÀÀÀÅÅÅÉÉÉÌÌÌÏÏÏÓÓÓ×××ÙÙÙÜÜÜÞÞÞßßßàààááááááàààßßßÞÞÞÚÚÚÊÊÊªªªggggggÛÛÛ÷÷÷üüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüöööÐÐÐ
-
-
-333www²²²¸¸¸¼¼¼ÀÀÀÅÅÅÉÉÉÍÍÍÑÑÑÔÔÔØØØÛÛÛÝÝÝßßßàààáááááááááàààßßßÜÜÜÚÚÚÓÓÓ½½½uuu
-
-
-ÏÏÏõõõüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüöööËËËxxx000{{{¥¥¥¬¬¬°°°³³³¸¸¸½½½ÂÂÂÇÇÇÌÌÌÑÑÑÕÕÕØØØÜÜÜÞÞÞàààáááâââãããâââáááàààÞÞÞÜÜÜ×××ÔÔÔÉÉÉ{{{xxxËËËõõõüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýøøøÐÐÐxxx///{{{   ¦¦¦¨¨¨¬¬¬²²²···½½½ÃÃÃÈÈÈÎÎÎÓÓÓ×××ÛÛÛÞÞÞáááãããååååååæææååååååãããáááÞÞÞÛÛÛÖÖÖÒÒÒÈÈÈ}}}xxxÐÐÐ÷÷÷üüüýýýýýýýýýýýýýýýýýýýýýýýýúúúÛÛÛ
-
-
-000{{{£££¤¤¤¨¨¨­­­²²²¹¹¹¿¿¿ÆÆÆÌÌÌÒÒÒ×××ÜÜÜàààãããåååçççéééêêêêêêêêêéééçççåååãããàààÜÜÜ×××ÑÑÑÆÆÆ{{{
-
-
-ÛÛÛúúúüüüýýýýýýýýýýýýýýýýýýüüüèèè333{{{   ££££££¦¦¦ªªª¯¯¯¶¶¶½½½ÄÄÄËËËÒÒÒ×××ÝÝÝáááåååèèèêêêìììíííîîîîîîîîîíííìììêêêèèèåååáááÝÝÝØØØÑÑÑÅÅÅuuuèèèûûûüüüýýýýýýýýýýýýýýýôôôººº555www¥¥¥¦¦¦¤¤¤¦¦¦©©©®®®´´´¼¼¼ÃÃÃËËËÒÒÒØØØÞÞÞãããçççêêêíííïïïðððñññòòòòòòòòòñññðððïïïíííêêêçççãããÞÞÞØØØÑÑÑÃÃÃgggºººôôôüüüýýýýýýýýýýýýûûûÚÚÚwwwNNN­­­¨¨¨¨¨¨ªªª®®®´´´»»»ÃÃÃËËËÒÒÒÙÙÙßßßäääéééìììïïïñññóóóôôôõõõõõõõõõõõõõõõôôôóóóñññïïïìììéééäääßßßÙÙÙÑÑÑµµµwwwÚÚÚúúúüüüýýýýýýýýýñññ¬¬¬@@@²²²¯¯¯¬¬¬­­­¯¯¯´´´»»»ÃÃÃËËËÓÓÓÚÚÚàààæææëëëîîîñññóóóõõõööö÷÷÷øøøøøøøøøøøøøøø÷÷÷öööõõõóóóñññîîîëëëæææáááÙÙÙÎÎÎjjj¬¬¬ðððüüüýýýýýýûûûÙÙÙooojjj¯¯¯¸¸¸³³³²²²²²²¶¶¶¼¼¼ÃÃÃËËËÓÓÓÚÚÚáááçççìììðððóóóõõõ÷÷÷øøøùùùúúúúúúúúúúúúúúúúúúúúúùùùøøø÷÷÷õõõóóóðððìììçççâââÚÚÚÃÃÃoooÙÙÙûûûüüüýýýõõõºººFFFÀÀÀ¼¼¼¸¸¸···¹¹¹½½½ÃÃÃËËËÓÓÓÚÚÚáááèèèíííñññôôôöööøøøùùùúúúûûûûûûûûûüüüüüüüüüûûûûûûûûûúúúùùùøøøöööôôôñññíííèèèâââÙÙÙ¦¦¦eeeºººôôôüüüüüüåååeee¶¶¶ÆÆÆÀÀÀ½½½½½½¿¿¿ÄÄÄËËËÒÒÒÚÚÚáááèèèíííñññôôô÷÷÷ùùùúúúûûûûûûüüüüüüýýýýýýýýýýýýýýýüüüüüüûûûûûûúúúùùù÷÷÷õõõñññîîîéééâââÆÆÆåååüüüüüüÓÓÓ]]]ËËËÉÉÉÅÅÅÂÂÂÃÃÃÆÆÆËËËÒÒÒÙÙÙàààçççíííñññõõõ÷÷÷ùùùúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúùùù÷÷÷õõõòòòîîîéééßßßÃÃÃ]]]ÒÒÒûûû÷÷÷ÂÂÂKKK³³³ÒÒÒÌÌÌÉÉÉÇÇÇÈÈÈÌÌÌÒÒÒØØØßßßæææìììñññôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûùùùøøøõõõòòòïïïééé¿¿¿___ÂÂÂ÷÷÷ïïïªªª^^^½½½ÕÕÕÏÏÏÍÍÍÌÌÌÎÎÎÒÒÒ×××ÞÞÞäääëëëðððôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúøøøöööóóóïïïÍÍÍvvvªªªïïïæææzzzÈÈÈ×××ÓÓÓÑÑÑÐÐÐÓÓÓ×××ÝÝÝãããéééîîîóóóöööùùùúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúøøøöööôôôÜÜÜæææÞÞÞtttÓÓÓÙÙÙÖÖÖÔÔÔÕÕÕ×××ÜÜÜáááçççìììñññõõõøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúùùù÷÷÷èèè­­­tttÞÞÞ×××aaa«««ÚÚÚÜÜÜÙÙÙØØØØØØÛÛÛßßßåååêêêïïïóóó÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûúúúùùùòòòÁÁÁaaa×××ÔÔÔWWW¸¸¸àààÞÞÞÜÜÜÚÚÚÜÜÜÞÞÞãããèèèíííñññõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûûûûøøøÍÍÍWWWÔÔÔÔÔÔWWW¹¹¹áááßßßÞÞÞÝÝÝÞÞÞáááåååêêêïïïóóóöööùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüùùùÍÍÍWWWÔÔÔ×××aaa¯¯¯ßßßáááßßßßßßàààãããçççìììðððôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýý÷÷÷ÂÂÂaaa×××ÞÞÞtttÙÙÙáááààààààáááäääèèèíííñññõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýððð­­­tttÞÞÞæææÐÐÐâââááááááâââåååéééíííòòòõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýèèèæææïïï©©©eeeÇÇÇâââááááááãããæææéééîîîòòòõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýßßßvvv©©©ïïï÷÷÷ÁÁÁ___¿¿¿âââàààáááâââåååéééíííòòòõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüÖÖÖ___ÁÁÁöööüüüÒÒÒ]]]­­­ÜÜÜßßßàààáááäääèèèíííñññõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýøøøÄÄÄ]]]ÒÒÒûûûüüüåååtttËËËÞÞÞßßßàààãããçççìììðððôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýæææåååüüüüüüôôô¹¹¹eee²²²ÚÚÚÜÜÜÞÞÞáááåååêêêïïïóóóöööùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúÐÐÐeee¹¹¹óóóüüüýýýûûûÙÙÙooo~~~ËËËÙÙÙÜÜÜÞÞÞãããèèèíííñññõõõøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüêêêoooÙÙÙûûûüüüýýýüüüððð«««jjjªªªÔÔÔ×××ÛÛÛßßßåååêêêïïïóóó÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷ÎÎÎjjj«««ïïïüüüüüüýýýýýýûûûÚÚÚwwwfff¾¾¾ÔÔÔÖÖÖÜÜÜáááçççìììñññõõõøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúäääwwwÚÚÚúúúüüüýýýýýýýýýüüüôôôºººgggÈÈÈÒÒÒ×××ÝÝÝãããéééîîîóóóöööùùùúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûóóóÀÀÀgggºººóóóüüüüüüýýýýýýýýýýýýüüüèèèuuuÈÈÈÑÑÑ×××ÞÞÞäääëëëðððôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûôôôÌÌÌuuuçççûûûüüüýýýýýýýýýýýýýýýüüüùùùÛÛÛ
-
-
-{{{ÆÆÆÑÑÑØØØßßßæææìììñññõõõ÷÷÷ùùùûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûõõõÐÐÐ{{{
-
-
-ÛÛÛùùùüüüüüüýýýýýýýýýýýýýýýýýýüüü÷÷÷ÏÏÏxxx}}}ÅÅÅÑÑÑÙÙÙáááçççíííñññõõõøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûôôôÐÐÐ}}}xxxÏÏÏ÷÷÷üüüüüüýýýýýýýýýýýýýýýýýýýýýýýýüüüõõõËËËxxx{{{ÄÄÄÑÑÑÙÙÙâââèèèîîîòòòõõõøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúóóóÌÌÌ{{{xxxËËËõõõüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüõõõÐÐÐ
-
-
-uuuµµµÏÏÏÚÚÚâââéééîîîòòòöööøøøúúúûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷äääÁÁÁuuu
-
-
-ÏÏÏõõõûûûüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüü÷÷÷ÛÛÛgggÂÂÂÙÙÙâââéééïïïóóóöööøøøúúúûûûýýýýýýýýýýýýýýýýýýýýýýýýúúúêêêÎÎÎgggÚÚÚöööûûûüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüùùùèèèºººxxxkkk¥¥¥ÅÅÅßßßéééïïïôôô÷÷÷ùùùûûûüüüýýýýýýýýýýýýüüüøøøæææÏÏÏkkkwww¹¹¹çççùùùüüüüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûóóóÚÚÚ¬¬¬ooodddÄÄÄ½½½ÍÍÍÛÛÛèèèòòòøøøùùù÷÷÷ðððçççÞÞÞÖÖÖÄÄÄdddnnn«««ÙÙÙóóóûûûüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüúúúðððÙÙÙººº]]]```vvv­­­ÂÂÂÍÍÍÍÍÍÂÂÂ­­­vvv```]]]ºººÙÙÙðððúúúüüüüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüûûûôôôåååÓÓÓÂÂÂ©©©tttaaaVVVVVVaaattt©©©ÁÁÁÒÒÒåååôôôúúúüüüüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüüüüûûûöööîîîæææÝÝÝ×××ÓÓÓÓÓÓ×××ÝÝÝåååîîîöööûûûûûûüüüüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýý
Index: pace/srv/hid/console/gfx/helenos.ppm
===================================================================
--- uspace/srv/hid/console/gfx/helenos.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,13 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-64 60
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýøùùñóõîñóïòóö÷÷ûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþþøùùíñóäêîßèìÞæëÝåêÝåêÞåêäèêðññûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþþøùùïòôåëïåìðäêîÛàãØÜßÛàâæëîåëîÝåêÛäèÛáåèééúúúþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþþùùúïóôæìïåìðåëî×Üß½ÄÆµ¼¾ÈÍÏÍÒÓÊÏÑ·¾ÀÃÊÌãçêÝåéÚãçØÛÞçèèûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþúúúðôõèîñäìðçíðÙÞáÁÇÉ´¼¾ÊÏÑèëì÷ùù÷ùúôöøòõ÷ñóôÖÚÜ¹ÀÂÞäæÜâåØÝâÔÕ×ñòòþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûûûòõöéîñåíñæíñÛáäÄËÎµ¼¾ÈÍÏäæçöøøøúúõ÷ùòõ÷ðóõðóõðóõïòôïòôÒ×Ù¿ÅÈàåéØßäÎÒÕáááûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûûûóö÷êïòæíñçîñÞãåÇÎÐµ½¿ÅËÍàãäö÷÷ùúûöøùóöøòõ÷ñôöðóõðóõïòôïòôïòôîñóëïñ»ÂÅÛßâÚàåÓÙÞÑÒÓôôôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûüüôöøëðóçîñèïòßåèËÑÓ¶¾ÀÃÉËÜàáóôõøúû÷ùúô÷øóöøòõ÷òõ÷ñôöðóõðóõïòôïòôîñóîñóìðòìïòÔÙÛÄËÍÞäè×ÞãËÎÐæççüýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþûüüô÷øíñôèîòéïóáçêÍÔÖ¹ÁÃÂÈÊØÜÝñòóøúú÷úûõ÷ùôöøóöøòõ÷òõ÷ñôöñôöðóõðóõïòôîñóîñóíñóìðòëïñëîñåéìºÁÃÞãå×ÞãÐÕÙÕÕÖ÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþüüüõøùîòõèïóéðôãéìÑ×Ù»ÂÄÀÆÈÔØÙïðñøùúøúûõøúô÷ùôöøóöøóöøòõ÷òõ÷ñôöðóõðóõïòôïòôîñóîñóìðòìïòëîñëîñêíðéíðÉÏÒÌÒÓÛàäÓÙÞÊÌÏìííþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷ùùðóõèïóéðôåêîÔÚÝ½ÄÇ¿ÆÇÑÖ×ëíîøùùúûüöùúô÷ùô÷ùô÷ùôöøóöøòõ÷òõ÷òõ÷ñôöðóõðóõïòôîñóîñóíñóìðòëïñëîñêîñéíðèìïèìïÝâä»ÂÄÞâåÓÚßËÐÓÛÛÛúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýý÷ùúðôöéðóêðôæìï×ÝßÁÈË¾ÅÇÎÓÔèëëöøøúüü÷úûöùúõ÷ùô÷ùô÷ùô÷ùôöøòõ÷òõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóíñóìðòìïòëîñëîñêíðéíðèìïèìïçëîæêí¿ÆÈÕÚÜÖÜáÐ×ÛÍÏÐððñþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþùúúñõ÷êñôêñõçíñÚàâÃÊÌ¾ÅÆÊÏÑæèéö÷øûüüøúûöùúöùúõøùô÷ùô÷ùô÷ùôöøóöøòõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóîñóíðòìðòìïòëîñëîñêíðéíðèìïçëîçëîæêíåêíÕÛÞ¿ÆÇÝâåÓÙÞÉÍÏâââûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþùûûíóöéñôëñôßäçÆÍÏ¾ÅÇÇÌÎâåæõö÷ûüýùûü÷ùúöùúöùúöùúõøùô÷ùô÷ùô÷ùôöøóöøòõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóÛÞà±²´´µ¶ÛÝàëîñêîñéíðèìïèìïçëîçëîæêíåéìäéìáæèºÁÃÙÝßÓÙÝÍÓÖÑÒÓôõõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùúúèðôêñõíñóÃÉËÂÈÊßâãóôõûüýúûýøúü÷ùûöùúöùúöùúõøùô÷ùô÷ùô÷ùôöøôöøòõ÷òõ÷òõ÷òõ÷ñôöïòôïòôîñóîñóÜÞá~~ooptsuÛÞáéíðèìïèìïçëîæêíåêíäéìäéëãèêãèêËÒÔÅËÍØÞáÏÖÚÈËÍèèèýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüëðôçðôóöø½ÄÆ×ÚÜúûûûüýøúüøúü÷úûöùúöùúöùúöùúõ÷ùô÷ùô÷ùôöøôöøóöøòõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóîñóíñó¯±³poq{{|º»½çëîçëîçëîæêíåéìäéìãèëãèêâçéáæèÛàâ¸¿ÁÛßâÐ×ÚËÐÒ×××÷øøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïððäíñðöøÔÙÛÍÒÓûüýùûüøúüøúü÷úûöùúöùúöùúõøùõ÷ùô÷ùô÷ùôöøôöøóöøòõ÷òõ÷ñôöðóõïòôïòôïòôîñóîñóíðòìðò«¬®yyz¢¢£«ª«­®¯áåèçëîæêíäéìäèëãèêâçéâçéáæèàåçßäçÁÈÊÌÒÔÓÙÜÎÓÖÊÌÍíîîþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþþÝàáâëð÷úûºÁÃðòóùûüøúüøúü÷ùûöùúöùúöùúõøùô÷ùô÷ùôöøôöøôöøòõ÷òõ÷òõ÷ñôöðóõïòôïòôîñóîñóîñóìðòìðòëîñÑÓÕ³³´½¼½µµ¶ÑÔ×æêíåéìãèêãèêâçéâçéàåçßäçÞãæÝâåÓØÛºÀÃÙÞáÎÔØÆÊÍÝÝÞúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüÍÑÒáêïøúüºÁÃ÷øùøúüøúü÷ùûöùúöùúöùúõ÷ùô÷ùô÷ùôöøôöøóöøòõ÷òõ÷ëîðæéëîñóïòôïòôîñóîñóíñóìðòìïòëîñêîñéìï  ¡¸·¹ÁÀÂ¾½¿ÀÁÂâæéãèêâçéâçéáæèàåçßäçÞãæÝâåÜáäÚßãºÁÄÔÙÛÎÕØËÐÔÍÎÏòòòþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûû¶¸¹Ýåêóöù»ÂÄðòò÷úûöùúöùúöùúõøùõ÷ùô÷ùôöøôöøôöøóöøòõ÷ñôöÎÐÒ°±³èëíîñóîñóíñóìðòìïòëîñêíðéíðèìïÂÄÆ³³´À¿ÁÀÀÁ¹¹ºÙÝÞâçéâçéàåçßäçßäçÝâåÜáäÛàäÛàäÚßãËÑÔ½ÄÆ×ÜßÌÓ×ÆÉËäääüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûº»»½ÄÈëñôÏÔÖÕÙÛöùúöùúöùúõøùô÷ùô÷ùôöøôöøôöøóõ÷òõ÷ñôößâä~~qpqxxz¹º»îñóìðòìðòëîñëîñêíðéíðèìïèìïàäç««¬½¼¾ÂÁÃ½¼¾ÇÈÉàåçàåçßäçÞãæÝâåÜáäÛàäÚßãÚßãÙÞâÕÚÞ¶¾ÀÕÚÞËÒÖÈÎÑÒÒÒöööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýýÙÙÙàéíèíï»ÁÃóö÷öùúõøùô÷ùôöøôöøôöøóöøòõ÷òõ÷ñôöðóõÇÉÊqpq~~~£¤¥æêëìïòëîñêíðéíðèìïèìïçëîçëîæêí±³µ¡¡¢··¸ÁÀÂÀ¿Áºº¼ÚßáßäçÞãæÜáåÛàäÛàäÚßãÚÞâØÝáØÝáÖÛàÁÈËÇÌÎÑ×ÚÊÐÔÇÉËéêêýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþéééÌÔØíóõ¿ÆÈâæèõ÷ùô÷ùôöøôöøôöøóõ÷òõ÷ñôöñôöðóõïòôÔÖØ|}}¦¥¦³²³°°±ÒÕ×ëîñêíðéíðèìïèìïçëîæêíæêíåéìÍÐÓ°¯±¿¾ÀÂÁÃ»º»ÌÐÒÝâåÜáäÛàäÚßãÚßãÙÞâØÝá×ÜàÖÛàÕÚßÏÕÙ¶½¿ØÜÞÊÐÔÆÊÌØØÙùùùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôõõº»¼¢§ª¶¼¾¡¡¤¥ðòôôöøôöøóöøòõ÷òõ÷ñôöñôöðóõïòôïòôèëí²±³¿¾À½¼¾ÀÀÂéìïèìïèìïçëîçëîæêíæêíÞáäÂÅÇ¨¨©»»½ÂÁÃ¾¾À¾¿ÁÙÞáÛàäÚßãÚÞâÙÝáØÝáÖÛàÖÛàÕÚÞÕÚÝÓØÜ»ÁÄÎÓÕÌÒÖÉÎÒÉÊËïïïþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüüàààehi444444ÇÇÈôöøóõ÷òõ÷ñôöñôöñôöðóõïòôïòôîñóíñóÁÂÄ²±³À¿ÁÁÀÂ»º¼ÜßáçëîçëîæêíäèëØÛÞ¬®°onowxy¦¦§º¹ºÂÁÃÁÀÂ¸¸¹ÐÔ×ÚßãÚÞâØÝá×ÜàÖÛàÕÚßÕÚÞÔÙÝÓØÛÒ×ÚÊÏÒ·¾ÀÖÚÝÊÐÔÅÈËßßßûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþïïïªª¬|??@222||}ðòôòõ÷ñôöñôöðóõðóõïòôîñóîñóíðòìðòàâå««¬½¼¾ÁÁÂ¼¼½ÈÊÌæêíâåèÉËÍuuvppqvvw}~~®®¯¼¼½ÂÁÃÂÁÃ½½¾ÂÄÆÙÝá×ÜáÖÛàÖÛàÕÚßÔÙÝÔÙÝÓØÛÒ×ÚÑÖÙÏÕØ¶½ÀÔÙÛÊÐÔÈÍÑÌÍÎóóóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùùùÐÐÐ
-XYY333AAAÜßàñôöñôöðóõðóõïòôîñóíñóìðòìïòëîñêíð´µ·¡¡¢¸¸¹ÁÀÂÀÀÁº¹»ÅÈÊsstrrsyyz¥¥¦±°±º¹»À¿ÁÃÂÄÃÂÄÀ¿Á¹¹»ÒÖÚÖÛàÖÛßÕÚÞÔÙÝÓØÜÒ×ÚÒ×ÚÑÖÙÐÖÙÐÖÙÃÉÌ¾ÄÆÓØÛÊÐÔÅÈÊæææüýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýééérvx999222 ¡¢ñôöðóõïòôîñóîñóíðòìðòìïñëîñêíðéíðÓÖØ°°±¾¾¿ÁÀÂ»º»¨¨©
-
- ªª«³²´º¹»ÂÁÃÊÌÎÂÁÃÂÁÃÂÁÃÂÁÃ»»¼ÆÈËÕÚßÔÙÝÔÙÝÓØÛÒ×ÚÒ×ÚÐÖÙÐÖÙÏÕØÏÕØËÑÕ³»½ÖÙÜÊÐÔÇÍÐÓÓÓ÷÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôôô»¼½JJK222]]]çéëïòôîñóíðòìðòìïñëîñêîðêíðéíðèìïãæé¥¦§¦¦§»º¼ÂÁÃ¿¾Àµ´¶§§¨  ¢¥¥¥®®¯¶¶¸¼¼½ÆÇÉÒÕ×ÚÞâÚßãÃÄÆ¼»½À¿ÁÂÁÃ¿¾À¼¼¾Ò×ÚÔÙÜÓØÛÒ×ÚÑ×ÚÐÖÙÐÖÙÏÕØÏÔØÍÓ×ÍÓ×ºÂÄÈÎÐÍÓ×ÉÏÓÆÈÉìììýþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüüàààfij555444ÆÆÇîñóíðòìðòìïñëîñêíðêíðéìïèìïçëîçëîÄÇÈ´´µÀ¿ÁÂÁÃ¾½¿¹¸º·¶¸º¹ºÀÀÁÌÎÐØÜßÛàäÚßãÚßãÚÞâÉÌÏ®®¯¹¸ºÀÀÁÁÀÂ¹¹ºÉÍÏÒ×ÚÒ×ÚÑÖÙÐÖÙÐÖÙÏÕØÏÔØÍÓ×ÍÓ×ÌÒÖÈÎÒ³»½×ÛÞÊÐÔÅÉËÚÛÛúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþïïï©«¬|AAB222{||ìïðìðòìîñëîñêíðêíðèìïèìïçëîæêíæêíÜàâ««¬½¼¾ÂÁÃÂÁÃÂÁÃÆÇÉÓÖØÜàãÝâåÛàäÚßãÚÞâÚÞâØÝáÔØÜ¡¡£¬¬­¼¼½ÁÀÂ½¼¾¾¿ÁÑÖÙÐÖÙÐÖÙÏÕØÏÕØÎÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕµ½ÀÐÔÖËÐÔÉÏÒÉÊËðññþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øøÍÍÎY[\333CCCÙÛÜëîñêîðêíðéìïèìïçëîçëîæêíåéìåéìãèê²´µ  ¡·¶·ÁÁÂÃÂÄÅÄÆÛßâÝâåÜáäÚßãÚßãÚÞâÙÝá×ÜàÖÛàÖÛà°²´ ·¶·ÁÀÂÀÀÁ¹¹»ÌÑÓÐÖÙÏÕØÏÔØÎÓ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÃÊÍ·¾ÀÕÚÝÊÐÔÄÇÉáááüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýççèsxy:::222 ¡¢ìïòêíðéìïèìïçëîçëîæêíåéìåéìäèëâçéÑÕÖ¯¯°¾¾¿ÃÂÄÂÁÃÐÓÖÛàäÚßãÚÞâÚÞâØÝá×ÜàÖÛàÖÛßÔÙÝÇËÎ®­®¾½¾ÂÁÃ»»¼ÃÇÉÏÕØÏÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÉÏÓ³º½ÔØÛÊÐÔÈÎÑÍÎÎôôõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóôô¹ººLMN222^^^ãåçèìïèìïçëîæêíæêíåéìäèëãèêâçéâçéÞãä¥§¨¥¥¦º¹»ÂÁÃÂÁÃÁÁÄÙÞáÚÞâÙÝáØÝáÖÛàÖÛàÕÚÞÔÙÝÓØÛÒ×Ú¢£¤¤¤¥¹¹ºÁÀÂ¿¾ÀÆÈËÎÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔ¾ÅÇÀÆÉÐÕÙÊÐÔÅÈÉçèèýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûûÝÝÝhjl666666ÃÄÅèìïçëîæêíåéìåéìäèëãçêâçéáæèáæèàåçÂÅÇ³³´À¿ÁÂÁÃ¼»½ÎÒÕÙÝá×ÜàÖÛàÕÚßÕÚÞÓØÜÓØÛÒ×ÚÒ×ÚÀÃÆ²±²À¿ÁÃÃÅÌÐÔÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÇÎÑ±¸»ÖÚÝÊÐÔÆËÏÔÔÔøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþîîï§¨ª{BBC222|}}éìîæêíåéìäèëãèêâçéâçéáæèàåèßäçÞãæÖÚÝªª«¼¼½ÂÁÃ¾½¿ÀÁÃ×ÜàÖÛàÕÚÞÔÙÝÓØÛÓØÛÒ×ÚÒ×ÚÑÖÙÐÕØÃÈÊ¼¾ÀÅÇÉÌÐÔÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÈÏÒ¸¾Á¾ÄÇËÑÕÊÐÔ¹ÀÃÌÑÓÌÒÖÊÏÓÆÇÈíîîþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øøËËË[]^344EEEÖØÙåéìäèëâçéâçéáæèáæèàåçßäæÝâåÝâåÛàä³µ·  ¶¶·ÁÀÂÀÀÁ¸¸ºÑÕÙÕÚÞÔÙÜÓØÛÓØÛÒ×ÚÒ×ÚÐÖÙÐÖÙÏÕØÏÕØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔ£ª¬{ÐÔ×ÊÐÔÄÊÎºÁÃÚÞáÊÐÔÄÈÊÜÜÜúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýçççswy;;;222 ¡¢æêíâçéáæèáæèàåèßäçÞãæÝâåÜáäÛàäÚßãÍÐÓ®®¯¾¾¿ÂÁÃ»»¼ÄÆÉÓØÜÓØÛÒ×ÚÒ×ÚÑ×ÚÐÖÙÐÖÙÏÕØÏÔØÎÓ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔ®³µ¤«­ÊÐÒâäæÊÐÔÇÍÑ¹ÀÂäæéÊÐÔÉÏÒÉÉÊóóóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóôô¸¹¹MNO222___áãåáæèáæèàåçßäçÞãæÝâåÜáäÛàäÚßãÚÞâ×ÚÞ¥¦¨¤¤¥º¹»ÁÀÂ¿¾À¾¿ÁÓØÛÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÏÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÌÒÖàãåèëìÑÖÚÊÐÔÂÈË¿ÅÇæèêÊÐÔÉÏÓ¼¾¿êêêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúûûÛÛÛhlm666666½¾¿âçéàåçßäæÝâåÜáäÜáäÚßãÚÞâÙÝáÙÝá×Üà¿ÂÅ³²³À¿ÁÂÁÃÆÈÊÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔËÐÔËÑÕÊÐÔÉÏÓ³»½ÙÝÞÜàãÊÐÔÉÏÓ³´µäääÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþîîî§¨©{DEE222wxxäèêÞãæÝâåÜáäÛàäÚßãÚÞâÙÝáØÜáÖÛàÕÚßÒ×Û±³µ¬«­¼¼½ÆÆÈÐÔ×Ò×ÚÐÖÙÐÖÙÏÕØÏÔØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÈÎÒ¶¾Á½ÄÅñóôÍÓ×ÊÐÔÃÉÌ¬¬­äääÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ÊÊÊ\^_444EEEÒÔÕÝâåÜáäÛàãÚßãÙÝáÙÝá×ÜàÖÛàÕÚßÔÙÝÔÙÝÒ×ÚÌÐÒÎÒÔÑÖØÑÖÙÐÖÙÏÕØÏÕØÏÔØÍÓ×ÍÓ×ÌÒÖÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÉÏÓÃÊÎ¸ÀÃ±¹»ÇÍÏïñòØÜßÊÐÔÉÏÓ³³´éêêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýææçsxy<<<222áåèÚßãÚÞâÙÝáØÝá×ÜàÖÛßÕÚÞÔÙÝÓØÜÓØÛÓØÛÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÅËÎ»ÃÅ²º½ºÀÂÑÖ×éëìêíîÔÙÜÊÐÔÉÏÓnooÂÂÃñòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóóô¸¸¹
-OQQ222\\\ÝàâÚÞâÙÝá×ÜáÖÛàÕÚßÔÙÞÔÙÝÓØÜÓØÛÒ×ÚÒ×ÚÒ×ÚÐÖÙÐÖÙÏÕØÏÔØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÆÌÐ¾ÄÇ²º¼¸¿ÀËÐÑæèéëíîáåçÓØÛËÑÕÇÍÑ®²µxyzKKKÖÖÖøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúÚÚÚiln667777¼½¾Ûàä×ÜàÖÛßÕÚÞÔÙÝÔÙÜÓØÛÓØÛÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÏÔØÍÓ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÊÐÔÇÍÑÀÆÊµ¼¿µ¼¾ÇÌÎáäåìîïäèêÕÚÝÌÒÖÈÎÒ´º½`abAABCCD¼»¼êêêýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþîîî¥§¨zDEF333¥¥¦àãæÖÛßÔÙÞÔÙÝÓØÜÓØÛÓØÛÒ×ÚÒ×ÚÑÖÙÐÖÙÏÕØÏÕØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕËÑÕÊÐÔÊÐÔÊÐÔÊÐÔÈÎÒÁÈËµ½Àµ¼¾ÁÇÉÞáâëíîèêìØÜßÍÓ×ÉÏÓ¹¾ÂgjkHIJ;;;FGGaab¶¶·ßààøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ÈÈÉ]__\\]ÐÒÓÛßâÔÙÝÔÙÝÓØÜÓØÛÈÍÐÀÄÇÍÒÔÐÖÙÐÖÙÏÕØÏÔØÎÔ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÊÐÔÊÐÔÉÏÓÃÉÍ¸¿Â³»½½ÃÅØÜÝêìíëíîÚÞáÏÔØÊÐÓ½ÂÆ¡¥¨qstOOO===DDDZ[[www«««ÇÇÈäää÷÷÷þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýæææ}ÂÃÄÂÉËÎÓÕÖÛßÓØÛÓØÛÍÒÕ~
-¤¨ªÚÞáÏÕØÏÔØÎÓ×ÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÉÏÓÅËÏºÂÅ³»¾¹ÀÂÓ×ØèêëìîïÝáäÐÖÙÊÐÔÀÆÊ¨¬¯|UVV>>>CCDTTUppq¥¥¦»»¼ÐÐÐâââñññúúúþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóóô·¸¸ÑÕØÊÐÓºÀÂÚÞáÓØÛÒ×ÚÎÓÕ¢¥§¹ÀÂÕ×ØÝáãÏÔØÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕËÑÕÊÐÔÅÌÏ¾ÄÇ³»½·¾ÀÍÒÓåèèïðñàäæÓØÛËÑÔÃÈÌ°µ¸
-\^_CCDCDDQQQjkk
- µµ¶ËËÌÞÞÞìììöööüüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúÙÙÙ·¼¿ÎÔØ·¾ÀÔÙÜÓØÛÒ×ÚÐÖÙÙÝàçêëæéêÐÕÙÍÓ×ÍÓ×ÌÒÖÌÒÖËÑÕÈÎÒÀÇÉ´»¾´»½ÇÌÎâåæîðñäçéÔÙÜËÑÕÆÌÐ´º½cdeGGGCDDNOOddd~°°±ÆÆÇÚÚÚéééôôôûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþíîîÌÒÕÆÌÎ»ÂÄÔÙÜÐÖÙÐÖÙÏÕØÏÔØÎÓ×ÍÓ×ÍÓ×ÌÒÖÉÏÓÃÉÍ¶¾À³»½ÁÈÉÞáâïññæéë×ÜßËÑÕÇÍÑº¿ÂknoKLMDEFKLL_``yzz«««ÁÁÁÕÕÖæççòòóùúúýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ÆÇÇuwx¾ÄÈÏÔ×¹ÁÃºÂÄËÑÔÏÕØÏÔØÍÓ×ÍÓ×ËÑÕÅËÏ¸ÀÃ´»½»ÁÃÛÞßíîïëíïÚÞàÍÓ×ÈÎÒ½ÃÇ£¦qsuPQRDEEIJKZ[\uuv¦¦§½½½ÑÑÑáââïïðøøøýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýýåææ£¥ÌÒÖÎÔ×¾ÅÈ²º¼ºÁÄÁÈËÂÉÌºÁÄ³»½¸¿ÁÓ×ØëííîðñÝáãÏÔØÊÏÓÁÆÊ§¬¯x{}RTUCDEGHIUUWoop¡¡¢¸·¸ÍÍÎßààíîî÷÷÷üüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóóô²²²uxyÃÉÍÍÓÖÐÖÙÕÙÜÒ×ØÇÍÏÉÎÐ×ÚÜæéêñòóàãæÐÖÚÊÐÔÃÉÍ­²µ
-Z\]DEFEFGPPQhii²²³ÈÈÈÜÜÜëëëõööûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúúúØØØopqÈÎÑÌÒÖÍÓ×ÎÔØÖÛßÛßâÚÞáÒ×ÛÊÐÔÅËÏ¶¼¿`bdGHIGHINOPbcd}}~¬¬­ÃÃÄ××ØèèèóóóúúúþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþíîîXYZ½ÂÆÉÏÓËÑÕËÑÕÊÐÔÇÍÑ»ÀÄhklKLMGHIKLM]^_vww§§¨¾½¾ÒÓÔåååñññùùùýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øøÔÔÕ{||RTU\^_|qstQRRHIJLMNYZZqqq¢¢£¹¹¹ÏÏÐáááîîî÷÷÷üüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýïïïÅÅÅ~UWXPQROPQNOOMNNNOOWXYklm´³´ÊÊÊÝÝÝìííö÷÷üüüþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüüêëëÊÊÊ z{{jkkhhhnoo®®¯ÅÅÅÙÚÚéééóôôûûûþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüüðððÛÜÜÇÇÇ··¸²²²¶¶¶ÃÃÄÕÕÕæææòóóúúúýþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
Index: pace/srv/hid/console/gfx/nameic.ppm
===================================================================
--- uspace/srv/hid/console/gfx/nameic.ppm	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,14 +1,0 @@
-P6
-# CREATOR: The GIMP's PNM Filter Version 1.0
-100 26
-255
-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿããã»»»¤¤¤¿¿¿êêêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñññÄÄÄ¦¦¦¢¢¢ÅÅÅððñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËËË___444222222222222222666rrsÞÞÞÿÿÿÿÿÿÿÿÿññò;;;222222222222222999òòòÿÿÿÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯¯°888222222222222222222222222222AAAÈÈÈÿÿÿïïïbbb222222222222222222222222222VVWïïïÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÖÖÖ;;;222222222222222222222222222222222UUUììì222222222222222222222222222222222~~~ÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzzz222222222222222IIIeef???222222222222222NNN222222222222???hhhLLL222222222222444ççè~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöööBBB222222222222VVVëëëÿÿÿÔÔÔAAA222222222222AAA444222222222CCCàááÿÿÿñññWWW222222222333®®®~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÞÞ;;;222222222222ÿÿÿÿÿÿýýýaaa222222222222222222222222222\\\ÿÿÿÿÿÿþþþ222222222222
-
-
-~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýààà¿¿¿´´´ÀÀÀßßßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëëëÈÈÈ´´´ºººÔÔÕúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñññÇÇÇ´´´¿¿¿ÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222222222222222222GGGëëëÿÿÿÿÿÿ£££222222222222ttt~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿÿÿÿúúú°°±PPP222222222222333\\\ÑÑÑÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿÿÿÿÏÏÏggg666222222222222GHH¬¬¬ûûûÿÿÿÿÿÿâââMMMNNN¤¤¤ùùú;;;222222222222WXXËËËÿÿÿÿÿÿÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222222222222222222222uuuôôôÿÿÿòòòãããããããããäääëëë~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿôôôzz{222222222222222222222222777¼¼¼ÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿ§§§999222222222222222222222444ùùùÿÿÿÞÞÞ222222222222222222222222222555ÄÄÄÿÿÿÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222BBBHHH222222222222222YYYÇÇÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿúúú222222BBBÛÛÛãããÏÏÏ
-
-
-5552229::ãããÿÿÿÿÿÿVVV222IIIòòòÿÿÿ¶¶¶888222666ÏÏÏäääÙÙÙ  ¡EEE222555ªªªÿÿÿÞÞÞ222222CCD222KKK¨¨©ÞÞÞãããÂÃÃ]]]222222RRRúúúÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222OOOooo222222222222222222555wwwçççÿÿÿÿÿÿÿÿÿÿÿÿ~~~222222QQQhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhEEE222222«««ÿÿÿÆÆÆ666222NNNÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿþþþ­¬­222222þþþÿÿÿVVV222IIIòòòïïïLLL222999µµµþþþÿÿÿÿÿÿÿÿÿÿÿÿÖÖÖFFF222RRRîîîÞÞÞ222222222WWWìììÿÿÿÿÿÿÿÿÿÿÿÿóóóFFF222222ÕÕÕÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRÓÓÓKKK222222222222222222222===üüüÿÿÿÿÿÿ~~~222222222222222222222222222222222222222222222222222«««ûûûuuu222<<<ÆÆÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûûû__`222899óóóÿÿÿVVV222IIIòòò¬¬¬444222ýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ222555¸¸¸ÞÞÞ222222:::ÆÆÆÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ222222²²²ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRïïïÔÔÔPPP222222222222222222222333nnnùùùÿÿÿ~~~222222222222222222222222222222222222222222222222222«««æææKKK222[[[úúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§¨¨222222¾¾¾ÿÿÿVVV222IIIòòòppp222999ÝÝÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚÚÚ>>>222ÞÞÞ222222SSSúúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°°°222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRïïïÿÿÿìììzzz222222222222222222222333ÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ËËË222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊÊÊ222222ÿÿÿVVV222IIIêêêEEE222WWWðððÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêêêQQQ222]]]ÞÞÞ222222wwwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRïïïÿÿÿÿÿÿýýýÁÁÁRRR222222222222222222444ááá~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««³³³222222222222222222222222222222222222222222~~~þþþVVV222IIIÖÖÖ@@@222222222222222222222222222222222222222NNNÎÎÎ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222RRRïïïÿÿÿÿÿÿÿÿÿÿÿÿõõõ777222222222222222~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««¥¥¥222222222222222222222222222222222222222222zzzþþþVVV222IIIËËË===222222222222222222222222222222222222222MMMÌÌÌ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222BBB¤¤¤´´´´´´´´´ÚÚÚÿÿÿþþþÆÆÆ===222222222222{{{~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««¨¨¨222222tttÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏàààÿÿÿVVV222IIIÎÎÎ>>>222PPPÄÄÄÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÕÕÕÙÙÙ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÕÕÕ999222222222222±±±ÿÿÿÿÿÿÿÿÿxxx222222222222222222222222222ÿÿÿÿÿÿþþþ222222222222iii~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÁÁÁ222222|||ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿVVV222IIIáááCCC222PPPíííÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÞÞÞ;;;222222222222£££ÿÿÿÿÿÿÿÿÿmmm222222222222222222222222222ÿÿÿÿÿÿÿÿÿ£££222222222222iii~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ßßßAAA222SSSøøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÏÏÏ}}}}}}ÊÊÊÿÿÿVVV222IIIòòò___222555×××ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëëë}}}¢¢¢ÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ööö>>>222222222222tttûûûÿÿÿîîïQQQ222222222222222222222222222pqqÿÿÿÿÿÿüüü222222222222~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««øøøjij222888¸¸¸ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüüülll222222áááÿÿÿVVV222IIIòòò  ¡333222ûûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ§¨¨222222£££ÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÿÿÿiii222222222222777ÌÌÌ555222222222222\\\222222222222999ÎÎÎ¤¤¤;;;222222222333®®®~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÃÃÃ666222IIIÔÔÔÿÿÿÿÿÿÿÿÿÿÿÿøøø222222vvvþþþÿÿÿVVV222IIIòòòìììKKK222677¬¬¬ûûûÿÿÿÿÿÿÿÿÿýýýºººAAA222OOOçççÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÿÿÿ¬¬¬444222222222222222222222222222222222===£££:::222222222222222222222222222222222;;;îîï~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿûûû222222777www©©©³³³TTT222222HHHçççÿÿÿÿÿÿVVV222IIIòòòÿÿÿ¿¿¿:::222222aaa´´´§§§kkl555222;;;¶¶¶ÿÿÿÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÿÿÿóóó\\\222222222222222222222222222222222
-úúú222222222222222222222222222222333 ÿÿÿ~~~222222©©©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ}}}222222«««ÿÿÿÿÿÿøøø777222222222222222222222TTTáááÿÿÿÿÿÿÿÿÿVVV222IIIòòòÿÿÿÿÿÿ»»¼DDD222222222222222222222BBBµµµÿÿÿÿÿÿÞÞÞ222222ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´222222¬¬¬ÿÿÿÿÿÿæææbbb333222222222222222222222444~~ôôôÿÿÿ÷÷÷444222222222222222222222444ÿÿÿÿÿÿ¿¿¿ÔÔÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾¾¾ÕÕÕÿÿÿÿÿÿÿÿÿþþþ×ØØ
-
-SSS555333EEEeef­­­ùùùÿÿÿÿÿÿÿÿÿÿÿÿ«««¤¤¤ùùùÿÿÿÿÿÿÿÿÿëëë__`;;;222===YYZèèèÿÿÿÿÿÿÿÿÿîîîÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÙÙÕÕÕÿÿÿÿÿÿÿÿÿüüüÁÁÁzzzTUU666222:::XYYÐÐÐýýýÿÿÿÿÿÿÿÿÿþþþÕÕÕZZ[<<<222888[[[ÝÝÝÿÿÿÿÿÿÿÿÿ
Index: uspace/srv/hid/console/keybuffer.c
===================================================================
--- uspace/srv/hid/console/keybuffer.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/console/keybuffer.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -90,5 +90,5 @@
  *
  */
-void keybuffer_push(keybuffer_t *keybuffer, const console_event_t *ev)
+void keybuffer_push(keybuffer_t *keybuffer, const kbd_event_t *ev)
 {
 	futex_down(&keybuffer_futex);
@@ -110,5 +110,5 @@
  *
  */
-bool keybuffer_pop(keybuffer_t *keybuffer, console_event_t *edst)
+bool keybuffer_pop(keybuffer_t *keybuffer, kbd_event_t *edst)
 {
 	futex_down(&keybuffer_futex);
Index: uspace/srv/hid/console/keybuffer.h
===================================================================
--- uspace/srv/hid/console/keybuffer.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/console/keybuffer.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -46,5 +46,5 @@
 
 typedef struct {
-	console_event_t fifo[KEYBUFFER_SIZE];
+	kbd_event_t fifo[KEYBUFFER_SIZE];
 	size_t head;
 	size_t tail;
@@ -56,6 +56,6 @@
 extern size_t keybuffer_available(keybuffer_t *);
 extern bool keybuffer_empty(keybuffer_t *);
-extern void keybuffer_push(keybuffer_t *, const console_event_t *);
-extern bool keybuffer_pop(keybuffer_t *, console_event_t *);
+extern void keybuffer_push(keybuffer_t *, const kbd_event_t *);
+extern bool keybuffer_pop(keybuffer_t *, kbd_event_t *);
 
 #endif
Index: uspace/srv/hid/fb/Makefile
===================================================================
--- uspace/srv/hid/fb/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -40,6 +40,5 @@
 
 SOURCES = \
-	main.c \
-	ppm.c
+	main.c
 
 ifneq ($(UARCH),ia64)
@@ -84,14 +83,8 @@
 		EXTRA_CFLAGS += -DNIAGARA_ENABLED
 	endif
-	
-	ifeq ($(MACHINE),serengeti)
-		SOURCES += \
-			sgcn.c \
-			serial_console.c
-		EXTRA_CFLAGS += -DSGCN_ENABLED
-	endif
 endif
 
-EXTRA_CFLAGS += -D$(UARCH)
+LIBS = $(LIBIMGMAP_PREFIX)/libimgmap.a
+EXTRA_CFLAGS += -I$(LIBIMGMAP_PREFIX) -D$(UARCH)
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/fb/ega.c
===================================================================
--- uspace/srv/hid/fb/ega.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/ega.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,7 +52,9 @@
 #include <io/screenbuffer.h>
 #include <sys/types.h>
-
 #include "ega.h"
 #include "main.h"
+
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
 
 #define MAX_SAVED_SCREENS  256
@@ -254,5 +256,6 @@
 }
 
-static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	size_t intersize = 0;
@@ -291,6 +294,5 @@
 		int retval;
 		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		if (!IPC_GET_IMETHOD(call)) {
 			client_connected = 0;
 			async_answer_0(callid, EOK);
@@ -298,4 +300,7 @@
 			/* Exit thread */
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case IPC_M_SHARE_OUT:
 			/* We accept one area for data interchange */
@@ -409,12 +414,12 @@
 			retval = 0;
 			break;
-		case FB_VP_DRAW_PIXMAP:
+		case FB_VP_DRAW_IMGMAP:
 			scr = IPC_GET_ARG2(call);
 			retval = print_screen(scr);
 			break;
-		case FB_VP2PIXMAP:
+		case FB_VP2IMGMAP:
 			retval = save_screen();
 			break;
-		case FB_DROP_PIXMAP:
+		case FB_DROP_IMGMAP:
 			scr = IPC_GET_ARG1(call);
 			
Index: uspace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/fb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -49,6 +49,6 @@
 #include <ipc/ns.h>
 #include <ipc/services.h>
-#include <kernel/errno.h>
-#include <kernel/genarch/fb/visuals.h>
+#include <errno.h>
+#include <abi/fb/visuals.h>
 #include <io/color.h>
 #include <io/style.h>
@@ -59,13 +59,14 @@
 #include <byteorder.h>
 #include <io/screenbuffer.h>
-
+#include <imgmap.h>
 #include "font-8x16.h"
 #include "fb.h"
 #include "main.h"
-#include "ppm.h"
-
 #include "pointer.xbm"
 #include "pointer_mask.xbm"
 
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
+
 #define DEFAULT_BGCOLOR  0xf0f0f0
 #define DEFAULT_FGCOLOR  0x000000
@@ -75,5 +76,5 @@
 #define MAX_ANIM_LEN    8
 #define MAX_ANIMATIONS  4
-#define MAX_PIXMAPS     256  /**< Maximum number of saved pixmaps */
+#define MAX_IMGMAPS     256  /**< Maximum number of saved image maps */
 #define MAX_VIEWPORTS   128  /**< Viewport is a rectangular area on the screen */
 
@@ -159,5 +160,5 @@
 	unsigned int pos;
 	unsigned int animlen;
-	unsigned int pixmaps[MAX_ANIM_LEN];
+	unsigned int imgmaps[MAX_ANIM_LEN];
 } animation_t;
 
@@ -165,11 +166,5 @@
 static bool anims_enabled;
 
-typedef struct {
-	unsigned int width;
-	unsigned int height;
-	uint8_t *data;
-} pixmap_t;
-
-static pixmap_t pixmaps[MAX_PIXMAPS];
+static imgmap_t *imgmaps[MAX_IMGMAPS];
 static viewport_t viewports[128];
 
@@ -211,5 +206,4 @@
 static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
     unsigned int row);
-
 
 #define RED(x, bits)                 (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
@@ -874,5 +868,4 @@
 }
 
-
 /** Show cursor if cursor showing is enabled
  *
@@ -887,5 +880,4 @@
 }
 
-
 /** Invert cursor, if it is enabled
  *
@@ -898,5 +890,4 @@
 		cursor_show(vport);
 }
-
 
 /** Draw character at given position relative to viewport
@@ -980,18 +971,7 @@
 }
 
-
-static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color)
-{
-	int pm = *((int *) data);
-	pixmap_t *pmap = &pixmaps[pm];
-	unsigned int pos = (y * pmap->width + x) * screen.pixelbytes;
-	
-	screen.rgb_conv(&pmap->data[pos], color);
-}
-
-
-static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color)
-{
-	viewport_t *vport = (viewport_t *) data;
+static void putpixel(viewport_t *vport, unsigned int x, unsigned int y,
+    uint32_t color)
+{
 	unsigned int dx = vport->x + x;
 	unsigned int dy = vport->y + y;
@@ -1000,14 +980,50 @@
 }
 
-
-/** Return first free pixmap
- *
- */
-static int find_free_pixmap(void)
+/** Draw image map
+ *
+ * @param[in] img       Image map.
+ * @param[in] sx        Coordinate of upper left corner.
+ * @param[in] sy        Coordinate of upper left corner.
+ * @param[in] maxwidth  Maximum allowed width for picture.
+ * @param[in] maxheight Maximum allowed height for picture.
+ * @param[in] vport     Viewport.
+ *
+ * @return EOK on success.
+ *
+ */
+static int imgmap_draw(imgmap_t *img, unsigned int sx, unsigned int sy,
+    unsigned int maxwidth, unsigned int maxheight, void *vport)
+{
+	if (img->visual != VISUAL_BGR_8_8_8)
+		return EINVAL;
+	
+	uint8_t *data = (uint8_t *) img->data;
+	
+	for (sysarg_t y = 0; y < img->height; y++) {
+		for (sysarg_t x = 0; x < img->width; x++) {
+			if ((x > maxwidth) || (y > maxheight)) {
+				data += 3;
+				continue;
+			}
+			
+			uint32_t color = (data[2] << 16) + (data[1] << 8) + data[0];
+			
+			putpixel(vport, sx + x, sy + y, color);
+			data += 3;
+		}
+	}
+	
+	return EOK;
+}
+
+/** Return first free image map
+ *
+ */
+static int find_free_imgmap(void)
 {
 	unsigned int i;
 	
-	for (i = 0; i < MAX_PIXMAPS; i++)
-		if (!pixmaps[i].data)
+	for (i = 0; i < MAX_IMGMAPS; i++)
+		if (!imgmaps[i])
 			return i;
 	
@@ -1015,38 +1031,28 @@
 }
 
-
-/** Create a new pixmap and return appropriate ID
- *
- */
-static int shm2pixmap(unsigned char *shm, size_t size)
-{
-	int pm;
-	pixmap_t *pmap;
-	
-	pm = find_free_pixmap();
-	if (pm == -1)
+/** Create a new image map and return appropriate ID
+ *
+ */
+static int shm2imgmap(imgmap_t *shm, size_t size)
+{
+	int im = find_free_imgmap();
+	if (im == -1)
 		return ELIMIT;
 	
-	pmap = &pixmaps[pm];
-	
-	if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
-		return EINVAL;
-	
-	pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
-	if (!pmap->data)
+	imgmap_t *imap = malloc(size);
+	if (!imap)
 		return ENOMEM;
 	
-	ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm);
-	
-	return pm;
-}
-
+	memcpy(imap, shm, size);
+	imgmaps[im] = imap;
+	return im;
+}
 
 /** Handle shared memory communication calls
  *
- * Protocol for drawing pixmaps:
+ * Protocol for drawing image maps:
  * - FB_PREPARE_SHM(client shm identification)
  * - IPC_M_AS_AREA_SEND
- * - FB_DRAW_PPM(startx, starty)
+ * - FB_DRAW_IMGMAP(startx, starty)
  * - FB_DROP_SHM
  *
@@ -1070,5 +1076,5 @@
 	static size_t intersize = 0;
 	
-	static unsigned char *shm = NULL;
+	static imgmap_t *shm = NULL;
 	static sysarg_t shm_id = 0;
 	static size_t shm_size;
@@ -1092,9 +1098,6 @@
 				return false;
 			}
+			
 			shm = dest;
-			
-			if (shm[0] != 'P')
-				return false;
-			
 			return true;
 		} else {
@@ -1106,8 +1109,7 @@
 		if (shm_id)
 			retval = EBUSY;
-		else 
+		else
 			shm_id = IPC_GET_ARG1(*call);
 		break;
-		
 	case FB_DROP_SHM:
 		if (shm) {
@@ -1117,17 +1119,17 @@
 		shm_id = 0;
 		break;
-		
-	case FB_SHM2PIXMAP:
+	case FB_SHM2IMGMAP:
 		if (!shm) {
 			retval = EINVAL;
 			break;
 		}
-		retval = shm2pixmap(shm, shm_size);
-		break;
-	case FB_DRAW_PPM:
+		retval = shm2imgmap(shm, shm_size);
+		break;
+	case FB_DRAW_IMGMAP:
 		if (!shm) {
 			retval = EINVAL;
 			break;
 		}
+		
 		x = IPC_GET_ARG1(*call);
 		y = IPC_GET_ARG2(*call);
@@ -1138,6 +1140,6 @@
 		}
 		
-		ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
-		    IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport);
+		imgmap_draw(shm, IPC_GET_ARG1(*call), IPC_GET_ARG2(*call),
+		    vport->width - x, vport->height - y, vport);
 		break;
 	case FB_DRAW_TEXT_DATA:
@@ -1166,9 +1168,9 @@
 	if (handled)
 		async_answer_0(callid, retval);
+	
 	return handled;
 }
 
-
-static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
+static void copy_vp_to_imgmap(viewport_t *vport, imgmap_t *imap)
 {
 	unsigned int width = vport->width;
@@ -1177,9 +1179,10 @@
 	if (width + vport->x > screen.xres)
 		width = screen.xres - vport->x;
+	
 	if (height + vport->y > screen.yres)
 		height = screen.yres - vport->y;
 	
-	unsigned int realwidth = pmap->width <= width ? pmap->width : width;
-	unsigned int realheight = pmap->height <= height ? pmap->height : height;
+	unsigned int realwidth = imap->width <= width ? imap->width : width;
+	unsigned int realheight = imap->height <= height ? imap->height : height;
 	
 	unsigned int srcrowsize = vport->width * screen.pixelbytes;
@@ -1189,44 +1192,44 @@
 	for (y = 0; y < realheight; y++) {
 		unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
-		memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
-	}
-}
-
-
-/** Save viewport to pixmap
- *
- */
-static int save_vp_to_pixmap(viewport_t *vport)
-{
-	int pm;
-	pixmap_t *pmap;
-	
-	pm = find_free_pixmap();
-	if (pm == -1)
+		memcpy(imap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
+	}
+}
+
+/** Save viewport to image map
+ *
+ */
+static int save_vp_to_imgmap(viewport_t *vport)
+{
+	int im = find_free_imgmap();
+	if (im == -1)
 		return ELIMIT;
 	
-	pmap = &pixmaps[pm];
-	pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
-	if (!pmap->data)
+	size_t size = screen.pixelbytes * vport->width * vport->height;
+	imgmap_t *imap = malloc(sizeof(imgmap_t) + size);
+	if (!imap)
 		return ENOMEM;
 	
-	pmap->width = vport->width;
-	pmap->height = vport->height;
-	
-	copy_vp_to_pixmap(vport, pmap);
-	
-	return pm;
-}
-
-
-/** Draw pixmap on screen
- *
- * @param vp Viewport to draw on
- * @param pm Pixmap identifier
- *
- */
-static int draw_pixmap(int vp, int pm)
-{
-	pixmap_t *pmap = &pixmaps[pm];
+	imap->size = sizeof(imgmap_t) + size;
+	imap->width = vport->width;
+	imap->height = vport->height;
+	imap->visual = (visual_t) -1;
+	
+	copy_vp_to_imgmap(vport, imap);
+	imgmaps[im] = imap;
+	return im;
+}
+
+/** Draw image map to screen
+ *
+ * @param vp Viewport to draw to
+ * @param im Image map identifier
+ *
+ */
+static int draw_imgmap(int vp, int im)
+{
+	imgmap_t *imap = imgmaps[im];
+	if (!imap)
+		return EINVAL;
+	
 	viewport_t *vport = &viewports[vp];
 	
@@ -1236,25 +1239,25 @@
 	if (width + vport->x > screen.xres)
 		width = screen.xres - vport->x;
+	
 	if (height + vport->y > screen.yres)
 		height = screen.yres - vport->y;
 	
-	if (!pmap->data)
-		return EINVAL;
-	
-	unsigned int realwidth = pmap->width <= width ? pmap->width : width;
-	unsigned int realheight = pmap->height <= height ? pmap->height : height;
-	
-	unsigned int srcrowsize = vport->width * screen.pixelbytes;
-	unsigned int realrowsize = realwidth * screen.pixelbytes;
-	
-	unsigned int y;
-	for (y = 0; y < realheight; y++) {
-		unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
-		memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize);
-	}
+	unsigned int realwidth = imap->width <= width ? imap->width : width;
+	unsigned int realheight = imap->height <= height ? imap->height : height;
+	
+	if (imap->visual == (visual_t) -1) {
+		unsigned int srcrowsize = vport->width * screen.pixelbytes;
+		unsigned int realrowsize = realwidth * screen.pixelbytes;
+		
+		unsigned int y;
+		for (y = 0; y < realheight; y++) {
+			unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
+			memcpy(screen.fb_addr + tmp, imap->data + y * srcrowsize, realrowsize);
+		}
+	} else
+		imgmap_draw(imap, 0, 0, realwidth, realheight, vport);
 	
 	return EOK;
 }
-
 
 /** Tick animation one step forward
@@ -1276,5 +1279,5 @@
 			continue;
 		
-		draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);
+		draw_imgmap(animations[i].vp, animations[i].imgmaps[animations[i].pos]);
 		animations[i].pos = (animations[i].pos + 1) % animations[i].animlen;
 	}
@@ -1286,5 +1289,5 @@
 static bool pointer_shown, pointer_enabled;
 static int pointer_vport = -1;
-static int pointer_pixmap = -1;
+static int pointer_imgmap = -1;
 
 
@@ -1309,8 +1312,8 @@
 	}
 	
-	if (pointer_pixmap == -1)
-		pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
+	if (pointer_imgmap == -1)
+		pointer_imgmap = save_vp_to_imgmap(&viewports[pointer_vport]);
 	else
-		copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]);
+		copy_vp_to_imgmap(&viewports[pointer_vport], imgmaps[pointer_imgmap]);
 	
 	/* Draw mouse pointer. */
@@ -1337,5 +1340,5 @@
 	/* Restore image under the pointer. */
 	if (pointer_shown) {
-		draw_pixmap(pointer_vport, pointer_pixmap);
+		draw_imgmap(pointer_vport, pointer_imgmap);
 		pointer_shown = 0;
 	}
@@ -1392,5 +1395,5 @@
 		animations[i].initialized = 0;
 		break;
-	case FB_ANIM_ADDPIXMAP:
+	case FB_ANIM_ADDIMGMAP:
 		i = IPC_GET_ARG1(*call);
 		if (i >= MAX_ANIMATIONS || i < 0 ||
@@ -1404,10 +1407,10 @@
 		}
 		newval = IPC_GET_ARG2(*call);
-		if (newval < 0 || newval > MAX_PIXMAPS ||
-			!pixmaps[newval].data) {
+		if (newval < 0 || newval > MAX_IMGMAPS ||
+			!imgmaps[newval]) {
 			retval = EINVAL;
 			break;
 		}
-		animations[i].pixmaps[animations[i].animlen++] = newval;
+		animations[i].imgmaps[animations[i].animlen++] = newval;
 		break;
 	case FB_ANIM_CHGVP:
@@ -1448,9 +1451,8 @@
 }
 
-
-/** Handler for messages concerning pixmap handling
- *
- */
-static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
+/** Handler for messages concerning image map handling
+ *
+ */
+static int imgmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
 {
 	bool handled = true;
@@ -1459,36 +1461,43 @@
 	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case FB_VP_DRAW_PIXMAP:
+	case FB_VP_DRAW_IMGMAP:
 		nvp = IPC_GET_ARG1(*call);
 		if (nvp == -1)
 			nvp = vp;
+		
 		if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
-			!viewports[nvp].initialized) {
+		    !viewports[nvp].initialized) {
 			retval = EINVAL;
 			break;
 		}
+		
 		i = IPC_GET_ARG2(*call);
-		retval = draw_pixmap(nvp, i);
-		break;
-	case FB_VP2PIXMAP:
+		retval = draw_imgmap(nvp, i);
+		break;
+	case FB_VP2IMGMAP:
 		nvp = IPC_GET_ARG1(*call);
 		if (nvp == -1)
 			nvp = vp;
+		
 		if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
-			!viewports[nvp].initialized)
+		    !viewports[nvp].initialized) {
 			retval = EINVAL;
-		else
-			retval = save_vp_to_pixmap(&viewports[nvp]);
-		break;
-	case FB_DROP_PIXMAP:
+			break;
+		}
+		
+		retval = save_vp_to_imgmap(&viewports[nvp]);
+		break;
+	case FB_DROP_IMGMAP:
 		i = IPC_GET_ARG1(*call);
-		if (i >= MAX_PIXMAPS) {
+		if (i >= MAX_IMGMAPS) {
 			retval = EINVAL;
 			break;
 		}
-		if (pixmaps[i].data) {
-			free(pixmaps[i].data);
-			pixmaps[i].data = NULL;
-		}
+		
+		if (imgmaps[i]) {
+			free(imgmaps[i]);
+			imgmaps[i] = NULL;
+		}
+		
 		break;
 	default:
@@ -1575,5 +1584,6 @@
  *
  */
-static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	unsigned int vp = 0;
@@ -1614,5 +1624,5 @@
 			continue;
 		
-		if (pixmap_handle(callid, &call, vp))
+		if (imgmap_handle(callid, &call, vp))
 			continue;
 		
@@ -1620,6 +1630,5 @@
 			continue;
 		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		if (!IPC_GET_IMETHOD(call)) {
 			client_connected = false;
 			
@@ -1630,5 +1639,7 @@
 			/* Exit thread */
 			return;
-		
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case FB_PUTCHAR:
 			ch = IPC_GET_ARG1(call);
Index: uspace/srv/hid/fb/fb.h
===================================================================
--- uspace/srv/hid/fb/fb.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/fb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,6 +39,4 @@
 #include <stdint.h>
 
-typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, uint32_t);
-
 extern int fb_init(void);
 
Index: uspace/srv/hid/fb/main.c
===================================================================
--- uspace/srv/hid/fb/main.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -28,5 +28,5 @@
 
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <sysinfo.h>
 #include <async.h>
@@ -40,5 +40,4 @@
 #include "msim.h"
 #include "ski.h"
-#include "sgcn.h"
 #include "niagara.h"
 #include "main.h"
@@ -92,10 +91,4 @@
 	}
 #endif
-#ifdef SGCN_ENABLED
-	if ((!initialized) && (fb_kind == 4)) {
-		if (sgcn_init() == 0)
-			initialized = true;
-	}
-#endif
 #ifdef NIAGARA_ENABLED
 	if ((!initialized) && (fb_kind == 5)) {
Index: uspace/srv/hid/fb/niagara.c
===================================================================
--- uspace/srv/hid/fb/niagara.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/niagara.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -29,5 +29,5 @@
  */
 
-/** @defgroup niagarafb SGCN
+/** @defgroup niagarafb
  * @brief	userland driver of the Niagara console output
  * @{
Index: uspace/srv/hid/fb/niagara.h
===================================================================
--- uspace/srv/hid/fb/niagara.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/niagara.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -27,6 +27,6 @@
  */
 
-/** @defgroup sgcnfb SGCN
- * @brief	userland driver of the Serengeti console output
+/** @defgroup niagarafb
+ * @brief	userland driver of the Niagara console output
  * @{
  */
Index: pace/srv/hid/fb/ppm.c
===================================================================
--- uspace/srv/hid/fb/ppm.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <errno.h>
-
-#include "ppm.h"
-
-static void skip_whitespace(unsigned char **data)
-{
-retry:
-	while (**data == ' ' || **data == '\t' || **data == '\n' ||
-	    **data == '\r')
-		(*data)++;
-	if (**data == '#') {
-		while (1) {
-			if (**data == '\n' || **data == '\r')
-				break;
-			(*data)++;
-		}
-		goto retry;
-	}
-}
-
-static void read_num(unsigned char **data, unsigned int *num)
-{
-	*num = 0;
-	while (**data >= '0' && **data <= '9') {
-		*num *= 10;
-		*num += **data - '0';
-		(*data)++;
-	}
-}
-
-int ppm_get_data(unsigned char *data, size_t dtsz, unsigned int *width,
-    unsigned int *height)
-{
-	/* Read magic */
-	if (data[0] != 'P' || data[1] != '6')
-		return EINVAL;
-
-	data+=2;
-	skip_whitespace(&data);
-	read_num(&data, width);
-	skip_whitespace(&data);
-	read_num(&data,height);
-
-	return 0;
-}
-
-/** Draw PPM pixmap
- *
- * @param data Pointer to PPM data
- * @param datasz Maximum data size
- * @param sx Coordinate of upper left corner
- * @param sy Coordinate of upper left corner
- * @param maxwidth Maximum allowed width for picture
- * @param maxheight Maximum allowed height for picture
- * @param putpixel Putpixel function used to print bitmap
- */
-int ppm_draw(unsigned char *data, size_t datasz, unsigned int sx,
-    unsigned int sy, unsigned int maxwidth, unsigned int maxheight,
-    putpixel_cb_t putpixel, void *vport)
-{
-	unsigned int width, height;
-	unsigned int maxcolor;
-	unsigned int i;
-	unsigned int color;
-	unsigned int coef;
-	
-	/* Read magic */
-	if ((data[0] != 'P') || (data[1] != '6'))
-		return EINVAL;
-	
-	data += 2;
-	skip_whitespace(&data);
-	read_num(&data, &width);
-	skip_whitespace(&data);
-	read_num(&data, &height);
-	skip_whitespace(&data);
-	read_num(&data, &maxcolor);
-	data++;
-	
-	if ((maxcolor == 0) || (maxcolor > 255) || (width * height > datasz))
-		return EINVAL;
-	
-	coef = 255 / maxcolor;
-	if (coef * maxcolor > 255)
-		coef -= 1;
-	
-	for (i = 0; i < width * height; i++) {
-		/* Crop picture if we don't fit into region */
-		if (i % width > maxwidth || i / width > maxheight) {
-			data += 3;
-			continue;
-		}
-		color = ((data[0] * coef) << 16) + ((data[1] * coef) << 8) +
-		    data[2] * coef;
-		
-		(*putpixel)(vport, sx + (i % width), sy + (i / width), color);
-		data += 3;
-	}
-	
-	return 0;
-}
Index: pace/srv/hid/fb/ppm.h
===================================================================
--- uspace/srv/hid/fb/ppm.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,39 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FB_PPM_H_
-#define FB_PPM_H_
-
-#include "fb.h"
-#include <sys/types.h>
-
-extern int ppm_draw(unsigned char *, size_t, unsigned int, unsigned int, 
-    unsigned int, unsigned int, putpixel_cb_t, void *);
-extern int ppm_get_data(unsigned char *, size_t, unsigned int *, unsigned int *);
-
-#endif
Index: uspace/srv/hid/fb/serial_console.c
===================================================================
--- uspace/srv/hid/fb/serial_console.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/serial_console.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,4 +52,7 @@
 #include "serial_console.h"
 
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
+
 #define MAX_CONTROL 20
 
@@ -312,5 +315,5 @@
  * Main function of the thread serving client connections.
  */
-void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	keyfield_t *interbuf = NULL;
@@ -344,6 +347,5 @@
 		int retval;
 		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		if (!IPC_GET_IMETHOD(call)) {
 			client_connected = 0;
 			async_answer_0(callid, EOK);
@@ -351,4 +353,7 @@
 			/* Exit thread */
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case IPC_M_SHARE_OUT:
 			/* We accept one area for data interchange */
Index: uspace/srv/hid/fb/serial_console.h
===================================================================
--- uspace/srv/hid/fb/serial_console.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/fb/serial_console.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,5 +52,5 @@
 extern void serial_set_scroll_region(sysarg_t);
 extern void serial_console_init(putc_function_t, sysarg_t, sysarg_t);
-extern void serial_client_connection(ipc_callid_t, ipc_call_t *);
+extern void serial_client_connection(ipc_callid_t, ipc_call_t *, void *arg);
 
 #endif
Index: pace/srv/hid/fb/sgcn.c
===================================================================
--- uspace/srv/hid/fb/sgcn.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,150 +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.
- */
-
-/** @defgroup sgcnfb SGCN
- * @brief	userland driver of the Serengeti console output
- * @{
- */ 
-/** @file
- */
-
-#include <async.h>
-#include <sysinfo.h>
-#include <as.h>
-#include <errno.h>
-#include <stdio.h>
-#include <ddi.h>
-
-#include "serial_console.h"
-#include "sgcn.h"
-
-#define WIDTH 80
-#define HEIGHT 24
-
-/**
- * Virtual address mapped to SRAM.
- */
-static uintptr_t sram_virt_addr;
-
-/**
- * SGCN buffer offset within SGCN.
- */
-static uintptr_t sram_buffer_offset;
-
-/**
- * SGCN buffer header. It is placed at the very beginning of the SGCN
- * buffer. 
- */
-typedef struct {
-	/** hard-wired to "CON" */
-	char magic[4];
-	
-	/** we don't need this */
-	char unused[24];
-
-	/** offset within the SGCN buffer of the output buffer start */
-	uint32_t out_begin;
-	
-	/** offset within the SGCN buffer of the output buffer end */
-	uint32_t out_end;
-	
-	/** offset within the SGCN buffer of the output buffer read pointer */
-	uint32_t out_rdptr;
-	
-	/** offset within the SGCN buffer of the output buffer write pointer */
-	uint32_t out_wrptr;
-} __attribute__ ((packed)) sgcn_buffer_header_t;
-
-
-/*
- * Returns a pointer to the object of a given type which is placed at the given
- * offset from the console buffer beginning.
- */
-#define SGCN_BUFFER(type, offset) \
-		((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
-
-/** Returns a pointer to the console buffer header. */
-#define SGCN_BUFFER_HEADER	(SGCN_BUFFER(sgcn_buffer_header_t, 0))
-
-/**
- * Pushes the character to the SGCN serial.
- * @param c	character to be pushed
- */
-static void sgcn_putc(char c)
-{
-	uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
-	uint32_t end = SGCN_BUFFER_HEADER->out_end;
-	uint32_t size = end - begin;
-	
-	/* we need pointers to volatile variables */
-	volatile char *buf_ptr = (volatile char *)
-		SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
-	volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
-	volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
-
-	uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
-	while (*out_rdptr_ptr == new_wrptr)
-		;
-	*buf_ptr = c;
-	*out_wrptr_ptr = new_wrptr;
-}
-
-/**
- * Initializes the SGCN serial driver.
- */
-int sgcn_init(void)
-{
-	sysarg_t sram_paddr;
-	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
-		return -1;
-	
-	sysarg_t sram_size;
-	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
-		sram_buffer_offset = 0;
-	
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
-	
-	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
-	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0)
-		return -1;
-	
-	serial_console_init(sgcn_putc, WIDTH, HEIGHT);
-	
-	async_set_client_connection(serial_client_connection);
-	return 0;
-}
-
-/** 
- * @}
- */
- 
Index: pace/srv/hid/fb/sgcn.h
===================================================================
--- uspace/srv/hid/fb/sgcn.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,46 +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.
- */
-
-/** @defgroup sgcnfb SGCN
- * @brief	userland driver of the Serengeti console output
- * @{
- */
- 
-/** @file
- */
-
-#ifndef FB_SGCN_H_
-#define FB_SGCN_H_
-
-int sgcn_init(void);
-
-#endif
-
-/** 
- * @}
- */
Index: uspace/srv/hid/input/Makefile
===================================================================
--- uspace/srv/hid/input/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+EXTRA_CFLAGS = -Iinclude
+BINARY = input
+
+SOURCES = \
+	generic/gsp.c \
+	generic/input.c \
+	generic/layout.c \
+	generic/stroke.c \
+	layout/cz.c \
+	layout/us_qwerty.c \
+	layout/us_dvorak.c \
+	port/adb.c \
+	port/adb_mouse.c \
+	port/chardev.c \
+	port/chardev_mouse.c \
+	port/gxemul.c \
+	port/msim.c \
+	port/niagara.c \
+	port/ns16550.c \
+	port/pl050.c \
+	port/ski.c \
+	proto/adb.c \
+	proto/mousedev.c \
+	proto/ps2.c \
+	ctl/apple.c \
+	ctl/gxe_fb.c \
+	ctl/kbdev.c \
+	ctl/pc.c \
+	ctl/stty.c \
+	ctl/sun.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/input/ctl/apple.c
===================================================================
--- uspace/srv/hid/input/ctl/apple.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/ctl/apple.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Apple ADB keyboard controller driver.
+ */
+
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+
+static void apple_ctl_parse(sysarg_t);
+static int apple_ctl_init(kbd_dev_t *);
+static void apple_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t apple_ctl = {
+	.parse = apple_ctl_parse,
+	.init = apple_ctl_init,
+	.set_ind = apple_ctl_set_ind
+};
+
+#define KBD_KEY_RELEASE		0x80
+
+static kbd_dev_t *kbd_dev;
+
+static int scanmap[];
+
+static int apple_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	return 0;
+}
+
+static void apple_ctl_parse(sysarg_t scancode)
+{
+	kbd_event_type_t type;
+	unsigned int key;
+
+	if (scancode >= 0x100)
+		return;
+
+	if (scancode & KBD_KEY_RELEASE) {
+		scancode &= ~KBD_KEY_RELEASE;
+		type = KEY_RELEASE;
+	} else {
+		type = KEY_PRESS;
+	}
+
+	key = scanmap[scancode];
+	if (key != 0)
+		kbd_push_event(kbd_dev, type, key);
+}
+
+static void apple_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	(void) mods;
+}
+
+static int scanmap[] = {
+	[0x00] = KC_A,
+	[0x01] = KC_S,
+	[0x02] = KC_D,
+	[0x03] = KC_F,
+	[0x04] = KC_H,
+	[0x05] = KC_G,
+	[0x06] = KC_Z,
+	[0x07] = KC_X,
+	[0x08] = KC_C,
+	[0x09] = KC_V,
+	[0x0a] = KC_BACKSLASH,
+	[0x0b] = KC_B,
+	[0x0c] = KC_Q,
+	[0x0d] = KC_W,
+	[0x0e] = KC_E,
+	[0x0f] = KC_R,
+	[0x10] = KC_Y,
+	[0x11] = KC_T,
+	[0x12] = KC_1,
+	[0x13] = KC_2,
+	[0x14] = KC_3,
+	[0x15] = KC_4,
+	[0x16] = KC_6,
+	[0x17] = KC_5,
+	[0x18] = KC_EQUALS,
+	[0x19] = KC_9,
+	[0x1a] = KC_7,
+	[0x1b] = KC_MINUS,
+	[0x1c] = KC_8,
+	[0x1d] = KC_0,
+	[0x1e] = KC_RBRACKET,
+	[0x1f] = KC_O,
+	[0x20] = KC_U,
+	[0x21] = KC_LBRACKET,
+	[0x22] = KC_I,
+	[0x23] = KC_P,
+	[0x24] = KC_ENTER,
+	[0x25] = KC_L,
+	[0x26] = KC_J,
+	[0x27] = KC_QUOTE,
+	[0x28] = KC_K,
+	[0x29] = KC_SEMICOLON,
+	[0x2a] = KC_BACKSLASH,
+	[0x2b] = KC_COMMA,
+	[0x2c] = KC_SLASH,
+	[0x2d] = KC_N,
+	[0x2e] = KC_M,
+	[0x2f] = KC_PERIOD,
+	[0x30] = KC_TAB,
+	[0x31] = KC_SPACE,
+	[0x32] = KC_BACKTICK,
+	[0x33] = KC_BACKSPACE,
+	[0x34] = 0,
+	[0x35] = KC_ESCAPE,
+	[0x36] = KC_LCTRL,
+	[0x37] = 0,
+	[0x38] = KC_LSHIFT,
+	[0x39] = KC_CAPS_LOCK,
+	[0x3a] = KC_LALT,
+	[0x3b] = KC_LEFT,
+	[0x3c] = KC_RIGHT,
+	[0x3d] = KC_DOWN,
+	[0x3e] = KC_UP,
+	[0x3f] = 0,
+	[0x40] = 0,
+	[0x41] = KC_NPERIOD,
+	[0x42] = 0,
+	[0x43] = KC_NTIMES,
+	[0x44] = 0,
+	[0x45] = KC_NPLUS,
+	[0x46] = 0,
+	[0x47] = KC_NUM_LOCK,
+	[0x48] = 0,
+	[0x49] = 0,
+	[0x4a] = 0,
+	[0x4b] = KC_NSLASH,
+	[0x4c] = KC_NENTER,
+	[0x4d] = 0,
+	[0x4e] = KC_NMINUS,
+	[0x4f] = 0,
+	[0x50] = 0,
+	[0x51] = 0,
+	[0x52] = KC_N0,
+	[0x53] = KC_N1,
+	[0x54] = KC_N2,
+	[0x55] = KC_N3,
+	[0x56] = KC_N4,
+	[0x57] = KC_N5,
+	[0x58] = KC_N6,
+	[0x59] = KC_N7,
+	[0x5a] = 0,
+	[0x5b] = KC_N8,
+	[0x5c] = KC_N9,
+	[0x5d] = 0,
+	[0x5e] = 0,
+	[0x5f] = 0,
+	[0x60] = KC_F5,
+	[0x61] = KC_F6,
+	[0x62] = KC_F7,
+	[0x63] = KC_F3,
+	[0x64] = KC_F8,
+	[0x65] = KC_F9,
+	[0x66] = 0,
+	[0x67] = KC_F11,
+	[0x68] = 0,
+	[0x69] = 0,
+	[0x6a] = 0,
+	[0x6b] = KC_SCROLL_LOCK,
+	[0x6c] = 0,
+	[0x6d] = KC_F10,
+	[0x6e] = 0,
+	[0x6f] = KC_F12,
+	[0x70] = 0,
+	[0x71] = 0,
+	[0x72] = KC_INSERT,
+	[0x73] = KC_HOME,
+	[0x74] = KC_PAGE_UP,
+	[0x75] = KC_DELETE,
+	[0x76] = KC_F4,
+	[0x77] = KC_END,
+	[0x78] = KC_F2,
+	[0x79] = KC_PAGE_DOWN,
+	[0x7a] = KC_F1,
+	[0x7b] = KC_RSHIFT,
+	[0x7c] = KC_RALT,
+	[0x7d] = KC_RCTRL,
+	[0x7e] = 0,
+	[0x7f] = 0
+};
+
+/** @}
+ */
Index: uspace/srv/hid/input/ctl/gxe_fb.c
===================================================================
--- uspace/srv/hid/input/ctl/gxe_fb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/ctl/gxe_fb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief	GXEmul framebuffer-mode keyboard controller driver.
+ */
+
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+#include <gsp.h>
+#include <stroke.h>
+
+static void gxe_fb_ctl_parse(sysarg_t);
+static int gxe_fb_ctl_init(kbd_dev_t *);
+static void gxe_fb_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t gxe_fb_ctl = {
+	.parse = gxe_fb_ctl_parse,
+	.init = gxe_fb_ctl_init,
+	.set_ind = gxe_fb_ctl_set_ind
+};
+
+static kbd_dev_t *kbd_dev;
+
+/** Scancode parser */
+static gsp_t sp;
+
+/** Current parser state */
+static int ds;
+
+#include <stdio.h>
+
+static int seq_defs[] = {
+	/* Not shifted */
+
+	0,	KC_BACKTICK,	0x60, GSP_END,
+
+	0,	KC_1,		0x31, GSP_END,
+	0,	KC_2,		0x32, GSP_END,
+	0,	KC_3,		0x33, GSP_END,
+	0,	KC_4,		0x34, GSP_END,
+	0,	KC_5,		0x35, GSP_END,
+	0,	KC_6,		0x36, GSP_END,
+	0,	KC_7,		0x37, GSP_END,
+	0,	KC_8,		0x38, GSP_END,
+	0,	KC_9,		0x39, GSP_END,
+	0,	KC_0,		0x30, GSP_END,
+
+	0,	KC_MINUS,	0x2d, GSP_END,
+	0,	KC_EQUALS,	0x3d, GSP_END,
+	0,	KC_BACKSPACE,	0x08, GSP_END,
+
+	0,	KC_TAB,		0x09, GSP_END,
+
+	0,	KC_Q,		0x71, GSP_END,
+	0,	KC_W,		0x77, GSP_END,
+	0,	KC_E,		0x65, GSP_END,
+	0,	KC_R,		0x72, GSP_END,
+	0,	KC_T,		0x74, GSP_END,
+	0,	KC_Y,		0x79, GSP_END,
+	0,	KC_U,		0x75, GSP_END,
+	0,	KC_I,		0x69, GSP_END,
+	0,	KC_O,		0x6f, GSP_END,
+	0,	KC_P,		0x70, GSP_END,
+
+	0,	KC_LBRACKET,	0x5b, GSP_END,
+	0,	KC_RBRACKET,	0x5d, GSP_END,
+
+	0,	KC_A,		0x61, GSP_END,
+	0,	KC_S,		0x73, GSP_END,
+	0,	KC_D,		0x64, GSP_END,
+	0,	KC_F,		0x66, GSP_END,
+	0,	KC_G,		0x67, GSP_END,
+	0,	KC_H,		0x68, GSP_END,
+	0,	KC_J,		0x6a, GSP_END,
+	0,	KC_K,		0x6b, GSP_END,
+	0,	KC_L,		0x6c, GSP_END,
+
+	0,	KC_SEMICOLON,	0x3b, GSP_END,
+	0,	KC_QUOTE,	0x27, GSP_END,
+	0,	KC_BACKSLASH,	0x5c, GSP_END,
+
+	0,	KC_Z,		0x7a, GSP_END,
+	0,	KC_X,		0x78, GSP_END,
+	0,	KC_C,		0x63, GSP_END,
+	0,	KC_V,		0x76, GSP_END,
+	0,	KC_B,		0x62, GSP_END,
+	0,	KC_N,		0x6e, GSP_END,
+	0,	KC_M,		0x6d, GSP_END,
+
+	0,	KC_COMMA,	0x2c, GSP_END,
+	0,	KC_PERIOD,	0x2e, GSP_END,
+	0,	KC_SLASH,	0x2f, GSP_END,
+
+	/* Shifted */
+
+	KM_SHIFT,	KC_BACKTICK,	0x7e, GSP_END,
+
+	KM_SHIFT,	KC_1,		0x21, GSP_END,
+	KM_SHIFT,	KC_2,		0x40, GSP_END,
+	KM_SHIFT,	KC_3,		0x23, GSP_END,
+	KM_SHIFT,	KC_4,		0x24, GSP_END,
+	KM_SHIFT,	KC_5,		0x25, GSP_END,
+	KM_SHIFT,	KC_6,		0x5e, GSP_END,
+	KM_SHIFT,	KC_7,		0x26, GSP_END,
+	KM_SHIFT,	KC_8,		0x2a, GSP_END,
+	KM_SHIFT,	KC_9,		0x28, GSP_END,
+	KM_SHIFT,	KC_0,		0x29, GSP_END,
+
+	KM_SHIFT,	KC_MINUS,	0x5f, GSP_END,
+	KM_SHIFT,	KC_EQUALS,	0x2b, GSP_END,
+
+	KM_SHIFT,	KC_Q,		0x51, GSP_END,
+	KM_SHIFT,	KC_W,		0x57, GSP_END,
+	KM_SHIFT,	KC_E,		0x45, GSP_END,
+	KM_SHIFT,	KC_R,		0x52, GSP_END,
+	KM_SHIFT,	KC_T,		0x54, GSP_END,
+	KM_SHIFT,	KC_Y,		0x59, GSP_END,
+	KM_SHIFT,	KC_U,		0x55, GSP_END,
+	KM_SHIFT,	KC_I,		0x49, GSP_END,
+	KM_SHIFT,	KC_O,		0x4f, GSP_END,
+	KM_SHIFT,	KC_P,		0x50, GSP_END,
+
+	KM_SHIFT,	KC_LBRACKET,	0x7b, GSP_END,
+	KM_SHIFT,	KC_RBRACKET,	0x7d, GSP_END,
+
+	KM_SHIFT,	KC_A,		0x41, GSP_END,
+	KM_SHIFT,	KC_S,		0x53, GSP_END,
+	KM_SHIFT,	KC_D,		0x44, GSP_END,
+	KM_SHIFT,	KC_F,		0x46, GSP_END,
+	KM_SHIFT,	KC_G,		0x47, GSP_END,
+	KM_SHIFT,	KC_H,		0x48, GSP_END,
+	KM_SHIFT,	KC_J,		0x4a, GSP_END,
+	KM_SHIFT,	KC_K,		0x4b, GSP_END,
+	KM_SHIFT,	KC_L,		0x4c, GSP_END,
+
+	KM_SHIFT,	KC_SEMICOLON,	0x3a, GSP_END,
+	KM_SHIFT,	KC_QUOTE,	0x22, GSP_END,
+	KM_SHIFT,	KC_BACKSLASH,	0x7c, GSP_END,
+
+	KM_SHIFT,	KC_Z,		0x5a, GSP_END,
+	KM_SHIFT,	KC_X,		0x58, GSP_END,
+	KM_SHIFT,	KC_C,		0x43, GSP_END,
+	KM_SHIFT,	KC_V,		0x56, GSP_END,
+	KM_SHIFT,	KC_B,		0x42, GSP_END,
+	KM_SHIFT,	KC_N,		0x4e, GSP_END,
+	KM_SHIFT,	KC_M,		0x4d, GSP_END,
+
+	KM_SHIFT,	KC_COMMA,	0x3c, GSP_END,
+	KM_SHIFT,	KC_PERIOD,	0x3e, GSP_END,
+	KM_SHIFT,	KC_SLASH,	0x3f, GSP_END,
+
+	/* ... */
+
+	0,	KC_SPACE,	0x20, GSP_END,
+	0,	KC_ENTER,	0x0a, GSP_END,
+	0,	KC_ENTER,	0x0d, GSP_END,
+
+	0,	KC_ESCAPE,	0x1b, 0x1b, GSP_END,
+
+	0,	KC_F1,		0x1b, 0x5b, 0x4f, 0x50, GSP_END,
+	0,	KC_F2,		0x1b, 0x5b, 0x4f, 0x51, GSP_END,
+	0,	KC_F3,		0x1b, 0x5b, 0x4f, 0x52, GSP_END,
+	0,	KC_F4,		0x1b, 0x5b, 0x4f, 0x53, GSP_END,
+	0,	KC_F5,		0x1b, 0x5b, 0x31, 0x35, GSP_END,
+	0,	KC_F6,		0x1b, 0x5b, 0x31, 0x37, GSP_END,
+	0,	KC_F7,		0x1b, 0x5b, 0x31, 0x38, GSP_END,
+	0,	KC_F8,		0x1b, 0x5b, 0x31, 0x39, GSP_END,
+	0,	KC_F9,		0x1b, 0x5b, 0x32, 0x38, GSP_END,
+	0,	KC_F10,		0x1b, 0x5b, 0x32, 0x39, GSP_END,
+	0,	KC_F11,		0x1b, 0x5b, 0x32, 0x33, GSP_END,
+	0,	KC_F12,		0x1b, 0x5b, 0x32, 0x34, GSP_END,
+
+	0,	KC_INSERT,	0x1b, 0x5b, 0x32, 0x7e, GSP_END,
+	0,	KC_HOME,	0x1b, 0x5b, 0x48, GSP_END,
+	0,	KC_PAGE_UP,	0x1b, 0x5b, 0x35, 0x7e, GSP_END,
+	0,	KC_DELETE,	0x1b, 0x5b, 0x33, 0x7e, GSP_END,
+	0,	KC_END,		0x1b, 0x5b, 0x46, GSP_END,
+	0,	KC_PAGE_DOWN,	0x1b, 0x5b, 0x36, 0x7e, GSP_END,
+
+	0,	KC_UP,		0x1b, 0x5b, 0x41, GSP_END,
+	0,	KC_LEFT,	0x1b, 0x5b, 0x44, GSP_END,
+	0,	KC_DOWN,	0x1b, 0x5b, 0x42, GSP_END,
+	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
+
+	0,	0
+};
+
+static int gxe_fb_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	ds = 0;
+
+	gsp_init(&sp);
+	return gsp_insert_defs(&sp, seq_defs);
+}
+
+static void gxe_fb_ctl_parse(sysarg_t scancode)
+{
+	unsigned mods, key;
+
+	ds = gsp_step(&sp, ds, scancode, &mods, &key);
+	if (key != 0) {
+		stroke_sim(kbd_dev, mods, key);
+	}
+}
+
+static void gxe_fb_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	(void) mods;
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/ctl/kbdev.c
===================================================================
--- uspace/srv/hid/input/ctl/kbdev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/ctl/kbdev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Keyboard device connector controller driver.
+ */
+
+#include <async.h>
+#include <bool.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gsp.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <ipc/kbdev.h>
+#include <input.h>
+#include <kbd.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <vfs/vfs_sess.h>
+#include <sys/typefmt.h>
+
+static int kbdev_ctl_init(kbd_dev_t *);
+static void kbdev_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+static void kbdev_callback_conn(ipc_callid_t, ipc_call_t *, void *arg);
+
+kbd_ctl_ops_t kbdev_ctl = {
+	.parse = NULL,
+	.init = kbdev_ctl_init,
+	.set_ind = kbdev_ctl_set_ind
+};
+
+/** Kbdev softstate */
+typedef struct {
+	/** Link to generic keyboard device */
+	kbd_dev_t *kbd_dev;
+
+	/** Session with kbdev device */
+	async_sess_t *sess;
+} kbdev_t;
+
+static kbdev_t *kbdev_new(kbd_dev_t *kdev)
+{
+	kbdev_t *kbdev;
+
+	kbdev = calloc(1, sizeof(kbdev_t));
+	if (kbdev == NULL)
+		return NULL;
+
+	kbdev->kbd_dev = kdev;
+
+	return kbdev;
+}
+
+static void kbdev_destroy(kbdev_t *kbdev)
+{
+	if (kbdev->sess != NULL)
+		async_hangup(kbdev->sess);
+	free(kbdev);
+}
+
+static int kbdev_ctl_init(kbd_dev_t *kdev)
+{
+	async_sess_t *sess;
+	async_exch_t *exch;
+	kbdev_t *kbdev;
+	int rc;
+
+	sess = loc_service_connect(EXCHANGE_SERIALIZE, kdev->svc_id, 0);
+	if (sess == NULL) {
+		printf("%s: Failed starting session with '%s.'\n", NAME,
+		    kdev->svc_name);
+		return -1;
+	}
+
+	kbdev = kbdev_new(kdev);
+	if (kbdev == NULL) {
+		printf("%s: Failed allocating device structure for '%s'.\n",
+		    NAME, kdev->svc_name);
+		return -1;
+	}
+
+	kbdev->sess = sess;
+
+	exch = async_exchange_begin(sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with '%s'.\n", NAME,
+		    kdev->svc_name);
+		kbdev_destroy(kbdev);
+		return -1;
+	}
+
+	rc = async_connect_to_me(exch, 0, 0, 0, kbdev_callback_conn, kbdev);
+	if (rc != EOK) {
+		printf("%s: Failed creating callback connection from '%s'.\n",
+		    NAME, kdev->svc_name);
+		async_exchange_end(exch);
+		kbdev_destroy(kbdev);
+		return -1;
+	}
+
+	async_exchange_end(exch);
+
+	kdev->ctl_private = (void *) kbdev;
+	return 0;
+}
+
+static void kbdev_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	async_sess_t *sess;
+	async_exch_t *exch;
+
+	sess = ((kbdev_t *) kdev->ctl_private)->sess;
+
+	exch = async_exchange_begin(sess);
+	if (!exch)
+		return;
+
+	async_msg_1(exch, KBDEV_SET_IND, mods);
+	async_exchange_end(exch);
+}
+
+static void kbdev_callback_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	kbdev_t *kbdev;
+	int retval;
+	int type, key;
+
+	/* Kbdev device structure */
+	kbdev = arg;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid;
+
+		callid = async_get_call(&call);
+		if (!IPC_GET_IMETHOD(call)) {
+			/* XXX Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case KBDEV_EVENT:
+			/* Got event from keyboard device */
+			retval = 0;
+			type = IPC_GET_ARG1(call);
+			key = IPC_GET_ARG2(call);
+			kbd_push_event(kbdev->kbd_dev, type, key);
+			break;
+		default:
+			retval = ENOTSUP;
+			break;
+		}
+
+		async_answer_0(callid, retval);
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/ctl/pc.c
===================================================================
--- uspace/srv/hid/input/ctl/pc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/ctl/pc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief PC keyboard controller driver.
+ */
+
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+#include <gsp.h>
+
+static void pc_ctl_parse(sysarg_t);
+static int pc_ctl_init(kbd_dev_t *);
+static void pc_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t pc_ctl = {
+	.parse = pc_ctl_parse,
+	.init = pc_ctl_init,
+	.set_ind = pc_ctl_set_ind
+};
+
+enum dec_state {
+	ds_s,
+	ds_e
+};
+
+enum special_code {
+	SC_ACK = 0xfa,
+	SC_NAK = 0xfe
+};
+
+enum lock_ind_bits {
+	LI_SCROLL	= 0x01,
+	LI_NUM		= 0x02,
+	LI_CAPS		= 0x04
+};
+
+enum kbd_command {
+	KBD_CMD_SET_LEDS = 0xed
+};
+
+static enum dec_state ds;
+static kbd_dev_t *kbd_dev;
+
+static int scanmap_simple[] = {
+
+	[0x29] = KC_BACKTICK,
+
+	[0x02] = KC_1,
+	[0x03] = KC_2,
+	[0x04] = KC_3,
+	[0x05] = KC_4,
+	[0x06] = KC_5,
+	[0x07] = KC_6,
+	[0x08] = KC_7,
+	[0x09] = KC_8,
+	[0x0a] = KC_9,
+	[0x0b] = KC_0,
+
+	[0x0c] = KC_MINUS,
+	[0x0d] = KC_EQUALS,
+	[0x0e] = KC_BACKSPACE,
+
+	[0x0f] = KC_TAB,
+
+	[0x10] = KC_Q,
+	[0x11] = KC_W,
+	[0x12] = KC_E,
+	[0x13] = KC_R,
+	[0x14] = KC_T,
+	[0x15] = KC_Y,
+	[0x16] = KC_U,
+	[0x17] = KC_I,
+	[0x18] = KC_O,
+	[0x19] = KC_P,
+
+	[0x1a] = KC_LBRACKET,
+	[0x1b] = KC_RBRACKET,
+
+	[0x3a] = KC_CAPS_LOCK,
+
+	[0x1e] = KC_A,
+	[0x1f] = KC_S,
+	[0x20] = KC_D,
+	[0x21] = KC_F,
+	[0x22] = KC_G,
+	[0x23] = KC_H,
+	[0x24] = KC_J,
+	[0x25] = KC_K,
+	[0x26] = KC_L,
+
+	[0x27] = KC_SEMICOLON,
+	[0x28] = KC_QUOTE,
+	[0x2b] = KC_BACKSLASH,
+
+	[0x2a] = KC_LSHIFT,
+
+	[0x2c] = KC_Z,
+	[0x2d] = KC_X,
+	[0x2e] = KC_C,
+	[0x2f] = KC_V,
+	[0x30] = KC_B,
+	[0x31] = KC_N,
+	[0x32] = KC_M,
+
+	[0x33] = KC_COMMA,
+	[0x34] = KC_PERIOD,
+	[0x35] = KC_SLASH,
+
+	[0x36] = KC_RSHIFT,
+
+	[0x1d] = KC_LCTRL,
+	[0x38] = KC_LALT,
+	[0x39] = KC_SPACE,
+
+	[0x01] = KC_ESCAPE,
+
+	[0x3b] = KC_F1,
+	[0x3c] = KC_F2,
+	[0x3d] = KC_F3,
+	[0x3e] = KC_F4,
+	[0x3f] = KC_F5,
+	[0x40] = KC_F6,
+	[0x41] = KC_F7,
+
+	[0x42] = KC_F8,
+	[0x43] = KC_F9,
+	[0x44] = KC_F10,
+
+	[0x57] = KC_F11,
+	[0x58] = KC_F12,
+
+	[0x46] = KC_SCROLL_LOCK,
+
+	[0x1c] = KC_ENTER,
+
+	[0x45] = KC_NUM_LOCK,
+	[0x37] = KC_NTIMES,
+	[0x4a] = KC_NMINUS,
+	[0x4e] = KC_NPLUS,
+	[0x47] = KC_N7,
+	[0x48] = KC_N8,
+	[0x49] = KC_N9,
+	[0x4b] = KC_N4,
+	[0x4c] = KC_N5,
+	[0x4d] = KC_N6,
+	[0x4f] = KC_N1,
+	[0x50] = KC_N2,
+	[0x51] = KC_N3,
+	[0x52] = KC_N0,
+	[0x53] = KC_NPERIOD
+};
+
+static int scanmap_e0[] = {
+	[0x38] = KC_RALT,
+	[0x1d] = KC_RSHIFT,
+
+	[0x37] = KC_PRTSCR,
+
+	[0x52] = KC_INSERT,
+	[0x47] = KC_HOME,
+	[0x49] = KC_PAGE_UP,
+
+	[0x53] = KC_DELETE,
+	[0x4f] = KC_END,
+	[0x51] = KC_PAGE_DOWN,
+
+	[0x48] = KC_UP,
+	[0x4b] = KC_LEFT,
+	[0x50] = KC_DOWN,
+	[0x4d] = KC_RIGHT,
+
+	[0x35] = KC_NSLASH,
+	[0x1c] = KC_NENTER
+};
+
+static int pc_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	ds = ds_s;
+	return 0;
+}
+
+static void pc_ctl_parse(sysarg_t scancode)
+{
+	kbd_event_type_t type;
+	unsigned int key;
+	int *map;
+	size_t map_length;
+
+	/*
+	 * ACK/NAK are returned as response to us sending a command.
+	 * We are not interested in them.
+	 */
+	if (scancode == SC_ACK || scancode == SC_NAK)
+		return;
+
+	if (scancode == 0xe0) {
+		ds = ds_e;
+		return;
+	}
+
+	switch (ds) {
+	case ds_s:
+		map = scanmap_simple;
+		map_length = sizeof(scanmap_simple) / sizeof(int);
+		break;
+	case ds_e:
+		map = scanmap_e0;
+		map_length = sizeof(scanmap_e0) / sizeof(int);
+		break;
+	default:
+		map = NULL;
+		map_length = 0;
+	}
+
+	ds = ds_s;
+
+	if (scancode & 0x80) {
+		scancode &= ~0x80;
+		type = KEY_RELEASE;
+	} else {
+		type = KEY_PRESS;
+	}
+
+	if ((size_t) scancode >= map_length)
+		return;
+
+	key = map[scancode];
+	if (key != 0)
+		kbd_push_event(kbd_dev, type, key);
+}
+
+static void pc_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	uint8_t b;
+
+	b = 0;
+	if ((mods & KM_CAPS_LOCK) != 0)
+		b = b | LI_CAPS;
+	if ((mods & KM_NUM_LOCK) != 0)
+		b = b | LI_NUM;
+	if ((mods & KM_SCROLL_LOCK) != 0)
+		b = b | LI_SCROLL;
+
+	(*kbd_dev->port_ops->write)(KBD_CMD_SET_LEDS);
+	(*kbd_dev->port_ops->write)(b);
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/ctl/stty.c
===================================================================
--- uspace/srv/hid/input/ctl/stty.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/ctl/stty.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Serial TTY-like keyboard controller driver.
+ *
+ * Keyboard emulation on a serial terminal.
+ */
+
+#include <kbd.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+#include <gsp.h>
+#include <stroke.h>
+
+static void stty_ctl_parse(sysarg_t);
+static int stty_ctl_init(kbd_dev_t *);
+static void stty_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t stty_ctl = {
+	.parse = stty_ctl_parse,
+	.init = stty_ctl_init,
+	.set_ind = stty_ctl_set_ind
+};
+
+static kbd_dev_t *kbd_dev;
+
+/** Scancode parser */
+static gsp_t sp;
+
+/** Current parser state */
+static int ds;
+
+#include <stdio.h>
+
+/**
+ * Sequnece definitions are primarily for Xterm. Additionally we define
+ * sequences that are unique to Gnome terminal -- most are the same but
+ * some differ.
+ */
+static int seq_defs[] = {
+	/* Not shifted */
+
+	0,	KC_BACKTICK,	0x60, GSP_END,
+
+	0,	KC_1,		0x31, GSP_END,
+	0,	KC_2,		0x32, GSP_END,
+	0,	KC_3,		0x33, GSP_END,
+	0,	KC_4,		0x34, GSP_END,
+	0,	KC_5,		0x35, GSP_END,
+	0,	KC_6,		0x36, GSP_END,
+	0,	KC_7,		0x37, GSP_END,
+	0,	KC_8,		0x38, GSP_END,
+	0,	KC_9,		0x39, GSP_END,
+	0,	KC_0,		0x30, GSP_END,
+
+	0,	KC_MINUS,	0x2d, GSP_END,
+	0,	KC_EQUALS,	0x3d, GSP_END,
+
+	0,	KC_BACKSPACE,	0x08, GSP_END,
+
+	0,	KC_TAB,		0x09, GSP_END,
+
+	0,	KC_Q,		0x71, GSP_END,
+	0,	KC_W,		0x77, GSP_END,
+	0,	KC_E,		0x65, GSP_END,
+	0,	KC_R,		0x72, GSP_END,
+	0,	KC_T,		0x74, GSP_END,
+	0,	KC_Y,		0x79, GSP_END,
+	0,	KC_U,		0x75, GSP_END,
+	0,	KC_I,		0x69, GSP_END,
+	0,	KC_O,		0x6f, GSP_END,
+	0,	KC_P,		0x70, GSP_END,
+
+	0,	KC_LBRACKET,	0x5b, GSP_END,
+	0,	KC_RBRACKET,	0x5d, GSP_END,
+
+	0,	KC_A,		0x61, GSP_END,
+	0,	KC_S,		0x73, GSP_END,
+	0,	KC_D,		0x64, GSP_END,
+	0,	KC_F,		0x66, GSP_END,
+	0,	KC_G,		0x67, GSP_END,
+	0,	KC_H,		0x68, GSP_END,
+	0,	KC_J,		0x6a, GSP_END,
+	0,	KC_K,		0x6b, GSP_END,
+	0,	KC_L,		0x6c, GSP_END,
+
+	0,	KC_SEMICOLON,	0x3b, GSP_END,
+	0,	KC_QUOTE,	0x27, GSP_END,
+	0,	KC_BACKSLASH,	0x5c, GSP_END,
+
+	0,	KC_Z,		0x7a, GSP_END,
+	0,	KC_X,		0x78, GSP_END,
+	0,	KC_C,		0x63, GSP_END,
+	0,	KC_V,		0x76, GSP_END,
+	0,	KC_B,		0x62, GSP_END,
+	0,	KC_N,		0x6e, GSP_END,
+	0,	KC_M,		0x6d, GSP_END,
+
+	0,	KC_COMMA,	0x2c, GSP_END,
+	0,	KC_PERIOD,	0x2e, GSP_END,
+	0,	KC_SLASH,	0x2f, GSP_END,
+
+	/* Shifted */
+
+	KM_SHIFT,	KC_BACKTICK,	0x7e, GSP_END,
+
+	KM_SHIFT,	KC_1,		0x21, GSP_END,
+	KM_SHIFT,	KC_2,		0x40, GSP_END,
+	KM_SHIFT,	KC_3,		0x23, GSP_END,
+	KM_SHIFT,	KC_4,		0x24, GSP_END,
+	KM_SHIFT,	KC_5,		0x25, GSP_END,
+	KM_SHIFT,	KC_6,		0x5e, GSP_END,
+	KM_SHIFT,	KC_7,		0x26, GSP_END,
+	KM_SHIFT,	KC_8,		0x2a, GSP_END,
+	KM_SHIFT,	KC_9,		0x28, GSP_END,
+	KM_SHIFT,	KC_0,		0x29, GSP_END,
+
+	KM_SHIFT,	KC_MINUS,	0x5f, GSP_END,
+	KM_SHIFT,	KC_EQUALS,	0x2b, GSP_END,
+
+	KM_SHIFT,	KC_Q,		0x51, GSP_END,
+	KM_SHIFT,	KC_W,		0x57, GSP_END,
+	KM_SHIFT,	KC_E,		0x45, GSP_END,
+	KM_SHIFT,	KC_R,		0x52, GSP_END,
+	KM_SHIFT,	KC_T,		0x54, GSP_END,
+	KM_SHIFT,	KC_Y,		0x59, GSP_END,
+	KM_SHIFT,	KC_U,		0x55, GSP_END,
+	KM_SHIFT,	KC_I,		0x49, GSP_END,
+	KM_SHIFT,	KC_O,		0x4f, GSP_END,
+	KM_SHIFT,	KC_P,		0x50, GSP_END,
+
+	KM_SHIFT,	KC_LBRACKET,	0x7b, GSP_END,
+	KM_SHIFT,	KC_RBRACKET,	0x7d, GSP_END,
+
+	KM_SHIFT,	KC_A,		0x41, GSP_END,
+	KM_SHIFT,	KC_S,		0x53, GSP_END,
+	KM_SHIFT,	KC_D,		0x44, GSP_END,
+	KM_SHIFT,	KC_F,		0x46, GSP_END,
+	KM_SHIFT,	KC_G,		0x47, GSP_END,
+	KM_SHIFT,	KC_H,		0x48, GSP_END,
+	KM_SHIFT,	KC_J,		0x4a, GSP_END,
+	KM_SHIFT,	KC_K,		0x4b, GSP_END,
+	KM_SHIFT,	KC_L,		0x4c, GSP_END,
+
+	KM_SHIFT,	KC_SEMICOLON,	0x3a, GSP_END,
+	KM_SHIFT,	KC_QUOTE,	0x22, GSP_END,
+	KM_SHIFT,	KC_BACKSLASH,	0x7c, GSP_END,
+
+	KM_SHIFT,	KC_Z,		0x5a, GSP_END,
+	KM_SHIFT,	KC_X,		0x58, GSP_END,
+	KM_SHIFT,	KC_C,		0x43, GSP_END,
+	KM_SHIFT,	KC_V,		0x56, GSP_END,
+	KM_SHIFT,	KC_B,		0x42, GSP_END,
+	KM_SHIFT,	KC_N,		0x4e, GSP_END,
+	KM_SHIFT,	KC_M,		0x4d, GSP_END,
+
+	KM_SHIFT,	KC_COMMA,	0x3c, GSP_END,
+	KM_SHIFT,	KC_PERIOD,	0x3e, GSP_END,
+	KM_SHIFT,	KC_SLASH,	0x3f, GSP_END,
+
+	/* ... */
+
+	0,	KC_SPACE,	0x20, GSP_END,
+	0,	KC_ENTER,	0x0a, GSP_END,
+	0,	KC_ENTER,	0x0d, GSP_END,
+
+	0,	KC_ESCAPE,	0x1b, 0x1b, GSP_END,
+
+	0,	KC_F1,		0x1b, 0x4f, 0x50, GSP_END,
+	0,	KC_F2,		0x1b, 0x4f, 0x51, GSP_END,
+	0,	KC_F3,		0x1b, 0x4f, 0x52, GSP_END,
+	0,	KC_F4,		0x1b, 0x4f, 0x53, GSP_END,
+	0,	KC_F5,		0x1b, 0x5b, 0x31, 0x35, 0x7e, GSP_END,
+	0,	KC_F6,		0x1b, 0x5b, 0x31, 0x37, 0x7e, GSP_END,
+	0,	KC_F7,		0x1b, 0x5b, 0x31, 0x38, 0x7e, GSP_END,
+	0,	KC_F8,		0x1b, 0x5b, 0x31, 0x39, 0x7e, GSP_END,
+	0,	KC_F9,		0x1b, 0x5b, 0x32, 0x30, 0x7e, GSP_END,
+	0,	KC_F10,		0x1b, 0x5b, 0x32, 0x31, 0x7e, GSP_END,
+	0,	KC_F11,		0x1b, 0x5b, 0x32, 0x33, 0x7e, GSP_END,
+	0,	KC_F12,		0x1b, 0x5b, 0x32, 0x34, 0x7e, GSP_END,
+
+	0,	KC_INSERT,	0x1b, 0x5b, 0x32, 0x7e, GSP_END,
+	0,	KC_HOME,	0x1b, 0x5b, 0x48, GSP_END,
+	0,	KC_PAGE_UP,	0x1b, 0x5b, 0x35, 0x7e, GSP_END,
+	0,	KC_DELETE,	0x1b, 0x5b, 0x33, 0x7e, GSP_END,
+	0,	KC_END,		0x1b, 0x5b, 0x46, GSP_END,
+	0,	KC_PAGE_DOWN,	0x1b, 0x5b, 0x36, 0x7e, GSP_END,
+
+	0,	KC_UP,		0x1b, 0x5b, 0x41, GSP_END,
+	0,	KC_LEFT,	0x1b, 0x5b, 0x44, GSP_END,
+	0,	KC_DOWN,	0x1b, 0x5b, 0x42, GSP_END,
+	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
+
+	/*
+	 * Sequences specific to Gnome terminal
+	 */
+	0,	KC_BACKSPACE,	0x7f, GSP_END, /* ASCII DEL */
+	0,	KC_HOME,	0x1b, 0x4f, 0x48, GSP_END,
+	0,	KC_END,		0x1b, 0x4f, 0x46, GSP_END,
+
+	0,	0
+};
+
+static int stty_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	ds = 0;
+
+	gsp_init(&sp);
+	return gsp_insert_defs(&sp, seq_defs);
+}
+
+static void stty_ctl_parse(sysarg_t scancode)
+{
+	unsigned mods, key;
+
+	ds = gsp_step(&sp, ds, scancode, &mods, &key);
+	if (key != 0) {
+		stroke_sim(kbd_dev, mods, key);
+	}
+}
+
+static void stty_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	(void) mods;
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/ctl/sun.c
===================================================================
--- uspace/srv/hid/input/ctl/sun.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/ctl/sun.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2006 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Sun keyboard controller driver.
+ */
+
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+
+static void sun_ctl_parse(sysarg_t);
+static int sun_ctl_init(kbd_dev_t *);
+static void sun_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t sun_ctl = {
+	.parse = sun_ctl_parse,
+	.init = sun_ctl_init,
+	.set_ind = sun_ctl_set_ind
+};
+
+static kbd_dev_t *kbd_dev;
+
+#define KBD_KEY_RELEASE		0x80
+#define KBD_ALL_KEYS_UP		0x7f
+
+static int scanmap_simple[];
+
+static int sun_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	return 0;
+}
+
+static void sun_ctl_parse(sysarg_t scancode)
+{
+	kbd_event_type_t type;
+	unsigned int key;
+
+	if (scancode >= 0x100)
+		return;
+
+	if (scancode == KBD_ALL_KEYS_UP)
+		return;
+
+	if (scancode & KBD_KEY_RELEASE) {
+		scancode &= ~KBD_KEY_RELEASE;
+		type = KEY_RELEASE;
+	} else {
+		type = KEY_PRESS;
+	}
+
+	key = scanmap_simple[scancode];
+	if (key != 0)
+		kbd_push_event(kbd_dev, type, key);
+}
+
+static void sun_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	(void) mods;
+}
+
+/** Primary meaning of scancodes. */
+static int scanmap_simple[] = {
+	[0x00] = 0,
+	[0x01] = 0,
+	[0x02] = 0,
+	[0x03] = 0,
+	[0x04] = 0,
+	[0x05] = KC_F1,
+	[0x06] = KC_F2,
+	[0x07] = KC_F10,
+	[0x08] = KC_F3,
+	[0x09] = KC_F11,
+	[0x0a] = KC_F4,
+	[0x0b] = KC_F12,
+	[0x0c] = KC_F5,
+	[0x0d] = KC_RALT,
+	[0x0e] = KC_F6,
+	[0x0f] = 0,
+	[0x10] = KC_F7,
+	[0x11] = KC_F8,
+	[0x12] = KC_F9,
+	[0x13] = KC_LALT,
+	[0x14] = KC_UP,
+	[0x15] = KC_PAUSE,
+	[0x16] = 0,
+	[0x17] = KC_SCROLL_LOCK,
+	[0x18] = KC_LEFT,
+	[0x19] = 0,
+	[0x1a] = 0,
+	[0x1b] = KC_DOWN,
+	[0x1c] = KC_RIGHT,
+	[0x1d] = KC_ESCAPE,
+	[0x1e] = KC_1,
+	[0x1f] = KC_2,
+	[0x20] = KC_3,
+	[0x21] = KC_4,
+	[0x22] = KC_5,
+	[0x23] = KC_6,
+	[0x24] = KC_7,
+	[0x25] = KC_8,
+	[0x26] = KC_9,
+	[0x27] = KC_0,
+	[0x28] = KC_MINUS,
+	[0x29] = KC_EQUALS,
+	[0x2a] = KC_BACKTICK,
+	[0x2b] = KC_BACKSPACE,
+	[0x2c] = KC_INSERT,
+	[0x2d] = 0,
+	[0x2e] = KC_NSLASH,
+	[0x2f] = KC_NTIMES,
+	[0x30] = 0,
+	[0x31] = 0,
+	[0x32] = KC_NPERIOD,
+	[0x33] = 0,
+	[0x34] = KC_HOME,
+	[0x35] = KC_TAB,
+	[0x36] = KC_Q,
+	[0x37] = KC_W,
+	[0x38] = KC_E,
+	[0x39] = KC_R,
+	[0x3a] = KC_T,
+	[0x3b] = KC_Y,
+	[0x3c] = KC_U,
+	[0x3d] = KC_I,
+	[0x3e] = KC_O,
+	[0x3f] = KC_P,
+	[0x40] = KC_LBRACKET,
+	[0x41] = KC_RBRACKET,
+	[0x42] = KC_DELETE,
+	[0x43] = 0,
+	[0x44] = KC_N7,
+	[0x45] = KC_N8,
+	[0x46] = KC_N9,
+	[0x47] = KC_NMINUS,
+	[0x48] = 0,
+	[0x49] = 0,
+	[0x4a] = KC_END,
+	[0x4b] = 0,
+	[0x4c] = KC_LCTRL,
+	[0x4d] = KC_A,
+	[0x4e] = KC_S,
+	[0x4f] = KC_D,
+	[0x50] = KC_F,
+	[0x51] = KC_G,
+	[0x52] = KC_H,
+	[0x53] = KC_J,
+	[0x54] = KC_K,
+	[0x55] = KC_L,
+	[0x56] = KC_SEMICOLON,
+	[0x57] = KC_QUOTE,
+	[0x58] = KC_BACKSLASH,
+	[0x59] = KC_ENTER,
+	[0x5a] = KC_NENTER,
+	[0x5b] = KC_N4,
+	[0x5c] = KC_N5,
+	[0x5d] = KC_N6,
+	[0x5e] = KC_N0,
+	[0x5f] = 0,
+	[0x60] = KC_PAGE_UP,
+	[0x61] = 0,
+	[0x62] = KC_NUM_LOCK,
+	[0x63] = KC_LSHIFT,
+	[0x64] = KC_Z,
+	[0x65] = KC_X,
+	[0x66] = KC_C,
+	[0x67] = KC_V,
+	[0x68] = KC_B,
+	[0x69] = KC_N,
+	[0x6a] = KC_M,
+	[0x6b] = KC_COMMA,
+	[0x6c] = KC_PERIOD,
+	[0x6d] = KC_SLASH,
+	[0x6e] = KC_RSHIFT,
+	[0x6f] = 0,
+	[0x70] = KC_N1,
+	[0x71] = KC_N2,
+	[0x72] = KC_N3,
+	[0x73] = 0,
+	[0x74] = 0,
+	[0x75] = 0,
+	[0x76] = 0,
+	[0x77] = KC_CAPS_LOCK,
+	[0x78] = 0,
+	[0x79] = KC_SPACE,
+	[0x7a] = 0,
+	[0x7b] = KC_PAGE_DOWN,
+	[0x7c] = 0,
+	[0x7d] = KC_NPLUS,
+	[0x7e] = 0,
+	[0x7f] = 0
+};
+
+/** @}
+ */
Index: uspace/srv/hid/input/generic/gsp.c
===================================================================
--- uspace/srv/hid/input/generic/gsp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/generic/gsp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,291 @@
+/*
+ * 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 kbdgen generic
+ * @ingroup  input
+ * @{
+ */ 
+/** @file
+ * @brief	Generic scancode parser.
+ *
+ * The scancode parser is a simple finite state machine. It is described
+ * using sequences of input symbols (scancodes) and the corresponding output
+ * value (mods, key pair). When the parser recognizes a sequence,
+ * it outputs the value and restarts. If a transition is undefined,
+ * the parser restarts, too.
+ *
+ * Apart from precise values, GSP_DEFAULT allows to catch general cases.
+ * I.e. if we knew that after 0x1b 0x4f there always follow two more
+ * scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END)
+ * with null output. This will force the parser to read the entire sequence,
+ * not leaving garbage on the input if it does not recognize the specific
+ * sequence.
+ */
+
+#include <gsp.h>
+#include <adt/hash_table.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define TRANS_TABLE_CHAINS 256
+
+/*
+ * Hash table operations for the transition function.
+ */
+
+static hash_index_t trans_op_hash(unsigned long key[]);
+static int trans_op_compare(unsigned long key[], hash_count_t keys,
+    link_t *item);
+static void trans_op_remove_callback(link_t *item);
+
+static hash_table_operations_t trans_ops = {
+	.hash = trans_op_hash,
+	.compare = trans_op_compare,
+	.remove_callback = trans_op_remove_callback
+};
+
+static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
+static void trans_insert(gsp_t *p, gsp_trans_t *t);
+static gsp_trans_t *trans_new(void);
+
+/** Initialise scancode parser. */
+void gsp_init(gsp_t *p)
+{
+	p->states = 1;
+	hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);
+}
+
+/** Insert a series of definitions into the parser.
+ *
+ * @param p	The parser.
+ * @param defs	Definition list. Each definition starts with two output values
+ *		(mods, key) and continues with a sequence of input values
+ *		terminated with GSP_END. The definition list is terminated
+ *		with two zeroes (0, 0) for output values.
+ */
+int gsp_insert_defs(gsp_t *p, const int *defs)
+{
+	unsigned mods, key;
+	const int *dp;
+	int rc;
+
+	dp = defs;
+
+	while (1) {
+		/* Read the output values. */
+		mods = *dp++;
+		key = *dp++;
+		if (key == 0) break;
+
+		/* Insert one sequence. */
+		rc = gsp_insert_seq(p, dp, mods, key);
+		if (rc != 0)
+			return rc;
+
+		/* Skip to the next definition. */
+		while (*dp != GSP_END)
+			++dp;
+		++dp;
+	}
+
+	return 0;
+}
+
+/** Insert one sequence into the parser.
+ *
+ * @param p	The parser.
+ * @param seq	Sequence of input values terminated with GSP_END.
+ * @param mods	Corresponsing output value.
+ * @param key	Corresponsing output value.
+ */
+int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
+{
+	int state;
+	gsp_trans_t *t;
+
+	state = 0;
+	t = NULL;
+
+	/* Input sequence must be non-empty. */
+	if (*seq == GSP_END)
+		return -1;
+
+	while (*(seq + 1) != GSP_END) {
+		t = trans_lookup(p, state, *seq);
+		if (t == NULL) {
+			/* Create new state. */
+			t = trans_new();
+			t->old_state = state;
+			t->input = *seq;
+			t->new_state = p->states++;
+
+			t->out_mods = 0;
+			t->out_key = 0;
+
+			trans_insert(p, t);
+		}
+		state = t->new_state;
+		++seq;
+	}
+
+	/* Process the last transition. */
+	t = trans_lookup(p, state, *seq);
+	if (t != NULL) {
+		exit(1);
+		return -1;	/* Conflicting definition. */
+	}
+
+	t = trans_new();
+	t->old_state = state;
+	t->input = *seq;
+	t->new_state = 0;
+
+	t->out_mods = mods;
+	t->out_key = key;
+
+	trans_insert(p, t);
+
+	return 0;
+}
+
+/** Compute one parser step.
+ *
+ * Computes the next state and output values for a given state and input.
+ * This handles everything including restarts and default branches.
+ *
+ * @param p		The parser.
+ * @param state		Old state.
+ * @param input		Input symbol (scancode).
+ * @param mods		Output value (modifier).
+ * @param key		Output value (key).
+ * @return		New state.
+ */
+int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
+{
+	gsp_trans_t *t;
+
+	t = trans_lookup(p, state, input);
+	if (t == NULL) {
+		t = trans_lookup(p, state, GSP_DEFAULT);
+	}
+
+	if (t == NULL) {
+		printf("gsp_step: not found, state=%d, input=0x%x\n",
+		    state, input);
+		*mods = 0;
+		*key = 0;
+		return 0;
+	}
+
+	*mods = t->out_mods;
+	*key = t->out_key;
+
+	return t->new_state;
+}
+
+/** Transition function lookup.
+ *
+ * Returns the value of the transition function for the given state
+ * and input. Note that the transition must be specified precisely,
+ * to obtain the default branch use input = GSP_DEFAULT.
+ *
+ * @param p		Parser.
+ * @param state		Current state.
+ * @param input		Input value.
+ * @return		The transition or @c NULL if not defined.
+ */
+static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
+{
+	link_t *item;
+	unsigned long key[2];
+
+	key[0] = state;
+	key[1] = input;
+
+	item = hash_table_find(&p->trans, key);
+	if (item == NULL) return NULL;
+
+	return hash_table_get_instance(item, gsp_trans_t, link);
+}
+
+/** Define a new transition.
+ *
+ * @param p	The parser.
+ * @param t	Transition with all fields defined.
+ */
+static void trans_insert(gsp_t *p, gsp_trans_t *t)
+{
+	unsigned long key[2];
+
+	key[0] = t->old_state;
+	key[1] = t->input;
+
+	hash_table_insert(&p->trans, key, &t->link);
+}
+
+/** Allocate transition structure. */
+static gsp_trans_t *trans_new(void)
+{
+	gsp_trans_t *t;
+
+	t = malloc(sizeof(gsp_trans_t));
+	if (t == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return t;
+}
+
+/*
+ * Transition function hash table operations.
+ */
+
+static hash_index_t trans_op_hash(unsigned long key[])
+{
+	return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS;
+}
+
+static int trans_op_compare(unsigned long key[], hash_count_t keys,
+    link_t *item)
+{
+	gsp_trans_t *t;
+
+	t = hash_table_get_instance(item, gsp_trans_t, link);
+	return ((key[0] == (unsigned long) t->old_state)
+	    && (key[1] == (unsigned long) t->input));
+}
+
+static void trans_op_remove_callback(link_t *item)
+{
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/generic/input.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#include <adt/list.h>
+#include <bool.h>
+#include <ipc/services.h>
+#include <ipc/input.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ns.h>
+#include <ns_obsolete.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <errno.h>
+#include <adt/fifo.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <loc.h>
+#include <input.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <kbd_ctl.h>
+#include <mouse_proto.h>
+#include <layout.h>
+#include <mouse.h>
+
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
+
+#define NUM_LAYOUTS  3
+
+static layout_ops_t *layout[NUM_LAYOUTS] = {
+	&us_qwerty_ops,
+	&us_dvorak_ops,
+	&cz_ops
+};
+
+static void kbd_devs_yield(void);
+static void kbd_devs_reclaim(void);
+
+int client_phone = -1;
+
+/** List of keyboard devices */
+static list_t kbd_devs;
+
+/** List of mouse devices */
+static list_t mouse_devs;
+
+bool irc_service = false;
+int irc_phone = -1;
+
+void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
+{
+	(*kdev->ctl_ops->parse)(data);
+}
+
+void mouse_push_data(mouse_dev_t *mdev, sysarg_t data)
+{
+	(*mdev->proto_ops->parse)(data);
+}
+
+void kbd_push_event(kbd_dev_t *kdev, int type, unsigned int key)
+{
+	kbd_event_t ev;
+	unsigned int mod_mask;
+	
+	switch (key) {
+	case KC_LCTRL: mod_mask = KM_LCTRL; break;
+	case KC_RCTRL: mod_mask = KM_RCTRL; break;
+	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
+	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
+	case KC_LALT: mod_mask = KM_LALT; break;
+	case KC_RALT: mod_mask = KM_RALT; break;
+	default: mod_mask = 0; break;
+	}
+	
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS)
+			kdev->mods = kdev->mods | mod_mask;
+		else
+			kdev->mods = kdev->mods & ~mod_mask;
+	}
+	
+	switch (key) {
+	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
+	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
+	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
+	default: mod_mask = 0; break;
+	}
+	
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS) {
+			/*
+			 * Only change lock state on transition from released
+			 * to pressed. This prevents autorepeat from messing
+			 * up the lock state.
+			 */
+			kdev->mods = kdev->mods ^ (mod_mask & ~kdev->lock_keys);
+			kdev->lock_keys = kdev->lock_keys | mod_mask;
+			
+			/* Update keyboard lock indicator lights. */
+			(*kdev->ctl_ops->set_ind)(kdev, kdev->mods);
+		} else {
+			kdev->lock_keys = kdev->lock_keys & ~mod_mask;
+		}
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F1) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[0]);
+		return;
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F2) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[1]);
+		return;
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F3) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[2]);
+		return;
+	}
+	
+	ev.type = type;
+	ev.key = key;
+	ev.mods = kdev->mods;
+	
+	ev.c = layout_parse_ev(kdev->active_layout, &ev);
+	async_obsolete_msg_4(client_phone, INPUT_EVENT_KEY, ev.type, ev.key,
+	    ev.mods, ev.c);
+}
+
+/** Mouse pointer has moved. */
+void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy)
+{
+	async_obsolete_msg_2(client_phone, INPUT_EVENT_MOVE, dx, dy);
+}
+
+/** Mouse button has been pressed. */
+void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press)
+{
+	async_obsolete_msg_2(client_phone, INPUT_EVENT_BUTTON, bnum, press);
+}
+
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	int retval;
+	
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			if (client_phone != -1) {
+				async_obsolete_hangup(client_phone);
+				client_phone = -1;
+			}
+			
+			async_answer_0(callid, EOK);
+			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case IPC_M_CONNECT_TO_ME:
+			if (client_phone != -1) {
+				retval = ELIMIT;
+				break;
+			}
+			client_phone = IPC_GET_ARG5(call);
+			retval = 0;
+			break;
+		case INPUT_YIELD:
+			kbd_devs_yield();
+			retval = 0;
+			break;
+		case INPUT_RECLAIM:
+			kbd_devs_reclaim();
+			retval = 0;
+			break;
+		default:
+			retval = EINVAL;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static kbd_dev_t *kbd_dev_new(void)
+{
+	kbd_dev_t *kdev = calloc(1, sizeof(kbd_dev_t));
+	if (kdev == NULL) {
+		printf("%s: Error allocating keyboard device. "
+		    "Out of memory.\n", NAME);
+		return NULL;
+	}
+	
+	link_initialize(&kdev->kbd_devs);
+	
+	kdev->mods = KM_NUM_LOCK;
+	kdev->lock_keys = 0;
+	kdev->active_layout = layout_create(layout[0]);
+	
+	return kdev;
+}
+
+static mouse_dev_t *mouse_dev_new(void)
+{
+	mouse_dev_t *mdev = calloc(1, sizeof(mouse_dev_t));
+	if (mdev == NULL) {
+		printf("%s: Error allocating keyboard device. "
+		    "Out of memory.\n", NAME);
+		return NULL;
+	}
+	
+	link_initialize(&mdev->mouse_devs);
+	
+	return mdev;
+}
+
+/** Add new legacy keyboard device. */
+static void kbd_add_dev(kbd_port_ops_t *port, kbd_ctl_ops_t *ctl)
+{
+	kbd_dev_t *kdev = kbd_dev_new();
+	if (kdev == NULL)
+		return;
+	
+	kdev->port_ops = port;
+	kdev->ctl_ops = ctl;
+	kdev->svc_id = 0;
+	
+	/* Initialize port driver. */
+	if ((*kdev->port_ops->init)(kdev) != 0)
+		goto fail;
+	
+	/* Initialize controller driver. */
+	if ((*kdev->ctl_ops->init)(kdev) != 0) {
+		/* XXX Uninit port */
+		goto fail;
+	}
+	
+	list_append(&kdev->kbd_devs, &kbd_devs);
+	return;
+	
+fail:
+	free(kdev);
+}
+
+/** Add new legacy mouse device. */
+static void mouse_add_dev(mouse_port_ops_t *port, mouse_proto_ops_t *proto)
+{
+	mouse_dev_t *mdev = mouse_dev_new();
+	if (mdev == NULL)
+		return;
+	
+	mdev->port_ops = port;
+	mdev->proto_ops = proto;
+	mdev->svc_id = 0;
+	
+	/* Initialize port driver. */
+	if ((*mdev->port_ops->init)(mdev) != 0)
+		goto fail;
+	
+	/* Initialize protocol driver. */
+	if ((*mdev->proto_ops->init)(mdev) != 0) {
+		/* XXX Uninit port */
+		goto fail;
+	}
+	
+	list_append(&mdev->mouse_devs, &mouse_devs);
+	return;
+	
+fail:
+	free(mdev);
+}
+
+/** Add new kbdev device.
+ *
+ * @param service_id	Service ID of the keyboard device
+ *
+ */
+static int kbd_add_kbdev(service_id_t service_id, kbd_dev_t **kdevp)
+{
+	kbd_dev_t *kdev = kbd_dev_new();
+	if (kdev == NULL)
+		return -1;
+	
+	kdev->svc_id = service_id;
+	kdev->port_ops = NULL;
+	kdev->ctl_ops = &kbdev_ctl;
+	
+	int rc = loc_service_get_name(service_id, &kdev->svc_name);
+	if (rc != EOK) {
+		kdev->svc_name = NULL;
+		goto fail;
+	}
+	
+	/* Initialize controller driver. */
+	if ((*kdev->ctl_ops->init)(kdev) != 0) {
+		goto fail;
+	}
+	
+	list_append(&kdev->kbd_devs, &kbd_devs);
+	*kdevp = kdev;
+	return EOK;
+	
+fail:
+	if (kdev->svc_name != NULL)
+		free(kdev->svc_name);
+	free(kdev);
+	return -1;
+}
+
+/** Add new mousedev device.
+ *
+ * @param service_id	Service ID of the mouse device
+ *
+ */
+static int mouse_add_mousedev(service_id_t service_id, mouse_dev_t **mdevp)
+{
+	mouse_dev_t *mdev = mouse_dev_new();
+	if (mdev == NULL)
+		return -1;
+	
+	mdev->svc_id = service_id;
+	mdev->port_ops = NULL;
+	mdev->proto_ops = &mousedev_proto;
+	
+	int rc = loc_service_get_name(service_id, &mdev->svc_name);
+	if (rc != EOK) {
+		mdev->svc_name = NULL;
+		goto fail;
+	}
+	
+	/* Initialize controller driver. */
+	if ((*mdev->proto_ops->init)(mdev) != 0) {
+		goto fail;
+	}
+	
+	list_append(&mdev->mouse_devs, &mouse_devs);
+	*mdevp = mdev;
+	return EOK;
+	
+fail:
+	free(mdev);
+	return -1;
+}
+
+/** Add legacy drivers/devices. */
+static void kbd_add_legacy_devs(void)
+{
+	/*
+	 * Need to add these drivers based on config unless we can probe
+	 * them automatically.
+	 */
+#if defined(UARCH_amd64)
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_gta02)
+	kbd_add_dev(&chardev_port, &stty_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_testarm) && defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_testarm) && !defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &stty_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_integratorcp)
+	kbd_add_dev(&pl050_port, &pc_ctl);
+#endif
+#if defined(UARCH_ia32)
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(MACHINE_i460GX)
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(MACHINE_ski)
+	kbd_add_dev(&ski_port, &stty_ctl);
+#endif
+#if defined(MACHINE_msim)
+	kbd_add_dev(&msim_port, &stty_ctl);
+#endif
+#if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
+#endif
+#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) && !defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &stty_ctl);
+#endif
+#if defined(UARCH_ppc32)
+	kbd_add_dev(&adb_port, &apple_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(PROCESSOR_sun4v)
+	kbd_add_dev(&niagara_port, &stty_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(MACHINE_generic)
+	kbd_add_dev(&ns16550_port, &sun_ctl);
+#endif
+	/* Silence warning on abs32le about kbd_add_dev() being unused */
+	(void) kbd_add_dev;
+}
+
+/** Add legacy drivers/devices. */
+static void mouse_add_legacy_devs(void)
+{
+	/*
+	 * Need to add these drivers based on config unless we can probe
+	 * them automatically.
+	 */
+#if defined(UARCH_amd64)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(UARCH_ia32)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(MACHINE_i460GX)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(UARCH_ppc32)
+	mouse_add_dev(&adb_mouse_port, &adb_proto);
+#endif
+	/* Silence warning on abs32le about mouse_add_dev() being unused */
+	(void) mouse_add_dev;
+}
+
+static void kbd_devs_yield(void)
+{
+	/* For each keyboard device */
+	list_foreach(kbd_devs, kdev_link) {
+		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
+		    kbd_devs);
+		
+		/* Yield port */
+		if (kdev->port_ops != NULL)
+			(*kdev->port_ops->yield)();
+	}
+}
+
+static void kbd_devs_reclaim(void)
+{
+	/* For each keyboard device */
+	list_foreach(kbd_devs, kdev_link) {
+		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
+		    kbd_devs);
+		
+		/* Reclaim port */
+		if (kdev->port_ops != NULL)
+			(*kdev->port_ops->reclaim)();
+	}
+}
+
+static int dev_check_new_kbdevs(void)
+{
+	category_id_t keyboard_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	bool already_known;
+	int rc;
+	
+	rc = loc_category_get_id("keyboard", &keyboard_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Failed resolving category 'keyboard'.\n", NAME);
+		return ENOENT;
+	}
+	
+	/*
+	 * Check for new keyboard devices
+	 */
+	rc = loc_category_get_svcs(keyboard_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf("%s: Failed getting list of keyboard devices.\n",
+		    NAME);
+		return EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		already_known = false;
+		
+		/* Determine whether we already know this device. */
+		list_foreach(kbd_devs, kdev_link) {
+			kbd_dev_t *kdev = list_get_instance(kdev_link,
+			    kbd_dev_t, kbd_devs);
+			if (kdev->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+		
+		if (!already_known) {
+			kbd_dev_t *kdev;
+			if (kbd_add_kbdev(svcs[i], &kdev) == EOK) {
+				printf("%s: Connected keyboard device '%s'\n",
+				    NAME, kdev->svc_name);
+			}
+		}
+	}
+	
+	free(svcs);
+	
+	/* XXX Handle device removal */
+	
+	return EOK;
+}
+
+static int dev_check_new_mousedevs(void)
+{
+	category_id_t mouse_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	bool already_known;
+	int rc;
+	
+	rc = loc_category_get_id("mouse", &mouse_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		printf("%s: Failed resolving category 'mouse'.\n", NAME);
+		return ENOENT;
+	}
+	
+	/*
+	 * Check for new mouse devices
+	 */
+	rc = loc_category_get_svcs(mouse_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf("%s: Failed getting list of mouse devices.\n",
+		    NAME);
+		return EIO;
+	}
+	
+	for (i = 0; i < count; i++) {
+		already_known = false;
+		
+		/* Determine whether we already know this device. */
+		list_foreach(mouse_devs, mdev_link) {
+			mouse_dev_t *mdev = list_get_instance(mdev_link,
+			    mouse_dev_t, mouse_devs);
+			if (mdev->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+		
+		if (!already_known) {
+			mouse_dev_t *mdev;
+			if (mouse_add_mousedev(svcs[i], &mdev) == EOK) {
+				printf("%s: Connected mouse device '%s'\n",
+				    NAME, mdev->svc_name);
+			}
+		}
+	}
+	
+	free(svcs);
+	
+	/* XXX Handle device removal */
+	
+	return EOK;
+}
+
+static int dev_check_new(void)
+{
+	int rc;
+	
+	rc = dev_check_new_kbdevs();
+	if (rc != EOK)
+		return rc;
+	
+	rc = dev_check_new_mousedevs();
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+static void cat_change_cb(void)
+{
+	dev_check_new();
+}
+
+/** Start listening for new devices. */
+static int input_start_dev_discovery(void)
+{
+	int rc;
+
+	rc = loc_register_cat_change_cb(cat_change_cb);
+	if (rc != EOK) {
+		printf("%s: Failed registering callback for device discovery. "
+		    "(%d)\n", NAME, rc);
+		return rc;
+	}
+
+	return dev_check_new();
+}
+
+int main(int argc, char **argv)
+{
+	printf("%s: HelenOS input service\n", NAME);
+	
+	sysarg_t obio;
+	
+	list_initialize(&kbd_devs);
+	list_initialize(&mouse_devs);
+	
+	if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio))
+		irc_service = true;
+	
+	if (irc_service) {
+		while (irc_phone < 0)
+			irc_phone = service_obsolete_connect_blocking(SERVICE_IRC, 0, 0);
+	}
+	
+	/* Add legacy keyboard devices. */
+	kbd_add_legacy_devs();
+	
+	/* Add legacy mouse devices. */
+	mouse_add_legacy_devs();
+	
+	/* Register driver */
+	int rc = loc_server_register(NAME, client_connection);
+	if (rc < 0) {
+		printf("%s: Unable to register server (%d)\n", NAME, rc);
+		return -1;
+	}
+	
+	char kbd[LOC_NAME_MAXLEN + 1];
+	snprintf(kbd, LOC_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
+	
+	service_id_t service_id;
+	if (loc_service_register(kbd, &service_id) != EOK) {
+		printf("%s: Unable to register service %s\n", NAME, kbd);
+		return -1;
+	}
+	
+	/* Start looking for new input devices */
+	input_start_dev_discovery();
+	
+	printf("%s: Accepting connections\n", NAME);
+	async_manager();
+	
+	/* Not reached. */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/generic/layout.c
===================================================================
--- uspace/srv/hid/input/generic/layout.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/generic/layout.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup inputgen generic
+ * @brief Keyboard layouts
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#include <errno.h>
+#include <input.h>
+#include <layout.h>
+#include <stdlib.h>
+
+/** Create a new layout instance. */
+layout_t *layout_create(layout_ops_t *ops)
+{
+	layout_t *layout;
+
+	layout = calloc(1, sizeof(layout_t));
+	if (layout == NULL) {
+		printf("%s: Out of memory.\n", NAME);
+		return NULL;
+	}
+
+	layout->ops = ops;
+	if ((*ops->create)(layout) != EOK) {
+		free(layout);
+		return NULL;
+	}
+
+	return layout;
+}
+
+/** Destroy layout instance. */
+void layout_destroy(layout_t *layout)
+{
+	(*layout->ops->destroy)(layout);
+	free(layout);
+}
+
+/** Parse keyboard event. */
+wchar_t layout_parse_ev(layout_t *layout, kbd_event_t *ev)
+{
+	return (*layout->ops->parse_ev)(layout, ev);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/generic/stroke.c
===================================================================
--- uspace/srv/hid/input/generic/stroke.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/generic/stroke.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Stroke simulator.
+ *
+ * When simulating a keyboard using a serial TTY we need to convert the
+ * recognized strokes (such as Shift-A) to sequences of key presses and
+ * releases (such as 'press Shift, press A, release A, release Shift').
+ *
+ */
+
+#include <stroke.h>
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+
+/** Correspondence between modifers and the modifier keycodes. */
+static unsigned int mods_keys[][2] = {
+	{ KM_LSHIFT, KC_LSHIFT },
+	{ 0, 0 }
+};
+
+/** Simulate keystroke using sequences of key presses and releases. */
+void stroke_sim(kbd_dev_t *kdev, unsigned mod, unsigned key)
+{
+	int i;
+
+	/* Simulate modifier presses. */
+	i = 0;
+	while (mods_keys[i][0] != 0) {
+		if (mod & mods_keys[i][0]) {
+			kbd_push_event(kdev, KEY_PRESS, mods_keys[i][1]);
+		}
+		++i;
+	}
+
+	/* Simulate key press and release. */
+	if (key != 0) {
+		kbd_push_event(kdev, KEY_PRESS, key);
+		kbd_push_event(kdev, KEY_RELEASE, key);
+	}
+
+	/* Simulate modifier releases. */
+	i = 0;
+	while (mods_keys[i][0] != 0) {
+		if (mod & mods_keys[i][0]) {
+			kbd_push_event(kdev, KEY_RELEASE, mods_keys[i][1]);
+		}
+		++i;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/gsp.h
===================================================================
--- uspace/srv/hid/input/include/gsp.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/gsp.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,84 @@
+/*
+ * 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 inputgen generic
+ * @brief	Generic scancode parser.
+ * @ingroup  input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_GSP_H_
+#define KBD_GSP_H_
+
+#include <adt/hash_table.h>
+
+enum {
+	GSP_END		= -1,	/**< Terminates a sequence. */
+	GSP_DEFAULT	= -2	/**< Wildcard, catches unhandled cases. */
+};
+
+/** Scancode parser description */
+typedef struct {
+	/** Transition table, (state, input) -> (state, output) */
+	hash_table_t trans;
+
+	/** Number of states */
+	int states;
+} gsp_t;
+
+/** Scancode parser transition. */
+typedef struct {
+	link_t link;		/**< Link to hash table in @c gsp_t */ 
+
+	/* Preconditions */
+
+	int old_state;		/**< State before transition */
+	int input;		/**< Input symbol (scancode) */
+
+	/* Effects */
+
+	int new_state;		/**< State after transition */
+
+	/* Output emitted during transition */
+
+	unsigned out_mods;	/**< Modifier to emit */
+	unsigned out_key;	/**< Keycode to emit */
+} gsp_trans_t;
+
+extern void gsp_init(gsp_t *);
+extern int gsp_insert_defs(gsp_t *, const int *);
+extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned);
+extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *);
+
+#endif
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/include/input.h
===================================================================
--- uspace/srv/hid/input/include/input.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/input.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef INPUT_H_
+#define INPUT_H_
+
+#include <bool.h>
+
+#define NAME       "input"
+#define NAMESPACE  "hid"
+
+extern bool irc_service;
+extern int irc_phone;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/kbd.h
===================================================================
--- uspace/srv/hid/input/include/kbd.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/kbd.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_KBD_H_
+#define KBD_KBD_H_
+
+#include <adt/list.h>
+#include <ipc/loc.h>
+
+struct kbd_port_ops;
+struct kbd_ctl_ops;
+struct layout;
+
+typedef struct kbd_dev {
+	/** Link to kbd_devs list */
+	link_t kbd_devs;
+
+	/** Service ID (only for kbdev devices) */
+	service_id_t svc_id;
+
+	/** Device service name (only for kbdev devices) */
+	char *svc_name;
+
+	/** Port ops */
+	struct kbd_port_ops *port_ops;
+
+	/** Ctl ops */
+	struct kbd_ctl_ops *ctl_ops;
+
+	/** Controller-private data */
+	void *ctl_private;
+
+	/** Currently active modifiers. */
+	unsigned mods;
+
+	/** Currently pressed lock keys. We track these to tackle autorepeat. */
+	unsigned lock_keys;
+
+	/** Active keyboard layout */
+	struct layout *active_layout;
+} kbd_dev_t;
+
+extern void kbd_push_data(kbd_dev_t *, sysarg_t);
+extern void kbd_push_event(kbd_dev_t *, int, unsigned int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/kbd_ctl.h
===================================================================
--- uspace/srv/hid/input/include/kbd_ctl.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/kbd_ctl.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Keyboard controller driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_CTL_H_
+#define KBD_CTL_H_
+
+#include <kbd_port.h>
+
+struct kbd_dev;
+
+typedef struct kbd_ctl_ops {
+	void (*parse)(sysarg_t);
+	int (*init)(struct kbd_dev *);
+	void (*set_ind)(struct kbd_dev *, unsigned int);
+} kbd_ctl_ops_t;
+
+extern kbd_ctl_ops_t apple_ctl;
+extern kbd_ctl_ops_t gxe_fb_ctl;
+extern kbd_ctl_ops_t kbdev_ctl;
+extern kbd_ctl_ops_t pc_ctl;
+extern kbd_ctl_ops_t stty_ctl;
+extern kbd_ctl_ops_t sun_ctl;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/kbd_port.h
===================================================================
--- uspace/srv/hid/input/include/kbd_port.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/kbd_port.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Keyboard port driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_PORT_H_
+#define KBD_PORT_H_
+
+#include <sys/types.h>
+
+struct kbd_dev;
+
+typedef struct kbd_port_ops {
+	int (*init)(struct kbd_dev *);
+	void (*yield)(void);
+	void (*reclaim)(void);
+	void (*write)(uint8_t);
+} kbd_port_ops_t;
+
+extern kbd_port_ops_t adb_port;
+extern kbd_port_ops_t chardev_port;
+extern kbd_port_ops_t gxemul_port;
+extern kbd_port_ops_t msim_port;
+extern kbd_port_ops_t niagara_port;
+extern kbd_port_ops_t ns16550_port;
+extern kbd_port_ops_t pl050_port;
+extern kbd_port_ops_t ski_port;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/layout.h
===================================================================
--- uspace/srv/hid/input/include/layout.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/layout.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,71 @@
+/*
+ * 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 inputgen generic
+ * @brief Keyboard layout interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_LAYOUT_H_
+#define KBD_LAYOUT_H_
+
+#include <sys/types.h>
+#include <io/console.h>
+
+/** Layout instance state */
+typedef struct layout {
+	/** Ops structure */
+	struct layout_ops *ops;
+
+	/* Layout-private data */
+	void *layout_priv;
+} layout_t;
+
+/** Layout ops */
+typedef struct layout_ops {
+	int (*create)(layout_t *);
+	void (*destroy)(layout_t *);
+	wchar_t (*parse_ev)(layout_t *, kbd_event_t *);
+} layout_ops_t;
+
+extern layout_ops_t us_qwerty_ops;
+extern layout_ops_t us_dvorak_ops;
+extern layout_ops_t cz_ops;
+
+extern layout_t *layout_create(layout_ops_t *);
+extern void layout_destroy(layout_t *);
+extern wchar_t layout_parse_ev(layout_t *, kbd_event_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/mouse.h
===================================================================
--- uspace/srv/hid/input/include/mouse.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/mouse.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Mouse device handling.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_H_
+#define MOUSE_H_
+
+#include <adt/list.h>
+#include <ipc/loc.h>
+
+struct mouse_port_ops;
+struct mouse_proto_ops;
+
+typedef struct mouse_dev {
+	/** Link to mouse_devs list */
+	link_t mouse_devs;
+	
+	/** Service ID (only for mousedev devices) */
+	service_id_t svc_id;
+	
+	/** Device service name (only for mousedev devices) */
+	char *svc_name;
+	
+	/** Port ops */
+	struct mouse_port_ops *port_ops;
+	
+	/** Protocol ops */
+	struct mouse_proto_ops *proto_ops;
+} mouse_dev_t;
+
+extern void mouse_push_data(mouse_dev_t *, sysarg_t);
+extern void mouse_push_event_move(mouse_dev_t *, int, int);
+extern void mouse_push_event_button(mouse_dev_t *, int, int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/mouse_port.h
===================================================================
--- uspace/srv/hid/input/include/mouse_port.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/mouse_port.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Mouse port driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_PORT_H_
+#define MOUSE_PORT_H_
+
+#include <sys/types.h>
+
+struct mouse_dev;
+
+typedef struct mouse_port_ops {
+	int (*init)(struct mouse_dev *);
+	void (*yield)(void);
+	void (*reclaim)(void);
+	void (*write)(uint8_t);
+} mouse_port_ops_t;
+
+extern mouse_port_ops_t adb_mouse_port;
+extern mouse_port_ops_t chardev_mouse_port;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/mouse_proto.h
===================================================================
--- uspace/srv/hid/input/include/mouse_proto.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/mouse_proto.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Mouse protocol driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_PROTO_H_
+#define MOUSE_PROTO_H_
+
+#include <mouse_port.h>
+
+struct mouse_dev;
+
+typedef struct mouse_proto_ops {
+	void (*parse)(sysarg_t);
+	int (*init)(struct mouse_dev *);
+} mouse_proto_ops_t;
+
+extern mouse_proto_ops_t adb_proto;
+extern mouse_proto_ops_t ps2_proto;
+extern mouse_proto_ops_t mousedev_proto;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/stroke.h
===================================================================
--- uspace/srv/hid/input/include/stroke.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/include/stroke.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief	Generic scancode parser.
+ * @ingroup  input
+ * @{
+ */ 
+/** @file
+ */
+
+#ifndef KBD_STROKE_H_
+#define KBD_STROKE_H_
+
+#include <kbd.h>
+
+extern void stroke_sim(kbd_dev_t *, unsigned, unsigned);
+
+#endif
+
+/**
+ * @}
+ */ 
+
Index: uspace/srv/hid/input/layout/cz.c
===================================================================
--- uspace/srv/hid/input/layout/cz.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/layout/cz.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @brief Czech QWERTZ layout.
+ * @{
+ */
+
+#include <errno.h>
+#include <input.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <bool.h>
+#include <layout.h>
+#include <stdlib.h>
+
+static int cz_create(layout_t *);
+static void cz_destroy(layout_t *);
+static wchar_t cz_parse_ev(layout_t *, kbd_event_t *ev);
+
+enum m_state {
+	ms_start,
+	ms_hacek,
+	ms_carka
+};
+
+typedef struct {
+	enum m_state mstate;
+} layout_cz_t;
+
+layout_ops_t cz_ops = {
+	.create = cz_create,
+	.destroy = cz_destroy,
+	.parse_ev = cz_parse_ev
+};
+
+static wchar_t map_lcase[] = {
+	[KC_Q] = 'q',
+	[KC_W] = 'w',
+	[KC_E] = 'e',
+	[KC_R] = 'r',
+	[KC_T] = 't',
+	[KC_Y] = 'z',
+	[KC_U] = 'u',
+	[KC_I] = 'i',
+	[KC_O] = 'o',
+	[KC_P] = 'p',
+
+	[KC_A] = 'a',
+	[KC_S] = 's',
+	[KC_D] = 'd',
+	[KC_F] = 'f',
+	[KC_G] = 'g',
+	[KC_H] = 'h',
+	[KC_J] = 'j',
+	[KC_K] = 'k',
+	[KC_L] = 'l',
+
+	[KC_Z] = 'y',
+	[KC_X] = 'x',
+	[KC_C] = 'c',
+	[KC_V] = 'v',
+	[KC_B] = 'b',
+	[KC_N] = 'n',
+	[KC_M] = 'm',
+};
+
+static wchar_t map_ucase[] = {
+	[KC_Q] = 'Q',
+	[KC_W] = 'W',
+	[KC_E] = 'E',
+	[KC_R] = 'R',
+	[KC_T] = 'T',
+	[KC_Y] = 'Z',
+	[KC_U] = 'U',
+	[KC_I] = 'I',
+	[KC_O] = 'O',
+	[KC_P] = 'P',
+
+	[KC_A] = 'A',
+	[KC_S] = 'S',
+	[KC_D] = 'D',
+	[KC_F] = 'F',
+	[KC_G] = 'G',
+	[KC_H] = 'H',
+	[KC_J] = 'J',
+	[KC_K] = 'K',
+	[KC_L] = 'L',
+
+	[KC_Z] = 'Y',
+	[KC_X] = 'X',
+	[KC_C] = 'C',
+	[KC_V] = 'V',
+	[KC_B] = 'B',
+	[KC_N] = 'N',
+	[KC_M] = 'M',
+};
+
+static wchar_t map_not_shifted[] = {
+	[KC_BACKTICK] = ';',
+
+	[KC_1] = '+',
+
+	[KC_MINUS] = '=',
+
+	[KC_RBRACKET] = ')',
+
+	[KC_QUOTE] = L'§',
+
+	[KC_COMMA] = ',',
+	[KC_PERIOD] = '.',
+	[KC_SLASH] = '-',
+};
+
+static wchar_t map_shifted[] = {
+	[KC_1] = '1',
+	[KC_2] = '2',
+	[KC_3] = '3',
+	[KC_4] = '4',
+	[KC_5] = '5',
+	[KC_6] = '6',
+	[KC_7] = '7',
+	[KC_8] = '8',
+	[KC_9] = '9',
+	[KC_0] = '0',
+
+	[KC_MINUS] = '%',
+
+	[KC_LBRACKET] = '/',
+	[KC_RBRACKET] = '(',
+
+	[KC_SEMICOLON] = '"',
+	[KC_QUOTE] = '!',
+	[KC_BACKSLASH] = '\'',
+
+	[KC_COMMA] = '?',
+	[KC_PERIOD] = ':',
+	[KC_SLASH] = '_',
+};
+
+static wchar_t map_ns_nocaps[] = {
+	[KC_2] = L'ě',
+	[KC_3] = L'š',
+	[KC_4] = L'č',
+	[KC_5] = L'ř',
+	[KC_6] = L'ž',
+	[KC_7] = L'ý',
+	[KC_8] = L'á',
+	[KC_9] = L'í',
+	[KC_0] = L'é',
+
+	[KC_LBRACKET] = L'ú',
+	[KC_SEMICOLON] = L'ů'
+};
+
+static wchar_t map_ns_caps[] = {
+	[KC_2] = L'Ě',
+	[KC_3] = L'Š',
+	[KC_4] = L'Č',
+	[KC_5] = L'Ř',
+	[KC_6] = L'Ž',
+	[KC_7] = L'Ý',
+	[KC_8] = L'Á',
+	[KC_9] = L'Í',
+	[KC_0] = L'É',
+
+	[KC_LBRACKET] = L'Ú',
+	[KC_SEMICOLON] = L'Ů'
+};
+
+static wchar_t map_neutral[] = {
+	[KC_BACKSPACE] = '\b',
+	[KC_TAB] = '\t',
+	[KC_ENTER] = '\n',
+	[KC_SPACE] = ' ',
+
+	[KC_NSLASH] = '/',
+	[KC_NTIMES] = '*',
+	[KC_NMINUS] = '-',
+	[KC_NPLUS] = '+',
+	[KC_NENTER] = '\n'
+};
+
+static wchar_t map_numeric[] = {
+	[KC_N7] = '7',
+	[KC_N8] = '8',
+	[KC_N9] = '9',
+	[KC_N4] = '4',
+	[KC_N5] = '5',
+	[KC_N6] = '6',
+	[KC_N1] = '1',
+	[KC_N2] = '2',
+	[KC_N3] = '3',
+
+	[KC_N0] = '0',
+	[KC_NPERIOD] = '.'
+};
+
+static wchar_t map_hacek_lcase[] = {
+	[KC_E] = L'ě',
+	[KC_R] = L'ř',
+	[KC_T] = L'ť',
+	[KC_Y] = L'ž',
+	[KC_U] = L'ů',
+
+	[KC_S] = L'š',
+	[KC_D] = L'ď',
+
+	[KC_C] = L'č',
+	[KC_N] = L'ň'
+};
+
+static wchar_t map_hacek_ucase[] = {
+	[KC_E] = L'Ě',
+	[KC_R] = L'Ř',
+	[KC_T] = L'Ť',
+	[KC_Y] = L'Ž',
+	[KC_U] = L'Ů',
+
+	[KC_S] = L'Š',
+	[KC_D] = L'Ď',
+
+	[KC_C] = L'Č',
+	[KC_N] = L'Ň'
+};
+
+static wchar_t map_carka_lcase[] = {
+	[KC_E] = L'é',
+	[KC_U] = L'ú',
+	[KC_I] = L'í',
+	[KC_O] = L'ó',
+
+	[KC_A] = L'á',
+
+	[KC_Z] = L'ý',
+};
+
+static wchar_t map_carka_ucase[] = {
+	[KC_E] = L'É',
+	[KC_U] = L'Ú',
+	[KC_I] = L'Í',
+	[KC_O] = L'Ó',
+
+	[KC_A] = L'Á',
+
+	[KC_Z] = L'Ý',
+};
+
+static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
+{
+	if (key >= map_length)
+		return 0;
+	return map[key];
+}
+
+static wchar_t parse_ms_hacek(layout_cz_t *cz_state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	cz_state->mstate = ms_start;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t));
+
+	return c;
+}
+
+static wchar_t parse_ms_carka(layout_cz_t *cz_state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	cz_state->mstate = ms_start;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t));
+
+	return c;
+}
+
+static wchar_t parse_ms_start(layout_cz_t *cz_state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	if (ev->key == KC_EQUALS) {
+		if ((ev->mods & KM_SHIFT) != 0)
+			cz_state->mstate = ms_hacek;
+		else
+			cz_state->mstate = ms_carka;
+
+		return 0;
+	}
+
+	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) == 0) {
+		if ((ev->mods & KM_CAPS_LOCK) != 0)
+			c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t));
+		else
+			c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t));
+
+		if (c != 0)
+			return c;
+	}	
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) != 0)
+		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_NUM_LOCK) != 0)
+		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
+	else
+		c = 0;
+
+	return c;
+}
+
+static bool key_is_mod(unsigned key)
+{
+	switch (key) {
+	case KC_LSHIFT:
+	case KC_RSHIFT:
+	case KC_LALT:
+	case KC_RALT:
+	case KC_LCTRL:
+	case KC_RCTRL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int cz_create(layout_t *state)
+{
+	layout_cz_t *cz_state;
+
+	cz_state = malloc(sizeof(layout_cz_t));
+	if (cz_state == NULL) {
+		printf("%s: Out of memory.\n", NAME);
+		return ENOMEM;
+	}
+
+	cz_state->mstate = ms_start;
+	state->layout_priv = (void *) cz_state;
+
+	return EOK;
+}
+
+static void cz_destroy(layout_t *state)
+{
+	free(state->layout_priv);
+}
+
+static wchar_t cz_parse_ev(layout_t *state, kbd_event_t *ev)
+{
+	layout_cz_t *cz_state = (layout_cz_t *) state->layout_priv;
+
+	if (ev->type != KEY_PRESS)
+		return 0;
+	
+	if (key_is_mod(ev->key))
+		return 0;
+	
+	switch (cz_state->mstate) {
+	case ms_start:
+		return parse_ms_start(cz_state, ev);
+	case ms_hacek:
+		return parse_ms_hacek(cz_state, ev);
+	case ms_carka:
+		return parse_ms_carka(cz_state, ev);
+	}
+	
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout/us_dvorak.c
===================================================================
--- uspace/srv/hid/input/layout/us_dvorak.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/layout/us_dvorak.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @brief US Dvorak Simplified Keyboard layout.
+ * @{
+ */
+
+#include <errno.h>
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <layout.h>
+
+static int us_dvorak_create(layout_t *);
+static void us_dvorak_destroy(layout_t *);
+static wchar_t us_dvorak_parse_ev(layout_t *, kbd_event_t *ev);
+
+layout_ops_t us_dvorak_ops = {
+	.create = us_dvorak_create,
+	.destroy = us_dvorak_destroy,
+	.parse_ev = us_dvorak_parse_ev
+};
+
+static wchar_t map_lcase[] = {
+	[KC_R] = 'p',
+	[KC_T] = 'y',
+	[KC_Y] = 'f',
+	[KC_U] = 'g',
+	[KC_I] = 'c',
+	[KC_O] = 'r',
+	[KC_P] = 'l',
+
+	[KC_A] = 'a',
+	[KC_S] = 'o',
+	[KC_D] = 'e',
+	[KC_F] = 'u',
+	[KC_G] = 'i',
+	[KC_H] = 'd',
+	[KC_J] = 'h',
+	[KC_K] = 't',
+	[KC_L] = 'n',
+
+	[KC_SEMICOLON] = 's',
+
+	[KC_X] = 'q',
+	[KC_C] = 'j',
+	[KC_V] = 'k',
+	[KC_B] = 'x',
+	[KC_N] = 'b',
+	[KC_M] = 'm',
+
+	[KC_COMMA] = 'w',
+	[KC_PERIOD] = 'v',
+	[KC_SLASH] = 'z',
+};
+
+static wchar_t map_ucase[] = {
+	[KC_R] = 'P',
+	[KC_T] = 'Y',
+	[KC_Y] = 'F',
+	[KC_U] = 'G',
+	[KC_I] = 'C',
+	[KC_O] = 'R',
+	[KC_P] = 'L',
+
+	[KC_A] = 'A',
+	[KC_S] = 'O',
+	[KC_D] = 'E',
+	[KC_F] = 'U',
+	[KC_G] = 'I',
+	[KC_H] = 'D',
+	[KC_J] = 'H',
+	[KC_K] = 'T',
+	[KC_L] = 'N',
+
+	[KC_SEMICOLON] = 'S',
+
+	[KC_X] = 'Q',
+	[KC_C] = 'J',
+	[KC_V] = 'K',
+	[KC_B] = 'X',
+	[KC_N] = 'B',
+	[KC_M] = 'M',
+
+	[KC_COMMA] = 'W',
+	[KC_PERIOD] = 'V',
+	[KC_SLASH] = 'Z',
+};
+
+static wchar_t map_not_shifted[] = {
+	[KC_BACKTICK] = '`',
+
+	[KC_1] = '1',
+	[KC_2] = '2',
+	[KC_3] = '3',
+	[KC_4] = '4',
+	[KC_5] = '5',
+	[KC_6] = '6',
+	[KC_7] = '7',
+	[KC_8] = '8',
+	[KC_9] = '9',
+	[KC_0] = '0',
+
+	[KC_MINUS] = '[',
+	[KC_EQUALS] = ']',
+
+	[KC_Q] = '\'',
+	[KC_W] = ',',
+	[KC_E] = '.',
+
+	[KC_LBRACKET] = '/',
+	[KC_RBRACKET] = '=',
+
+	[KC_QUOTE] = '-',
+	[KC_BACKSLASH] = '\\',
+
+	[KC_Z] = ';',
+};
+
+static wchar_t map_shifted[] = {
+	[KC_BACKTICK] = '~',
+
+	[KC_1] = '!',
+	[KC_2] = '@',
+	[KC_3] = '#',
+	[KC_4] = '$',
+	[KC_5] = '%',
+	[KC_6] = '^',
+	[KC_7] = '&',
+	[KC_8] = '*',
+	[KC_9] = '(',
+	[KC_0] = ')',
+
+	[KC_MINUS] = '{',
+	[KC_EQUALS] = '}',
+
+	[KC_Q] = '"',
+	[KC_W] = '<',
+	[KC_E] = '>',
+
+	[KC_LBRACKET] = '?',
+	[KC_RBRACKET] = '+',
+
+	[KC_QUOTE] = '_',
+	[KC_BACKSLASH] = '|',
+
+	[KC_Z] = ':',
+};
+
+static wchar_t map_neutral[] = {
+	[KC_BACKSPACE] = '\b',
+	[KC_TAB] = '\t',
+	[KC_ENTER] = '\n',
+	[KC_SPACE] = ' ',
+
+	[KC_NSLASH] = '/',
+	[KC_NTIMES] = '*',
+	[KC_NMINUS] = '-',
+	[KC_NPLUS] = '+',
+	[KC_NENTER] = '\n'
+};
+
+static wchar_t map_numeric[] = {
+	[KC_N7] = '7',
+	[KC_N8] = '8',
+	[KC_N9] = '9',
+	[KC_N4] = '4',
+	[KC_N5] = '5',
+	[KC_N6] = '6',
+	[KC_N1] = '1',
+	[KC_N2] = '2',
+	[KC_N3] = '3',
+
+	[KC_N0] = '0',
+	[KC_NPERIOD] = '.'
+};
+
+static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
+{
+	if (key >= map_length)
+		return 0;
+	return map[key];
+}
+
+static int us_dvorak_create(layout_t *state)
+{
+	return EOK;
+}
+
+static void us_dvorak_destroy(layout_t *state)
+{
+}
+
+static wchar_t us_dvorak_parse_ev(layout_t *state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
+	if (c != 0)
+		return c;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) != 0)
+		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_NUM_LOCK) != 0)
+		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
+	else
+		c = 0;
+
+	return c;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout/us_qwerty.c
===================================================================
--- uspace/srv/hid/input/layout/us_qwerty.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/layout/us_qwerty.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @brief	US QWERTY layout.
+ * @{
+ */
+
+#include <errno.h>
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <layout.h>
+
+static int us_qwerty_create(layout_t *);
+static void us_qwerty_destroy(layout_t *);
+static wchar_t us_qwerty_parse_ev(layout_t *, kbd_event_t *ev);
+
+layout_ops_t us_qwerty_ops = {
+	.create = us_qwerty_create,
+	.destroy = us_qwerty_destroy,
+	.parse_ev = us_qwerty_parse_ev
+};
+
+static wchar_t map_lcase[] = {
+	[KC_Q] = 'q',
+	[KC_W] = 'w',
+	[KC_E] = 'e',
+	[KC_R] = 'r',
+	[KC_T] = 't',
+	[KC_Y] = 'y',
+	[KC_U] = 'u',
+	[KC_I] = 'i',
+	[KC_O] = 'o',
+	[KC_P] = 'p',
+
+	[KC_A] = 'a',
+	[KC_S] = 's',
+	[KC_D] = 'd',
+	[KC_F] = 'f',
+	[KC_G] = 'g',
+	[KC_H] = 'h',
+	[KC_J] = 'j',
+	[KC_K] = 'k',
+	[KC_L] = 'l',
+
+	[KC_Z] = 'z',
+	[KC_X] = 'x',
+	[KC_C] = 'c',
+	[KC_V] = 'v',
+	[KC_B] = 'b',
+	[KC_N] = 'n',
+	[KC_M] = 'm',
+};
+
+static wchar_t map_ucase[] = {
+	[KC_Q] = 'Q',
+	[KC_W] = 'W',
+	[KC_E] = 'E',
+	[KC_R] = 'R',
+	[KC_T] = 'T',
+	[KC_Y] = 'Y',
+	[KC_U] = 'U',
+	[KC_I] = 'I',
+	[KC_O] = 'O',
+	[KC_P] = 'P',
+
+	[KC_A] = 'A',
+	[KC_S] = 'S',
+	[KC_D] = 'D',
+	[KC_F] = 'F',
+	[KC_G] = 'G',
+	[KC_H] = 'H',
+	[KC_J] = 'J',
+	[KC_K] = 'K',
+	[KC_L] = 'L',
+
+	[KC_Z] = 'Z',
+	[KC_X] = 'X',
+	[KC_C] = 'C',
+	[KC_V] = 'V',
+	[KC_B] = 'B',
+	[KC_N] = 'N',
+	[KC_M] = 'M',
+};
+
+static wchar_t map_not_shifted[] = {
+	[KC_BACKTICK] = '`',
+
+	[KC_1] = '1',
+	[KC_2] = '2',
+	[KC_3] = '3',
+	[KC_4] = '4',
+	[KC_5] = '5',
+	[KC_6] = '6',
+	[KC_7] = '7',
+	[KC_8] = '8',
+	[KC_9] = '9',
+	[KC_0] = '0',
+
+	[KC_MINUS] = '-',
+	[KC_EQUALS] = '=',
+
+	[KC_LBRACKET] = '[',
+	[KC_RBRACKET] = ']',
+
+	[KC_SEMICOLON] = ';',
+	[KC_QUOTE] = '\'',
+	[KC_BACKSLASH] = '\\',
+
+	[KC_COMMA] = ',',
+	[KC_PERIOD] = '.',
+	[KC_SLASH] = '/',
+};
+
+static wchar_t map_shifted[] = {
+	[KC_BACKTICK] = '~',
+
+	[KC_1] = '!',
+	[KC_2] = '@',
+	[KC_3] = '#',
+	[KC_4] = '$',
+	[KC_5] = '%',
+	[KC_6] = '^',
+	[KC_7] = '&',
+	[KC_8] = '*',
+	[KC_9] = '(',
+	[KC_0] = ')',
+
+	[KC_MINUS] = '_',
+	[KC_EQUALS] = '+',
+
+	[KC_LBRACKET] = '{',
+	[KC_RBRACKET] = '}',
+
+	[KC_SEMICOLON] = ':',
+	[KC_QUOTE] = '"',
+	[KC_BACKSLASH] = '|',
+
+	[KC_COMMA] = '<',
+	[KC_PERIOD] = '>',
+	[KC_SLASH] = '?',
+};
+
+static wchar_t map_neutral[] = {
+	[KC_BACKSPACE] = '\b',
+	[KC_TAB] = '\t',
+	[KC_ENTER] = '\n',
+	[KC_SPACE] = ' ',
+
+	[KC_NSLASH] = '/',
+	[KC_NTIMES] = '*',
+	[KC_NMINUS] = '-',
+	[KC_NPLUS] = '+',
+	[KC_NENTER] = '\n'
+};
+
+static wchar_t map_numeric[] = {
+	[KC_N7] = '7',
+	[KC_N8] = '8',
+	[KC_N9] = '9',
+	[KC_N4] = '4',
+	[KC_N5] = '5',
+	[KC_N6] = '6',
+	[KC_N1] = '1',
+	[KC_N2] = '2',
+	[KC_N3] = '3',
+
+	[KC_N0] = '0',
+	[KC_NPERIOD] = '.'
+};
+
+static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
+{
+	if (key >= map_length)
+		return 0;
+	return map[key];
+}
+
+static int us_qwerty_create(layout_t *state)
+{
+	return EOK;
+}
+
+static void us_qwerty_destroy(layout_t *state)
+{
+}
+
+static wchar_t us_qwerty_parse_ev(layout_t *state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
+	if (c != 0)
+		return c;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) != 0)
+		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_NUM_LOCK) != 0)
+		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
+	else
+		c = 0;
+
+	return c;
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/port/adb.c
===================================================================
--- uspace/srv/hid/input/port/adb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/adb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup kbd
+ * @{
+ */
+/** @file
+ * @brief ADB keyboard port driver.
+ */
+
+#include <ipc/adb.h>
+#include <async.h>
+#include <input.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <vfs/vfs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <loc.h>
+
+static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+static void adb_kbd_reg0_data(uint16_t data);
+
+static int adb_port_init(kbd_dev_t *);
+static void adb_port_yield(void);
+static void adb_port_reclaim(void);
+static void adb_port_write(uint8_t data);
+
+kbd_port_ops_t adb_port = {
+	.init = adb_port_init,
+	.yield = adb_port_yield,
+	.reclaim = adb_port_reclaim,
+	.write = adb_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+static async_sess_t *dev_sess;
+
+static int adb_port_init(kbd_dev_t *kdev)
+{
+	const char *dev = "adb/kbd";
+	service_id_t service_id;
+	async_exch_t *exch;
+	int rc;
+	
+	kbd_dev = kdev;
+	
+	rc = loc_service_get_id(dev, &service_id, 0);
+	if (rc != EOK)
+		return rc;
+	
+	dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0);
+	if (dev_sess == NULL) {
+		printf("%s: Failed to connect to device\n", NAME);
+		return ENOENT;
+	}
+	
+	exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, kbd_port_events, NULL);
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+static void adb_port_yield(void)
+{
+}
+
+static void adb_port_reclaim(void)
+{
+}
+
+static void adb_port_write(uint8_t data)
+{
+	/*async_msg_1(dev_phone, CHAR_WRITE_BYTE, data);*/
+}
+
+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);
+
+		int retval;
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case ADB_REG_NOTIF:
+			adb_kbd_reg0_data(IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		async_answer_0(callid, retval);
+	}
+}
+
+static void adb_kbd_reg0_data(uint16_t data)
+{
+	uint8_t b0 = (data >> 8) & 0xff;
+	uint8_t b1 = data & 0xff;
+	
+	if (b0 != 0xff)
+		kbd_push_data(kbd_dev, b0);
+	
+	if (b1 != 0xff)
+		kbd_push_data(kbd_dev, b1);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/adb_mouse.c
===================================================================
--- uspace/srv/hid/input/port/adb_mouse.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/adb_mouse.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup mouse_port
+ * @ingroup mouse
+ * @{
+ */
+/** @file
+ * @brief ADB mouse port driver.
+ */
+
+#include <ipc/adb.h>
+#include <async.h>
+#include <input.h>
+#include <mouse_port.h>
+#include <mouse.h>
+#include <errno.h>
+#include <loc.h>
+#include <stdio.h>
+
+static mouse_dev_t *mouse_dev;
+static async_sess_t *dev_sess;
+
+static void mouse_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);
+		
+		int retval;
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case ADB_REG_NOTIF:
+			mouse_push_data(mouse_dev, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int adb_port_init(mouse_dev_t *mdev)
+{
+	const char *dev = "adb/mouse";
+	
+	mouse_dev = mdev;
+	
+	service_id_t service_id;
+	int rc = loc_service_get_id(dev, &service_id, 0);
+	if (rc != EOK)
+		return rc;
+	
+	dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0);
+	if (dev_sess == NULL) {
+		printf("%s: Failed to connect to device\n", NAME);
+		return ENOENT;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, mouse_port_events, NULL);
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+static void adb_port_yield(void)
+{
+}
+
+static void adb_port_reclaim(void)
+{
+}
+
+static void adb_port_write(uint8_t data)
+{
+}
+
+mouse_port_ops_t adb_mouse_port = {
+	.init = adb_port_init,
+	.yield = adb_port_yield,
+	.reclaim = adb_port_reclaim,
+	.write = adb_port_write
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/chardev.c
===================================================================
--- uspace/srv/hid/input/port/chardev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/chardev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup kbd
+ * @{
+ */
+/** @file
+ * @brief Chardev keyboard port driver.
+ */
+
+#include <ipc/char.h>
+#include <async.h>
+#include <input.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <loc.h>
+#include <errno.h>
+#include <stdio.h>
+
+static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static int chardev_port_init(kbd_dev_t *);
+static void chardev_port_yield(void);
+static void chardev_port_reclaim(void);
+static void chardev_port_write(uint8_t data);
+
+kbd_port_ops_t chardev_port = {
+	.init = chardev_port_init,
+	.yield = chardev_port_yield,
+	.reclaim = chardev_port_reclaim,
+	.write = chardev_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+static async_sess_t *dev_sess;
+
+/** List of devices to try connecting to. */
+static const char *in_devs[] = {
+	"char/ps2a",
+	"char/s3c24ser"
+};
+
+static const unsigned int num_devs = sizeof(in_devs) / sizeof(in_devs[0]);
+
+static int chardev_port_init(kbd_dev_t *kdev)
+{
+	service_id_t service_id;
+	async_exch_t *exch;
+	unsigned int i;
+	int rc;
+	
+	kbd_dev = kdev;
+	
+	for (i = 0; i < num_devs; i++) {
+		rc = loc_service_get_id(in_devs[i], &service_id, 0);
+		if (rc == EOK)
+			break;
+	}
+	
+	if (i >= num_devs) {
+		printf("%s: Could not find any suitable input device\n", NAME);
+		return -1;
+	}
+	
+	dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id,
+	    IPC_FLAG_BLOCKING);
+	if (dev_sess == NULL) {
+		printf("%s: Failed connecting to device\n", NAME);
+		return ENOENT;
+	}
+	
+	exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, kbd_port_events, NULL);
+	async_exchange_end(exch);
+	
+	if (rc != 0) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return -1;
+	}
+	
+	return 0;
+}
+
+static void chardev_port_yield(void)
+{
+}
+
+static void chardev_port_reclaim(void)
+{
+}
+
+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);
+		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;
+
+		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);
+	}
+}
+
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/port/chardev_mouse.c
===================================================================
--- uspace/srv/hid/input/port/chardev_mouse.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/chardev_mouse.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup mouse_port
+ * @ingroup mouse
+ * @{
+ */
+/** @file
+ * @brief Chardev mouse port driver.
+ */
+
+#include <ipc/char.h>
+#include <stdio.h>
+#include <async.h>
+#include <errno.h>
+#include <loc.h>
+#include <input.h>
+#include <mouse_port.h>
+#include <mouse.h>
+
+static mouse_dev_t *mouse_dev;
+static async_sess_t *dev_sess;
+
+/** List of devices to try connecting to. */
+static const char *in_devs[] = {
+	"char/ps2b",
+};
+
+static const unsigned int num_devs = sizeof(in_devs) / sizeof(in_devs[0]);
+
+static void mouse_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;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case CHAR_NOTIF_BYTE:
+			mouse_push_data(mouse_dev, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int chardev_port_init(mouse_dev_t *mdev)
+{
+	service_id_t service_id;
+	unsigned int i;
+	int rc;
+	
+	mouse_dev = mdev;
+	
+	for (i = 0; i < num_devs; i++) {
+		rc = loc_service_get_id(in_devs[i], &service_id, 0);
+		if (rc == EOK)
+			break;
+	}
+	
+	if (i >= num_devs) {
+		printf("%s: Could not find any suitable input device\n", NAME);
+		return -1;
+	}
+	
+	dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id,
+	    IPC_FLAG_BLOCKING);
+	if (dev_sess == NULL) {
+		printf("%s: Failed connecting to device\n", NAME);
+		return ENOENT;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, mouse_port_events, NULL);
+	async_exchange_end(exch);
+	
+	if (rc != 0) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return -1;
+	}
+	
+	return 0;
+}
+
+static void chardev_port_yield(void)
+{
+}
+
+static void chardev_port_reclaim(void)
+{
+}
+
+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);
+		return;
+	}
+
+	async_msg_1(exch, CHAR_WRITE_BYTE, data);
+	async_exchange_end(exch);
+}
+
+mouse_port_ops_t chardev_mouse_port = {
+	.init = chardev_port_init,
+	.yield = chardev_port_yield,
+	.reclaim = chardev_port_reclaim,
+	.write = chardev_port_write
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/gxemul.c
===================================================================
--- uspace/srv/hid/input/port/gxemul.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/gxemul.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2007 Michal Kebrt
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @{
+ * @ingroup  kbd
+ */ 
+/** @file
+ * @brief	GXEmul keyboard port driver.
+ */
+
+#include <async.h>
+#include <sysinfo.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <ddi.h>
+#include <errno.h>
+
+static int gxemul_port_init(kbd_dev_t *);
+static void gxemul_port_yield(void);
+static void gxemul_port_reclaim(void);
+static void gxemul_port_write(uint8_t data);
+
+kbd_port_ops_t gxemul_port = {
+	.init = gxemul_port_init,
+	.yield = gxemul_port_yield,
+	.reclaim = gxemul_port_reclaim,
+	.write = gxemul_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+static irq_cmd_t gxemul_cmds[] = {
+	{ 
+		.cmd = CMD_PIO_READ_8, 
+		.addr = (void *) 0, 	/* will be patched in run-time */
+		.dstarg = 2,
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t gxemul_kbd = {
+	sizeof(gxemul_cmds) / sizeof(irq_cmd_t),
+	gxemul_cmds
+};
+
+static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+/** Initializes keyboard handler. */
+static int gxemul_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	
+	sysarg_t addr;
+	if (sysinfo_get_value("kbd.address.virtual", &addr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	async_set_interrupt_received(gxemul_irq_handler);
+	gxemul_cmds[0].addr = (void *) addr;
+	register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
+	return 0;
+}
+
+static void gxemul_port_yield(void)
+{
+}
+
+static void gxemul_port_reclaim(void)
+{
+}
+
+static void gxemul_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/** Process data sent when a key is pressed.
+ *
+ * @param keybuffer Buffer of pressed keys.
+ * @param call      IPC call.
+ *
+ */
+static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/port/msim.c
===================================================================
--- uspace/srv/hid/input/port/msim.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/msim.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief Msim keyboard port driver.
+ */
+
+#include <async.h>
+#include <sysinfo.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <ddi.h>
+#include <errno.h>
+
+static int msim_port_init(kbd_dev_t *);
+static void msim_port_yield(void);
+static void msim_port_reclaim(void);
+static void msim_port_write(uint8_t data);
+
+kbd_port_ops_t msim_port = {
+	.init = msim_port_init,
+	.yield = msim_port_yield,
+	.reclaim = msim_port_reclaim,
+	.write = msim_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+static irq_cmd_t msim_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,	/* will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t msim_kbd = {
+	sizeof(msim_cmds) / sizeof(irq_cmd_t),
+	msim_cmds
+};
+
+static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+static int msim_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+
+	sysarg_t vaddr;
+	if (sysinfo_get_value("kbd.address.virtual", &vaddr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	msim_cmds[0].addr = (void *) vaddr;
+	async_set_interrupt_received(msim_irq_handler);
+	register_irq(inr, device_assign_devno(), 0, &msim_kbd);
+	
+	return 0;
+}
+
+static void msim_port_yield(void)
+{
+}
+
+static void msim_port_reclaim(void)
+{
+}
+
+static void msim_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/port/niagara.c
===================================================================
--- uspace/srv/hid/input/port/niagara.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/niagara.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2008 Pavel Rimsky
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */ 
+/** @file
+ * @brief	Niagara console keyboard port driver.
+ */
+
+#include <as.h>
+#include <ddi.h>
+#include <async.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <thread.h>
+#include <bool.h>
+#include <errno.h>
+
+static int niagara_port_init(kbd_dev_t *);
+static void niagara_port_yield(void);
+static void niagara_port_reclaim(void);
+static void niagara_port_write(uint8_t data);
+
+kbd_port_ops_t niagara_port = {
+	.init = niagara_port_init,
+	.yield = niagara_port_yield,
+	.reclaim = niagara_port_reclaim,
+	.write = niagara_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+#define POLL_INTERVAL  10000
+
+/**
+ * Virtual address mapped to the buffer shared with the kernel counterpart.
+ */
+static uintptr_t input_buffer_addr;
+
+/*
+ * 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)
+
+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 volatile bool polling_disabled = false;
+static void niagara_thread_impl(void *arg);
+
+/**
+ * Initializes the Niagara driver.
+ * Maps the shared buffer and creates the polling thread. 
+ */
+static int niagara_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	
+	sysarg_t paddr;
+	if (sysinfo_get_value("niagara.inbuf.address", &paddr) != EOK)
+		return -1;
+	
+	input_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
+	int rc = physmem_map((void *) paddr, (void *) input_buffer_addr,
+	    1, AS_AREA_READ | AS_AREA_WRITE);
+	
+	if (rc != 0) {
+		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
+		    rc);
+		return rc;
+	}
+	
+	input_buffer = (input_buffer_t) input_buffer_addr;
+	
+	thread_id_t tid;
+	rc = thread_create(niagara_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0)
+		return rc;
+	
+	return 0;
+}
+
+static void niagara_port_yield(void)
+{
+	polling_disabled = true;
+}
+
+static void niagara_port_reclaim(void)
+{
+	polling_disabled = false;
+}
+
+static void niagara_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/**
+ * Called regularly by the polling thread. Reads codes of all the
+ * pressed keys from the buffer. 
+ */
+static void niagara_key_pressed(void)
+{
+	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;
+		kbd_push_data(kbd_dev, c);
+	}
+}
+
+/**
+ * Thread to poll Niagara console for keypresses.
+ */
+static void niagara_thread_impl(void *arg)
+{
+	(void) arg;
+
+	while (1) {
+		if (polling_disabled == false)
+			niagara_key_pressed();
+		usleep(POLL_INTERVAL);
+	}
+}
+/** @}
+ */
Index: uspace/srv/hid/input/port/ns16550.c
===================================================================
--- uspace/srv/hid/input/port/ns16550.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/ns16550.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief NS16550 port driver.
+ */
+
+#include <ipc/irc.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <sysinfo.h>
+#include <input.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <ddi.h>
+#include <errno.h>
+
+static int ns16550_port_init(kbd_dev_t *);
+static void ns16550_port_yield(void);
+static void ns16550_port_reclaim(void);
+static void ns16550_port_write(uint8_t data);
+
+kbd_port_ops_t ns16550_port = {
+	.init = ns16550_port_init,
+	.yield = ns16550_port_yield,
+	.reclaim = ns16550_port_reclaim,
+	.write = ns16550_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+/* NS16550 registers */
+#define RBR_REG  0  /** Receiver Buffer Register. */
+#define IER_REG  1  /** Interrupt Enable Register. */
+#define IIR_REG  2  /** Interrupt Ident Register (read). */
+#define FCR_REG  2  /** FIFO control register (write). */
+#define LCR_REG  3  /** Line Control register. */
+#define MCR_REG  4  /** Modem Control Register. */
+#define LSR_REG  5  /** Line Status Register. */
+
+#define LSR_DATA_READY  0x01
+
+static irq_cmd_t ns16550_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,     /* Will be patched in run-time */
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_BTEST,
+		.value = LSR_DATA_READY,
+		.srcarg = 1,
+		.dstarg = 3
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 2,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,     /* Will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+irq_code_t ns16550_kbd = {
+	sizeof(ns16550_cmds) / sizeof(irq_cmd_t),
+	ns16550_cmds
+};
+
+static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+static uintptr_t ns16550_physical;
+static uintptr_t ns16550_kernel;
+
+static kbd_dev_t *kbd_dev;
+
+static int ns16550_port_init(kbd_dev_t *kdev)
+{
+	void *vaddr;
+	
+	kbd_dev = kdev;
+	
+	sysarg_t ns16550;
+	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
+		return -1;
+	if (!ns16550)
+		return -1;
+	
+	if (sysinfo_get_value("kbd.address.physical", &ns16550_physical) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("kbd.address.kernel", &ns16550_kernel) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG);
+	ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG);
+	
+	async_set_interrupt_received(ns16550_irq_handler);
+	register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
+	
+	return pio_enable((void *) ns16550_physical, 8, &vaddr);
+}
+
+static void ns16550_port_yield(void)
+{
+}
+
+static void ns16550_port_reclaim(void)
+{
+}
+
+static void ns16550_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
+	
+	if (irc_service)
+		async_obsolete_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
+		    IPC_GET_IMETHOD(*call));
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/pl050.c
===================================================================
--- uspace/srv/hid/input/port/pl050.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/pl050.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2009 Vineeth Pillai
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup kbd
+ * @{
+ */ 
+/** @file
+ * @brief pl050 port driver.
+ */
+
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <async.h>
+#include <unistd.h>
+#include <sysinfo.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <ddi.h>
+#include <stdio.h>
+#include <errno.h>
+
+static int pl050_port_init(kbd_dev_t *);
+static void pl050_port_yield(void);
+static void pl050_port_reclaim(void);
+static void pl050_port_write(uint8_t data);
+
+kbd_port_ops_t pl050_port = {
+	.init = pl050_port_init,
+	.yield = pl050_port_yield,
+	.reclaim = pl050_port_reclaim,
+	.write = pl050_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+#define PL050_STAT_RXFULL  (1 << 4)
+
+static irq_cmd_t pl050_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_BTEST,
+		.value = PL050_STAT_RXFULL,
+		.srcarg = 1,
+		.dstarg = 3
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 2,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,  /* Will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t pl050_kbd = {
+	sizeof(pl050_cmds) / sizeof(irq_cmd_t),
+	pl050_cmds
+};
+
+static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+static int pl050_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	
+	sysarg_t addr;
+	if (sysinfo_get_value("kbd.address.status", &addr) != EOK)
+		return -1;
+	
+	pl050_kbd.cmds[0].addr = (void *) addr;
+	
+	if (sysinfo_get_value("kbd.address.data", &addr) != EOK)
+		return -1;
+	
+	pl050_kbd.cmds[3].addr = (void *) addr;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	async_set_interrupt_received(pl050_irq_handler);
+	register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
+	
+	return 0;
+}
+
+static void pl050_port_yield(void)
+{
+}
+
+static void pl050_port_reclaim(void)
+{
+}
+
+static void pl050_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/ski.c
===================================================================
--- uspace/srv/hid/input/port/ski.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/port/ski.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */ 
+/** @file
+ * @brief	Ski console keyboard port driver.
+ */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sys/types.h>
+#include <thread.h>
+#include <bool.h>
+
+static int ski_port_init(kbd_dev_t *);
+static void ski_port_yield(void);
+static void ski_port_reclaim(void);
+static void ski_port_write(uint8_t data);
+
+kbd_port_ops_t ski_port = {
+	.init = ski_port_init,
+	.yield = ski_port_yield,
+	.reclaim = ski_port_reclaim,
+	.write = ski_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+#define SKI_GETCHAR		21
+
+#define POLL_INTERVAL		10000
+
+static void ski_thread_impl(void *arg);
+static int32_t ski_getchar(void);
+
+static volatile bool polling_disabled = false;
+
+/** Initialize Ski port driver. */
+static int ski_port_init(kbd_dev_t *kdev)
+{
+	thread_id_t tid;
+	int rc;
+
+	kbd_dev = kdev;
+
+	rc = thread_create(ski_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0) {
+		return rc;
+	}
+
+	return 0;
+}
+
+static void ski_port_yield(void)
+{
+	polling_disabled = true;
+}
+
+static void ski_port_reclaim(void)
+{
+	polling_disabled = false;
+}
+
+static void ski_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/** Thread to poll Ski for keypresses. */
+static void ski_thread_impl(void *arg)
+{
+	int32_t c;
+	(void) arg;
+
+	while (1) {
+		while (polling_disabled == false) {
+			c = ski_getchar();
+			if (c == 0)
+				break;
+			kbd_push_data(kbd_dev, c);
+		}
+
+		usleep(POLL_INTERVAL);
+	}
+}
+
+/** Ask Ski if a key was pressed.
+ *
+ * Use SSC (Simulator System Call) to get character from the debug console.
+ * This call is non-blocking.
+ *
+ * @return ASCII code of pressed key or 0 if no key pressed.
+ */
+static int32_t ski_getchar(void)
+{
+	uint64_t ch;
+	
+#ifdef UARCH_ia64
+	asm volatile (
+		"mov r15 = %1\n"
+		"break 0x80000;;\n"	/* modifies r8 */
+		"mov %0 = r8;;\n"		
+
+		: "=r" (ch)
+		: "i" (SKI_GETCHAR)
+		: "r15", "r8"
+	);
+#else
+	ch = 0;
+#endif
+	return (int32_t) ch;
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/proto/adb.c
===================================================================
--- uspace/srv/hid/input/proto/adb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/proto/adb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief ADB protocol driver.
+ */
+
+#include <bool.h>
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+
+static mouse_dev_t *mouse_dev;
+static bool b1_pressed;
+static bool b2_pressed;
+
+static int adb_proto_init(mouse_dev_t *mdev)
+{
+	mouse_dev = mdev;
+	b1_pressed = false;
+	b2_pressed = false;
+	
+	return 0;
+}
+
+/** Process mouse data */
+static void adb_proto_parse(sysarg_t data)
+{
+	bool b1, b2;
+	uint16_t udx, udy;
+	int dx, dy;
+	
+	/* Extract fields. */
+	b1 = ((data >> 15) & 1) == 0;
+	udy = (data >> 8) & 0x7f;
+	b2 = ((data >> 7) & 1) == 0;
+	udx = data & 0x7f;
+	
+	/* Decode 7-bit two's complement signed values. */
+	dx = (udx & 0x40) ? (udx - 0x80) : udx;
+	dy = (udy & 0x40) ? (udy - 0x80) : udy;
+	
+	if (b1 != b1_pressed) {
+		mouse_push_event_button(mouse_dev, 1, b1);
+		b1_pressed = b1;
+	}
+	
+	if (b2 != b2_pressed) {
+		mouse_push_event_button(mouse_dev, 2, b2);
+		b1_pressed = b1;
+	}
+	
+	if (dx != 0 || dy != 0)
+		mouse_push_event_move(mouse_dev, dx, dy);
+}
+
+mouse_proto_ops_t adb_proto = {
+	.parse = adb_proto_parse,
+	.init = adb_proto_init
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/proto/mousedev.c
===================================================================
--- uspace/srv/hid/input/proto/mousedev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/proto/mousedev.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Mouse device connector controller driver.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <vfs/vfs_sess.h>
+#include <malloc.h>
+#include <async.h>
+#include <errno.h>
+#include <ipc/mouseev.h>
+#include <input.h>
+#include <loc.h>
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+#include <sys/typefmt.h>
+
+/** Mousedev softstate */
+typedef struct {
+	/** Link to generic mouse device */
+	mouse_dev_t *mouse_dev;
+	
+	/** Session to mouse device */
+	async_sess_t *sess;
+} mousedev_t;
+
+static mousedev_t *mousedev_new(mouse_dev_t *mdev)
+{
+	mousedev_t *mousedev = calloc(1, sizeof(mousedev_t));
+	if (mousedev == NULL)
+		return NULL;
+	
+	mousedev->mouse_dev = mdev;
+	
+	return mousedev;
+}
+
+static void mousedev_destroy(mousedev_t *mousedev)
+{
+	if (mousedev->sess != NULL)
+		async_hangup(mousedev->sess);
+	
+	free(mousedev);
+}
+
+static void mousedev_callback_conn(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
+{
+	/* Mousedev device structure */
+	mousedev_t *mousedev = (mousedev_t *) arg;
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* XXX Handle hangup */
+			return;
+		}
+		
+		int retval;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case MOUSEEV_MOVE_EVENT:
+			mouse_push_event_move(mousedev->mouse_dev, IPC_GET_ARG1(call),
+			    IPC_GET_ARG2(call));
+			retval = EOK;
+			break;
+		case MOUSEEV_BUTTON_EVENT:
+			mouse_push_event_button(mousedev->mouse_dev, IPC_GET_ARG1(call),
+			    IPC_GET_ARG2(call));
+			retval = EOK;
+			break;
+		default:
+			retval = ENOTSUP;
+			break;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int mousedev_proto_init(mouse_dev_t *mdev)
+{
+	async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE,
+	    mdev->svc_id, 0);
+	if (sess == NULL) {
+		printf("%s: Failed starting session with '%s'\n", NAME,
+		    mdev->svc_name);
+		return -1;
+	}
+	
+	mousedev_t *mousedev = mousedev_new(mdev);
+	if (mousedev == NULL) {
+		printf("%s: Failed allocating device structure for '%s'.\n",
+		    NAME, mdev->svc_name);
+		return -1;
+	}
+	
+	mousedev->sess = sess;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with '%s'.\n", NAME,
+		    mdev->svc_name);
+		mousedev_destroy(mousedev);
+		return -1;
+	}
+	
+	int rc = async_connect_to_me(exch, 0, 0, 0, mousedev_callback_conn, mousedev);
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		printf("%s: Failed creating callback connection from '%s'.\n",
+		    NAME, mdev->svc_name);
+		mousedev_destroy(mousedev);
+		return -1;
+	}
+	
+	return 0;
+}
+
+mouse_proto_ops_t mousedev_proto = {
+	.init = mousedev_proto_init
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/proto/ps2.c
===================================================================
--- uspace/srv/hid/input/proto/ps2.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/hid/input/proto/ps2.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief PS/2 protocol driver.
+ */
+
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+
+#define PS2_MOUSE_OUT_INIT  0xf4
+#define PS2_MOUSE_ACK       0xfa
+
+#define BUFSIZE 3
+
+typedef struct {
+	union {
+		unsigned char data[BUFSIZE];
+		struct {
+			unsigned int leftbtn : 1;
+			unsigned int rightbtn : 1;
+			unsigned int middlebtn : 1;
+			unsigned int isone : 1; /* Always one */
+			unsigned int xsign : 1;
+			unsigned int ysign : 1;
+			unsigned int xovfl : 1;
+			unsigned int yovfl : 1;
+			unsigned char x;
+			unsigned char y;
+		} val;
+	} u;
+} ps2packet_t;
+
+static ps2packet_t buf;
+static unsigned int bufpos;
+static unsigned int leftbtn;
+static unsigned int rightbtn;
+static unsigned int middlebtn;
+
+static mouse_dev_t *mouse_dev;
+
+static int ps2_proto_init(mouse_dev_t *mdev)
+{
+	mouse_dev = mdev;
+	bufpos = 0;
+	leftbtn = 0;
+	rightbtn = 0;
+	
+	mouse_dev->port_ops->write(PS2_MOUSE_OUT_INIT);
+	return 0;
+}
+
+/** Convert 9-bit 2-complement signed number to integer */
+static int bit9toint(int sign, unsigned char data)
+{
+	int tmp;
+	
+	if (!sign)
+		return data;
+	
+	tmp = ((unsigned char) ~data) + 1;
+	return -tmp;
+}
+
+/** Process mouse data */
+static void ps2_proto_parse(sysarg_t data)
+{
+	int x, y;
+	
+	/* Check that we have not lost synchronization */
+	if (bufpos == 0 && !(data & 0x8))
+		return; /* Synchro lost, ignore byte */
+	
+	buf.u.data[bufpos++] = data;
+	if (bufpos == BUFSIZE) {
+		bufpos = 0;
+		
+		if (buf.u.val.leftbtn ^ leftbtn) {
+			leftbtn = buf.u.val.leftbtn;
+			mouse_push_event_button(mouse_dev, 1, leftbtn);
+		}
+		
+		if (buf.u.val.rightbtn ^ rightbtn) {
+			rightbtn = buf.u.val.rightbtn;
+			mouse_push_event_button(mouse_dev, 2, rightbtn);
+		}
+		
+		if (buf.u.val.middlebtn ^ middlebtn) {
+			middlebtn = buf.u.val.middlebtn;
+			mouse_push_event_button(mouse_dev, 3, middlebtn);
+		}
+		
+		x = bit9toint(buf.u.val.xsign, buf.u.val.x);
+		y = -bit9toint(buf.u.val.ysign, buf.u.val.y);
+		
+		if (x != 0 || y != 0)
+			mouse_push_event_move(mouse_dev, x, y);
+	}
+}
+
+mouse_proto_ops_t ps2_proto = {
+	.parse = ps2_proto_parse,
+	.init = ps2_proto_init
+};
+
+/**
+ * @}
+ */
Index: pace/srv/hid/kbd/Makefile
===================================================================
--- uspace/srv/hid/kbd/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,167 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
-EXTRA_CFLAGS = -Iinclude
-BINARY = kbd
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-## Sources
-#
-
-SOURCES = \
-	generic/kbd.c \
-	genarch/gsp.c \
-	genarch/stroke.c \
-	layout/cz.c \
-	layout/us_qwerty.c \
-	layout/us_dvorak.c
-
-ifeq ($(UARCH),amd64)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(UARCH),arm32)
-	ifeq ($(MACHINE),gta02)
-		SOURCES += \
-			port/chardev.c \
-			ctl/stty.c
-	endif
-	ifeq ($(MACHINE),testarm)
-		SOURCES += \
-			port/gxemul.c
-		
-		ifeq ($(CONFIG_FB),y)
-			SOURCES += \
-				ctl/gxe_fb.c
-		else
-			SOURCES += \
-				ctl/stty.c
-		endif
-	endif
-	ifeq ($(MACHINE),integratorcp)
-		SOURCES += \
-			port/pl050.c \
-			ctl/pl050.c
-	endif
-endif
-
-ifeq ($(UARCH),ia32)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(MACHINE),i460GX)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(MACHINE),ski)
-	SOURCES += \
-		port/ski.c \
-		ctl/stty.c
-endif
-
-ifeq ($(MACHINE),msim)
-	SOURCES += \
-		port/msim.c \
-		ctl/stty.c
-endif
-
-ifeq ($(MACHINE),lgxemul)
-	SOURCES += \
-		port/gxemul.c
-	
-	ifeq ($(CONFIG_FB),y)
-		SOURCES += \
-			ctl/gxe_fb.c
-	else
-		SOURCES += \
-			ctl/stty.c
-	endif
-endif
-
-ifeq ($(MACHINE),bgxemul)
-	SOURCES += \
-		port/gxemul.c
-	
-	ifeq ($(CONFIG_FB),y)
-		SOURCES += \
-			ctl/gxe_fb.c
-	else
-		SOURCES += \
-			ctl/stty.c
-	endif
-endif
-
-ifeq ($(UARCH),ppc32)
-	SOURCES += \
-		port/adb.c \
-		ctl/apple.c
-endif
-
-ifeq ($(UARCH),sparc64)
-	ifeq ($(PROCESSOR),sun4v)
-		SOURCES += \
-			port/niagara.c \
-			ctl/stty.c
-	else
-		ifeq ($(MACHINE),serengeti)
-			SOURCES += \
-				port/sgcn.c \
-				ctl/stty.c
-		endif
-		ifeq ($(MACHINE),generic)
-			SOURCES += \
-			port/sun.c \
-			port/z8530.c \
-			port/ns16550.c \
-			ctl/sun.c
-		endif
-	endif
-endif
-
-ifeq ($(UARCH),abs32le)
-	SOURCES += \
-		port/dummy.c \
-		ctl/pc.c
-endif
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hid/kbd/ctl/apple.c
===================================================================
--- uspace/srv/hid/kbd/ctl/apple.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,209 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief	Apple ADB keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-
-#define KBD_KEY_RELEASE		0x80
-
-static int scanmap[];
-
-int kbd_ctl_init(void)
-{
-	return 0;
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	console_ev_type_t type;
-	unsigned int key;
-
-	if (scancode < 0 || scancode >= 0x100)
-		return;
-
-	if (scancode & KBD_KEY_RELEASE) {
-		scancode &= ~KBD_KEY_RELEASE;
-		type = KEY_RELEASE;
-	} else {
-		type = KEY_PRESS;
-	}
-
-	key = scanmap[scancode];
-	if (key != 0)
-		kbd_push_ev(type, key);
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-static int scanmap[] = {
-	[0x00] = KC_A,
-	[0x01] = KC_S,
-	[0x02] = KC_D,
-	[0x03] = KC_F,
-	[0x04] = KC_H,
-	[0x05] = KC_G,
-	[0x06] = KC_Z,
-	[0x07] = KC_X,
-	[0x08] = KC_C,
-	[0x09] = KC_V,
-	[0x0a] = KC_BACKSLASH,
-	[0x0b] = KC_B,
-	[0x0c] = KC_Q,
-	[0x0d] = KC_W,
-	[0x0e] = KC_E,
-	[0x0f] = KC_R,
-	[0x10] = KC_Y,
-	[0x11] = KC_T,
-	[0x12] = KC_1,
-	[0x13] = KC_2,
-	[0x14] = KC_3,
-	[0x15] = KC_4,
-	[0x16] = KC_6,
-	[0x17] = KC_5,
-	[0x18] = KC_EQUALS,
-	[0x19] = KC_9,
-	[0x1a] = KC_7,
-	[0x1b] = KC_MINUS,
-	[0x1c] = KC_8,
-	[0x1d] = KC_0,
-	[0x1e] = KC_RBRACKET,
-	[0x1f] = KC_O,
-	[0x20] = KC_U,
-	[0x21] = KC_LBRACKET,
-	[0x22] = KC_I,
-	[0x23] = KC_P,
-	[0x24] = KC_ENTER,
-	[0x25] = KC_L,
-	[0x26] = KC_J,
-	[0x27] = KC_QUOTE,
-	[0x28] = KC_K,
-	[0x29] = KC_SEMICOLON,
-	[0x2a] = KC_BACKSLASH,
-	[0x2b] = KC_COMMA,
-	[0x2c] = KC_SLASH,
-	[0x2d] = KC_N,
-	[0x2e] = KC_M,
-	[0x2f] = KC_PERIOD,
-	[0x30] = KC_TAB,
-	[0x31] = KC_SPACE,
-	[0x32] = KC_BACKTICK,
-	[0x33] = KC_BACKSPACE,
-	[0x34] = 0,
-	[0x35] = KC_ESCAPE,
-	[0x36] = KC_LCTRL,
-	[0x37] = 0,
-	[0x38] = KC_LSHIFT,
-	[0x39] = KC_CAPS_LOCK,
-	[0x3a] = KC_LALT,
-	[0x3b] = KC_LEFT,
-	[0x3c] = KC_RIGHT,
-	[0x3d] = KC_DOWN,
-	[0x3e] = KC_UP,
-	[0x3f] = 0,
-	[0x40] = 0,
-	[0x41] = KC_NPERIOD,
-	[0x42] = 0,
-	[0x43] = KC_NTIMES,
-	[0x44] = 0,
-	[0x45] = KC_NPLUS,
-	[0x46] = 0,
-	[0x47] = KC_NUM_LOCK,
-	[0x48] = 0,
-	[0x49] = 0,
-	[0x4a] = 0,
-	[0x4b] = KC_NSLASH,
-	[0x4c] = KC_NENTER,
-	[0x4d] = 0,
-	[0x4e] = KC_NMINUS,
-	[0x4f] = 0,
-	[0x50] = 0,
-	[0x51] = 0,
-	[0x52] = KC_N0,
-	[0x53] = KC_N1,
-	[0x54] = KC_N2,
-	[0x55] = KC_N3,
-	[0x56] = KC_N4,
-	[0x57] = KC_N5,
-	[0x58] = KC_N6,
-	[0x59] = KC_N7,
-	[0x5a] = 0,
-	[0x5b] = KC_N8,
-	[0x5c] = KC_N9,
-	[0x5d] = 0,
-	[0x5e] = 0,
-	[0x5f] = 0,
-	[0x60] = KC_F5,
-	[0x61] = KC_F6,
-	[0x62] = KC_F7,
-	[0x63] = KC_F3,
-	[0x64] = KC_F8,
-	[0x65] = KC_F9,
-	[0x66] = 0,
-	[0x67] = KC_F11,
-	[0x68] = 0,
-	[0x69] = 0,
-	[0x6a] = 0,
-	[0x6b] = KC_SCROLL_LOCK,
-	[0x6c] = 0,
-	[0x6d] = KC_F10,
-	[0x6e] = 0,
-	[0x6f] = KC_F12,
-	[0x70] = 0,
-	[0x71] = 0,
-	[0x72] = KC_INSERT,
-	[0x73] = KC_HOME,
-	[0x74] = KC_PAGE_UP,
-	[0x75] = KC_DELETE,
-	[0x76] = KC_F4,
-	[0x77] = KC_END,
-	[0x78] = KC_F2,
-	[0x79] = KC_PAGE_DOWN,
-	[0x7a] = KC_F1,
-	[0x7b] = KC_RSHIFT,
-	[0x7c] = KC_RALT,
-	[0x7d] = KC_RCTRL,
-	[0x7e] = 0,
-	[0x7f] = 0
-};
-
-/** @}
- */
Index: pace/srv/hid/kbd/ctl/gxe_fb.c
===================================================================
--- uspace/srv/hid/kbd/ctl/gxe_fb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,234 +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 kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief	GXEmul framebuffer-mode keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <gsp.h>
-#include <stroke.h>
-
-/** Scancode parser */
-static gsp_t sp;
-
-/** Current parser state */
-static int ds;
-
-#include <stdio.h>
-
-int seq_defs[] = {
-	/* Not shifted */
-
-	0,	KC_BACKTICK,	0x60, GSP_END,
-
-	0,	KC_1,		0x31, GSP_END,
-	0,	KC_2,		0x32, GSP_END,
-	0,	KC_3,		0x33, GSP_END,
-	0,	KC_4,		0x34, GSP_END,
-	0,	KC_5,		0x35, GSP_END,
-	0,	KC_6,		0x36, GSP_END,
-	0,	KC_7,		0x37, GSP_END,
-	0,	KC_8,		0x38, GSP_END,
-	0,	KC_9,		0x39, GSP_END,
-	0,	KC_0,		0x30, GSP_END,
-
-	0,	KC_MINUS,	0x2d, GSP_END,
-	0,	KC_EQUALS,	0x3d, GSP_END,
-	0,	KC_BACKSPACE,	0x08, GSP_END,
-
-	0,	KC_TAB,		0x09, GSP_END,
-
-	0,	KC_Q,		0x71, GSP_END,
-	0,	KC_W,		0x77, GSP_END,
-	0,	KC_E,		0x65, GSP_END,
-	0,	KC_R,		0x72, GSP_END,
-	0,	KC_T,		0x74, GSP_END,
-	0,	KC_Y,		0x79, GSP_END,
-	0,	KC_U,		0x75, GSP_END,
-	0,	KC_I,		0x69, GSP_END,
-	0,	KC_O,		0x6f, GSP_END,
-	0,	KC_P,		0x70, GSP_END,
-
-	0,	KC_LBRACKET,	0x5b, GSP_END,
-	0,	KC_RBRACKET,	0x5d, GSP_END,
-
-	0,	KC_A,		0x61, GSP_END,
-	0,	KC_S,		0x73, GSP_END,
-	0,	KC_D,		0x64, GSP_END,
-	0,	KC_F,		0x66, GSP_END,
-	0,	KC_G,		0x67, GSP_END,
-	0,	KC_H,		0x68, GSP_END,
-	0,	KC_J,		0x6a, GSP_END,
-	0,	KC_K,		0x6b, GSP_END,
-	0,	KC_L,		0x6c, GSP_END,
-
-	0,	KC_SEMICOLON,	0x3b, GSP_END,
-	0,	KC_QUOTE,	0x27, GSP_END,
-	0,	KC_BACKSLASH,	0x5c, GSP_END,
-
-	0,	KC_Z,		0x7a, GSP_END,
-	0,	KC_X,		0x78, GSP_END,
-	0,	KC_C,		0x63, GSP_END,
-	0,	KC_V,		0x76, GSP_END,
-	0,	KC_B,		0x62, GSP_END,
-	0,	KC_N,		0x6e, GSP_END,
-	0,	KC_M,		0x6d, GSP_END,
-
-	0,	KC_COMMA,	0x2c, GSP_END,
-	0,	KC_PERIOD,	0x2e, GSP_END,
-	0,	KC_SLASH,	0x2f, GSP_END,
-
-	/* Shifted */
-
-	KM_SHIFT,	KC_BACKTICK,	0x7e, GSP_END,
-
-	KM_SHIFT,	KC_1,		0x21, GSP_END,
-	KM_SHIFT,	KC_2,		0x40, GSP_END,
-	KM_SHIFT,	KC_3,		0x23, GSP_END,
-	KM_SHIFT,	KC_4,		0x24, GSP_END,
-	KM_SHIFT,	KC_5,		0x25, GSP_END,
-	KM_SHIFT,	KC_6,		0x5e, GSP_END,
-	KM_SHIFT,	KC_7,		0x26, GSP_END,
-	KM_SHIFT,	KC_8,		0x2a, GSP_END,
-	KM_SHIFT,	KC_9,		0x28, GSP_END,
-	KM_SHIFT,	KC_0,		0x29, GSP_END,
-
-	KM_SHIFT,	KC_MINUS,	0x5f, GSP_END,
-	KM_SHIFT,	KC_EQUALS,	0x2b, GSP_END,
-
-	KM_SHIFT,	KC_Q,		0x51, GSP_END,
-	KM_SHIFT,	KC_W,		0x57, GSP_END,
-	KM_SHIFT,	KC_E,		0x45, GSP_END,
-	KM_SHIFT,	KC_R,		0x52, GSP_END,
-	KM_SHIFT,	KC_T,		0x54, GSP_END,
-	KM_SHIFT,	KC_Y,		0x59, GSP_END,
-	KM_SHIFT,	KC_U,		0x55, GSP_END,
-	KM_SHIFT,	KC_I,		0x49, GSP_END,
-	KM_SHIFT,	KC_O,		0x4f, GSP_END,
-	KM_SHIFT,	KC_P,		0x50, GSP_END,
-
-	KM_SHIFT,	KC_LBRACKET,	0x7b, GSP_END,
-	KM_SHIFT,	KC_RBRACKET,	0x7d, GSP_END,
-
-	KM_SHIFT,	KC_A,		0x41, GSP_END,
-	KM_SHIFT,	KC_S,		0x53, GSP_END,
-	KM_SHIFT,	KC_D,		0x44, GSP_END,
-	KM_SHIFT,	KC_F,		0x46, GSP_END,
-	KM_SHIFT,	KC_G,		0x47, GSP_END,
-	KM_SHIFT,	KC_H,		0x48, GSP_END,
-	KM_SHIFT,	KC_J,		0x4a, GSP_END,
-	KM_SHIFT,	KC_K,		0x4b, GSP_END,
-	KM_SHIFT,	KC_L,		0x4c, GSP_END,
-
-	KM_SHIFT,	KC_SEMICOLON,	0x3a, GSP_END,
-	KM_SHIFT,	KC_QUOTE,	0x22, GSP_END,
-	KM_SHIFT,	KC_BACKSLASH,	0x7c, GSP_END,
-
-	KM_SHIFT,	KC_Z,		0x5a, GSP_END,
-	KM_SHIFT,	KC_X,		0x58, GSP_END,
-	KM_SHIFT,	KC_C,		0x43, GSP_END,
-	KM_SHIFT,	KC_V,		0x56, GSP_END,
-	KM_SHIFT,	KC_B,		0x42, GSP_END,
-	KM_SHIFT,	KC_N,		0x4e, GSP_END,
-	KM_SHIFT,	KC_M,		0x4d, GSP_END,
-
-	KM_SHIFT,	KC_COMMA,	0x3c, GSP_END,
-	KM_SHIFT,	KC_PERIOD,	0x3e, GSP_END,
-	KM_SHIFT,	KC_SLASH,	0x3f, GSP_END,
-
-	/* ... */
-
-	0,	KC_SPACE,	0x20, GSP_END,
-	0,	KC_ENTER,	0x0a, GSP_END,
-	0,	KC_ENTER,	0x0d, GSP_END,
-
-	0,	KC_ESCAPE,	0x1b, 0x1b, GSP_END,
-
-	0,	KC_F1,		0x1b, 0x5b, 0x4f, 0x50, GSP_END,
-	0,	KC_F2,		0x1b, 0x5b, 0x4f, 0x51, GSP_END,
-	0,	KC_F3,		0x1b, 0x5b, 0x4f, 0x52, GSP_END,
-	0,	KC_F4,		0x1b, 0x5b, 0x4f, 0x53, GSP_END,
-	0,	KC_F5,		0x1b, 0x5b, 0x31, 0x35, GSP_END,
-	0,	KC_F6,		0x1b, 0x5b, 0x31, 0x37, GSP_END,
-	0,	KC_F7,		0x1b, 0x5b, 0x31, 0x38, GSP_END,
-	0,	KC_F8,		0x1b, 0x5b, 0x31, 0x39, GSP_END,
-	0,	KC_F9,		0x1b, 0x5b, 0x32, 0x38, GSP_END,
-	0,	KC_F10,		0x1b, 0x5b, 0x32, 0x39, GSP_END,
-	0,	KC_F11,		0x1b, 0x5b, 0x32, 0x33, GSP_END,
-	0,	KC_F12,		0x1b, 0x5b, 0x32, 0x34, GSP_END,
-
-	0,	KC_INSERT,	0x1b, 0x5b, 0x32, 0x7e, GSP_END,
-	0,	KC_HOME,	0x1b, 0x5b, 0x48, GSP_END,
-	0,	KC_PAGE_UP,	0x1b, 0x5b, 0x35, 0x7e, GSP_END,
-	0,	KC_DELETE,	0x1b, 0x5b, 0x33, 0x7e, GSP_END,
-	0,	KC_END,		0x1b, 0x5b, 0x46, GSP_END,
-	0,	KC_PAGE_DOWN,	0x1b, 0x5b, 0x36, 0x7e, GSP_END,
-
-	0,	KC_UP,		0x1b, 0x5b, 0x41, GSP_END,
-	0,	KC_LEFT,	0x1b, 0x5b, 0x44, GSP_END,
-	0,	KC_DOWN,	0x1b, 0x5b, 0x42, GSP_END,
-	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
-
-	0,	0
-};
-
-int kbd_ctl_init(void)
-{
-	ds = 0;
-
-	gsp_init(&sp);
-	return gsp_insert_defs(&sp, seq_defs);
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	unsigned mods, key;
-
-	ds = gsp_step(&sp, ds, scancode, &mods, &key);
-	if (key != 0) {
-		stroke_sim(mods, key);
-	}
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/ctl/pc.c
===================================================================
--- uspace/srv/hid/kbd/ctl/pc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,273 +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 kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief PC keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <kbd_port.h>
-#include <gsp.h>
-
-enum dec_state {
-	ds_s,
-	ds_e
-};
-
-enum special_code {
-	SC_ACK = 0xfa,
-	SC_NAK = 0xfe
-};
-
-enum lock_ind_bits {
-	LI_SCROLL	= 0x01,
-	LI_NUM		= 0x02,
-	LI_CAPS		= 0x04
-};
-
-enum kbd_command {
-	KBD_CMD_SET_LEDS = 0xed
-};
-
-static enum dec_state ds;
-
-static int scanmap_simple[] = {
-
-	[0x29] = KC_BACKTICK,
-
-	[0x02] = KC_1,
-	[0x03] = KC_2,
-	[0x04] = KC_3,
-	[0x05] = KC_4,
-	[0x06] = KC_5,
-	[0x07] = KC_6,
-	[0x08] = KC_7,
-	[0x09] = KC_8,
-	[0x0a] = KC_9,
-	[0x0b] = KC_0,
-
-	[0x0c] = KC_MINUS,
-	[0x0d] = KC_EQUALS,
-	[0x0e] = KC_BACKSPACE,
-
-	[0x0f] = KC_TAB,
-
-	[0x10] = KC_Q,
-	[0x11] = KC_W,
-	[0x12] = KC_E,
-	[0x13] = KC_R,
-	[0x14] = KC_T,
-	[0x15] = KC_Y,
-	[0x16] = KC_U,
-	[0x17] = KC_I,
-	[0x18] = KC_O,
-	[0x19] = KC_P,
-
-	[0x1a] = KC_LBRACKET,
-	[0x1b] = KC_RBRACKET,
-
-	[0x3a] = KC_CAPS_LOCK,
-
-	[0x1e] = KC_A,
-	[0x1f] = KC_S,
-	[0x20] = KC_D,
-	[0x21] = KC_F,
-	[0x22] = KC_G,
-	[0x23] = KC_H,
-	[0x24] = KC_J,
-	[0x25] = KC_K,
-	[0x26] = KC_L,
-
-	[0x27] = KC_SEMICOLON,
-	[0x28] = KC_QUOTE,
-	[0x2b] = KC_BACKSLASH,
-
-	[0x2a] = KC_LSHIFT,
-
-	[0x2c] = KC_Z,
-	[0x2d] = KC_X,
-	[0x2e] = KC_C,
-	[0x2f] = KC_V,
-	[0x30] = KC_B,
-	[0x31] = KC_N,
-	[0x32] = KC_M,
-
-	[0x33] = KC_COMMA,
-	[0x34] = KC_PERIOD,
-	[0x35] = KC_SLASH,
-
-	[0x36] = KC_RSHIFT,
-
-	[0x1d] = KC_LCTRL,
-	[0x38] = KC_LALT,
-	[0x39] = KC_SPACE,
-
-	[0x01] = KC_ESCAPE,
-
-	[0x3b] = KC_F1,
-	[0x3c] = KC_F2,
-	[0x3d] = KC_F3,
-	[0x3e] = KC_F4,
-	[0x3f] = KC_F5,
-	[0x40] = KC_F6,
-	[0x41] = KC_F7,
-
-	[0x42] = KC_F8,
-	[0x43] = KC_F9,
-	[0x44] = KC_F10,
-
-	[0x57] = KC_F11,
-	[0x58] = KC_F12,
-
-	[0x46] = KC_SCROLL_LOCK,
-
-	[0x1c] = KC_ENTER,
-
-	[0x45] = KC_NUM_LOCK,
-	[0x37] = KC_NTIMES,
-	[0x4a] = KC_NMINUS,
-	[0x4e] = KC_NPLUS,
-	[0x47] = KC_N7,
-	[0x48] = KC_N8,
-	[0x49] = KC_N9,
-	[0x4b] = KC_N4,
-	[0x4c] = KC_N5,
-	[0x4d] = KC_N6,
-	[0x4f] = KC_N1,
-	[0x50] = KC_N2,
-	[0x51] = KC_N3,
-	[0x52] = KC_N0,
-	[0x53] = KC_NPERIOD
-};
-
-static int scanmap_e0[] = {
-	[0x38] = KC_RALT,
-	[0x1d] = KC_RSHIFT,
-
-	[0x37] = KC_PRTSCR,
-
-	[0x52] = KC_INSERT,
-	[0x47] = KC_HOME,
-	[0x49] = KC_PAGE_UP,
-
-	[0x53] = KC_DELETE,
-	[0x4f] = KC_END,
-	[0x51] = KC_PAGE_DOWN,
-
-	[0x48] = KC_UP,
-	[0x4b] = KC_LEFT,
-	[0x50] = KC_DOWN,
-	[0x4d] = KC_RIGHT,
-
-	[0x35] = KC_NSLASH,
-	[0x1c] = KC_NENTER
-};
-
-int kbd_ctl_init(void)
-{
-	ds = ds_s;
-	return 0;
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	console_ev_type_t type;
-	unsigned int key;
-	int *map;
-	size_t map_length;
-
-	/*
-	 * ACK/NAK are returned as response to us sending a command.
-	 * We are not interested in them.
-	 */
-	if (scancode == SC_ACK || scancode == SC_NAK)
-		return;
-
-	if (scancode == 0xe0) {
-		ds = ds_e;
-		return;
-	}
-
-	switch (ds) {
-	case ds_s:
-		map = scanmap_simple;
-		map_length = sizeof(scanmap_simple) / sizeof(int);
-		break;
-	case ds_e:
-		map = scanmap_e0;
-		map_length = sizeof(scanmap_e0) / sizeof(int);
-		break;
-	default:
-		map = NULL;
-		map_length = 0;
-	}
-
-	ds = ds_s;
-
-	if (scancode & 0x80) {
-		scancode &= ~0x80;
-		type = KEY_RELEASE;
-	} else {
-		type = KEY_PRESS;
-	}
-
-	if ((scancode < 0) || ((size_t) scancode >= map_length))
-		return;
-
-	key = map[scancode];
-	if (key != 0)
-		kbd_push_ev(type, key);
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	uint8_t b;
-
-	b = 0;
-	if ((mods & KM_CAPS_LOCK) != 0)
-		b = b | LI_CAPS;
-	if ((mods & KM_NUM_LOCK) != 0)
-		b = b | LI_NUM;
-	if ((mods & KM_SCROLL_LOCK) != 0)
-		b = b | LI_SCROLL;
-
-	kbd_port_write(KBD_CMD_SET_LEDS);
-	kbd_port_write(b);
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/ctl/pl050.c
===================================================================
--- uspace/srv/hid/kbd/ctl/pl050.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,267 +1,0 @@
-/*
- * Copyright (c) 2009 Vineeth Pillai
- * 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_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief PL050 keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <gsp.h>
-#include <stdio.h>
-
-#define PL050_CAPS_SCAN_CODE 0x58
-#define PL050_NUM_SCAN_CODE 0x77
-#define PL050_SCROLL_SCAN_CODE 0x7E
-
-static bool is_lock_key(int);
-enum dec_state {
-	ds_s,
-	ds_e
-};
-
-static enum dec_state ds;
-
-static int scanmap_simple[] = {
-
-	[0x0e] = KC_BACKTICK,
-
-	[0x16] = KC_1,
-	[0x1e] = KC_2,
-	[0x26] = KC_3,
-	[0x25] = KC_4,
-	[0x2e] = KC_5,
-	[0x36] = KC_6,
-	[0x3d] = KC_7,
-	[0x3e] = KC_8,
-	[0x46] = KC_9,
-	[0x45] = KC_0,
-
-	[0x4e] = KC_MINUS,
-	[0x55] = KC_EQUALS,
-	[0x66] = KC_BACKSPACE,
-
-	[0x0d] = KC_TAB,
-
-	[0x15] = KC_Q,
-	[0x1d] = KC_W,
-	[0x24] = KC_E,
-	[0x2d] = KC_R,
-	[0x2c] = KC_T,
-	[0x35] = KC_Y,
-	[0x3c] = KC_U,
-	[0x43] = KC_I,
-	[0x44] = KC_O,
-	[0x4d] = KC_P,
-
-	[0x54] = KC_LBRACKET,
-	[0x5b] = KC_RBRACKET,
-
-	[0x58] = KC_CAPS_LOCK,
-
-	[0x1c] = KC_A,
-	[0x1b] = KC_S,
-	[0x23] = KC_D,
-	[0x2b] = KC_F,
-	[0x34] = KC_G,
-	[0x33] = KC_H,
-	[0x3b] = KC_J,
-	[0x42] = KC_K,
-	[0x4b] = KC_L,
-
-	[0x4c] = KC_SEMICOLON,
-	[0x52] = KC_QUOTE,
-	[0x5d] = KC_BACKSLASH,
-
-	[0x12] = KC_LSHIFT,
-
-	[0x1a] = KC_Z,
-	[0x22] = KC_X,
-	[0x21] = KC_C,
-	[0x2a] = KC_V,
-	[0x32] = KC_B,
-	[0x31] = KC_N,
-	[0x3a] = KC_M,
-
-	[0x41] = KC_COMMA,
-	[0x49] = KC_PERIOD,
-	[0x4a] = KC_SLASH,
-
-	[0x59] = KC_RSHIFT,
-
-	[0x14] = KC_LCTRL,
-	[0x11] = KC_LALT,
-	[0x29] = KC_SPACE,
-
-	[0x76] = KC_ESCAPE,
-
-	[0x05] = KC_F1,
-	[0x06] = KC_F2,
-	[0x04] = KC_F3,
-	[0x0c] = KC_F4,
-	[0x03] = KC_F5,
-	[0x0b] = KC_F6,
-	[0x02] = KC_F7,
-
-	[0x0a] = KC_F8,
-	[0x01] = KC_F9,
-	[0x09] = KC_F10,
-
-	[0x78] = KC_F11,
-	[0x07] = KC_F12,
-
-	[0x60] = KC_SCROLL_LOCK,
-
-	[0x5a] = KC_ENTER,
-
-	[0x77] = KC_NUM_LOCK,
-	[0x7c] = KC_NTIMES,
-	[0x7b] = KC_NMINUS,
-	[0x79] = KC_NPLUS,
-	[0x6c] = KC_N7,
-	[0x75] = KC_N8,
-	[0x7d] = KC_N9,
-	[0x6b] = KC_N4,
-	[0x73] = KC_N5,
-	[0x74] = KC_N6,
-	[0x69] = KC_N1,
-	[0x72] = KC_N2,
-	[0x7a] = KC_N3,
-	[0x70] = KC_N0,
-	[0x71] = KC_NPERIOD
-};
-
-static int scanmap_e0[] = {
-	[0x65] = KC_RALT,
-	[0x59] = KC_RSHIFT,
-
-	[0x64] = KC_PRTSCR,
-
-	[0x70] = KC_INSERT,
-	[0x6c] = KC_HOME,
-	[0x7d] = KC_PAGE_UP,
-
-	[0x71] = KC_DELETE,
-	[0x69] = KC_END,
-	[0x7a] = KC_PAGE_DOWN,
-
-	[0x75] = KC_UP,
-	[0x6b] = KC_LEFT,
-	[0x72] = KC_DOWN,
-	[0x74] = KC_RIGHT,
-
-	[0x4a] = KC_NSLASH,
-	[0x5a] = KC_NENTER
-};
-
-int kbd_ctl_init(void)
-{
-	ds = ds_s;
-	return 0;
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	static int key_release_flag = 0;
-	static int is_locked = 0;
-	console_ev_type_t type;
-	unsigned int key;
-	int *map;
-	size_t map_length;
-
-	if (scancode == 0xe0) {
-		ds = ds_e;
-		return;
-	}
-
-	switch (ds) {
-	case ds_s:
-		map = scanmap_simple;
-		map_length = sizeof(scanmap_simple) / sizeof(int);
-		break;
-	case ds_e:
-		map = scanmap_e0;
-		map_length = sizeof(scanmap_e0) / sizeof(int);
-		break;
-	default:
-		map = NULL;
-		map_length = 0;
-	}
-
-	ds = ds_s;
-	if (scancode == 0xf0) {
-		key_release_flag = 1;
-		return;
-	} else {
-		if (key_release_flag) {
-			type = KEY_RELEASE;
-			key_release_flag = 0;
-			if (is_lock_key(scancode)) {
-				if (!is_locked) {
-					is_locked = 1;
-				} else {
-					is_locked = 0;
-					return;
-				}
-			}
-		} else {
-			if (is_lock_key(scancode) && is_locked)
-				return;
-			type = KEY_PRESS;
-		}
-	}
-
-	if (scancode < 0)
-		return;
-
-	key = map[scancode];
-	if (key != 0)
-		kbd_push_ev(type, key);
-}
-
-static bool is_lock_key(int sc)
-{
-	return ((sc == PL050_CAPS_SCAN_CODE) || (sc == PL050_NUM_SCAN_CODE) ||
-	    (sc == PL050_SCROLL_SCAN_CODE));
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/ctl/stty.c
===================================================================
--- uspace/srv/hid/kbd/ctl/stty.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,233 +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 kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief	Serial TTY-like keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <gsp.h>
-#include <stroke.h>
-
-/** Scancode parser */
-static gsp_t sp;
-
-/** Current parser state */
-static int ds;
-
-#include <stdio.h>
-
-int seq_defs[] = {
-	/* Not shifted */
-
-	0,	KC_BACKTICK,	0x60, GSP_END,
-
-	0,	KC_1,		0x31, GSP_END,
-	0,	KC_2,		0x32, GSP_END,
-	0,	KC_3,		0x33, GSP_END,
-	0,	KC_4,		0x34, GSP_END,
-	0,	KC_5,		0x35, GSP_END,
-	0,	KC_6,		0x36, GSP_END,
-	0,	KC_7,		0x37, GSP_END,
-	0,	KC_8,		0x38, GSP_END,
-	0,	KC_9,		0x39, GSP_END,
-	0,	KC_0,		0x30, GSP_END,
-
-	0,	KC_MINUS,	0x2d, GSP_END,
-	0,	KC_EQUALS,	0x3d, GSP_END,
-	0,	KC_BACKSPACE,	0x08, GSP_END,
-
-	0,	KC_TAB,		0x09, GSP_END,
-
-	0,	KC_Q,		0x71, GSP_END,
-	0,	KC_W,		0x77, GSP_END,
-	0,	KC_E,		0x65, GSP_END,
-	0,	KC_R,		0x72, GSP_END,
-	0,	KC_T,		0x74, GSP_END,
-	0,	KC_Y,		0x79, GSP_END,
-	0,	KC_U,		0x75, GSP_END,
-	0,	KC_I,		0x69, GSP_END,
-	0,	KC_O,		0x6f, GSP_END,
-	0,	KC_P,		0x70, GSP_END,
-
-	0,	KC_LBRACKET,	0x5b, GSP_END,
-	0,	KC_RBRACKET,	0x5d, GSP_END,
-
-	0,	KC_A,		0x61, GSP_END,
-	0,	KC_S,		0x73, GSP_END,
-	0,	KC_D,		0x64, GSP_END,
-	0,	KC_F,		0x66, GSP_END,
-	0,	KC_G,		0x67, GSP_END,
-	0,	KC_H,		0x68, GSP_END,
-	0,	KC_J,		0x6a, GSP_END,
-	0,	KC_K,		0x6b, GSP_END,
-	0,	KC_L,		0x6c, GSP_END,
-
-	0,	KC_SEMICOLON,	0x3b, GSP_END,
-	0,	KC_QUOTE,	0x27, GSP_END,
-	0,	KC_BACKSLASH,	0x5c, GSP_END,
-
-	0,	KC_Z,		0x7a, GSP_END,
-	0,	KC_X,		0x78, GSP_END,
-	0,	KC_C,		0x63, GSP_END,
-	0,	KC_V,		0x76, GSP_END,
-	0,	KC_B,		0x62, GSP_END,
-	0,	KC_N,		0x6e, GSP_END,
-	0,	KC_M,		0x6d, GSP_END,
-
-	0,	KC_COMMA,	0x2c, GSP_END,
-	0,	KC_PERIOD,	0x2e, GSP_END,
-	0,	KC_SLASH,	0x2f, GSP_END,
-
-	/* Shifted */
-
-	KM_SHIFT,	KC_BACKTICK,	0x7e, GSP_END,
-
-	KM_SHIFT,	KC_1,		0x21, GSP_END,
-	KM_SHIFT,	KC_2,		0x40, GSP_END,
-	KM_SHIFT,	KC_3,		0x23, GSP_END,
-	KM_SHIFT,	KC_4,		0x24, GSP_END,
-	KM_SHIFT,	KC_5,		0x25, GSP_END,
-	KM_SHIFT,	KC_6,		0x5e, GSP_END,
-	KM_SHIFT,	KC_7,		0x26, GSP_END,
-	KM_SHIFT,	KC_8,		0x2a, GSP_END,
-	KM_SHIFT,	KC_9,		0x28, GSP_END,
-	KM_SHIFT,	KC_0,		0x29, GSP_END,
-
-	KM_SHIFT,	KC_MINUS,	0x5f, GSP_END,
-	KM_SHIFT,	KC_EQUALS,	0x2b, GSP_END,
-
-	KM_SHIFT,	KC_Q,		0x51, GSP_END,
-	KM_SHIFT,	KC_W,		0x57, GSP_END,
-	KM_SHIFT,	KC_E,		0x45, GSP_END,
-	KM_SHIFT,	KC_R,		0x52, GSP_END,
-	KM_SHIFT,	KC_T,		0x54, GSP_END,
-	KM_SHIFT,	KC_Y,		0x59, GSP_END,
-	KM_SHIFT,	KC_U,		0x55, GSP_END,
-	KM_SHIFT,	KC_I,		0x49, GSP_END,
-	KM_SHIFT,	KC_O,		0x4f, GSP_END,
-	KM_SHIFT,	KC_P,		0x50, GSP_END,
-
-	KM_SHIFT,	KC_LBRACKET,	0x7b, GSP_END,
-	KM_SHIFT,	KC_RBRACKET,	0x7d, GSP_END,
-
-	KM_SHIFT,	KC_A,		0x41, GSP_END,
-	KM_SHIFT,	KC_S,		0x53, GSP_END,
-	KM_SHIFT,	KC_D,		0x44, GSP_END,
-	KM_SHIFT,	KC_F,		0x46, GSP_END,
-	KM_SHIFT,	KC_G,		0x47, GSP_END,
-	KM_SHIFT,	KC_H,		0x48, GSP_END,
-	KM_SHIFT,	KC_J,		0x4a, GSP_END,
-	KM_SHIFT,	KC_K,		0x4b, GSP_END,
-	KM_SHIFT,	KC_L,		0x4c, GSP_END,
-
-	KM_SHIFT,	KC_SEMICOLON,	0x3a, GSP_END,
-	KM_SHIFT,	KC_QUOTE,	0x22, GSP_END,
-	KM_SHIFT,	KC_BACKSLASH,	0x7c, GSP_END,
-
-	KM_SHIFT,	KC_Z,		0x5a, GSP_END,
-	KM_SHIFT,	KC_X,		0x58, GSP_END,
-	KM_SHIFT,	KC_C,		0x43, GSP_END,
-	KM_SHIFT,	KC_V,		0x56, GSP_END,
-	KM_SHIFT,	KC_B,		0x42, GSP_END,
-	KM_SHIFT,	KC_N,		0x4e, GSP_END,
-	KM_SHIFT,	KC_M,		0x4d, GSP_END,
-
-	KM_SHIFT,	KC_COMMA,	0x3c, GSP_END,
-	KM_SHIFT,	KC_PERIOD,	0x3e, GSP_END,
-	KM_SHIFT,	KC_SLASH,	0x3f, GSP_END,
-
-	/* ... */
-
-	0,	KC_SPACE,	0x20, GSP_END,
-	0,	KC_ENTER,	0x0a, GSP_END,
-	0,	KC_ENTER,	0x0d, GSP_END,
-
-	0,	KC_ESCAPE,	0x1b, 0x1b, GSP_END,
-
-	0,	KC_F1,		0x1b, 0x4f, 0x50, GSP_END,
-	0,	KC_F2,		0x1b, 0x4f, 0x51, GSP_END,
-	0,	KC_F3,		0x1b, 0x4f, 0x52, GSP_END,
-	0,	KC_F4,		0x1b, 0x4f, 0x53, GSP_END,
-	0,	KC_F5,		0x1b, 0x5b, 0x31, 0x35, 0x7e, GSP_END,
-	0,	KC_F6,		0x1b, 0x5b, 0x31, 0x37, 0x7e, GSP_END,
-	0,	KC_F7,		0x1b, 0x5b, 0x31, 0x38, 0x7e, GSP_END,
-	0,	KC_F8,		0x1b, 0x5b, 0x31, 0x39, 0x7e, GSP_END,
-	0,	KC_F9,		0x1b, 0x5b, 0x32, 0x30, 0x7e, GSP_END,
-	0,	KC_F10,		0x1b, 0x5b, 0x32, 0x31, 0x7e, GSP_END,
-	0,	KC_F11,		0x1b, 0x5b, 0x32, 0x33, 0x7e, GSP_END,
-	0,	KC_F12,		0x1b, 0x5b, 0x32, 0x34, 0x7e, GSP_END,
-
-	0,	KC_INSERT,	0x1b, 0x5b, 0x32, 0x7e, GSP_END,
-	0,	KC_HOME,	0x1b, 0x5b, 0x48, GSP_END,
-	0,	KC_PAGE_UP,	0x1b, 0x5b, 0x35, 0x7e, GSP_END,
-	0,	KC_DELETE,	0x1b, 0x5b, 0x33, 0x7e, GSP_END,
-	0,	KC_END,		0x1b, 0x5b, 0x46, GSP_END,
-	0,	KC_PAGE_DOWN,	0x1b, 0x5b, 0x36, 0x7e, GSP_END,
-
-	0,	KC_UP,		0x1b, 0x5b, 0x41, GSP_END,
-	0,	KC_LEFT,	0x1b, 0x5b, 0x44, GSP_END,
-	0,	KC_DOWN,	0x1b, 0x5b, 0x42, GSP_END,
-	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
-
-	0,	0
-};
-
-int kbd_ctl_init(void)
-{
-	ds = 0;
-
-	gsp_init(&sp);
-	return gsp_insert_defs(&sp, seq_defs);
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	unsigned mods, key;
-
-	ds = gsp_step(&sp, ds, scancode, &mods, &key);
-	if (key != 0) {
-		stroke_sim(mods, key);
-	}
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/ctl/sun.c
===================================================================
--- uspace/srv/hid/kbd/ctl/sun.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,214 +1,0 @@
-/*
- * Copyright (c) 2006 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 kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief	Sun keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-
-#define KBD_KEY_RELEASE		0x80
-#define KBD_ALL_KEYS_UP		0x7f
-
-static int scanmap_simple[];
-
-int kbd_ctl_init(void)
-{
-	return 0;
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	console_ev_type_t type;
-	unsigned int key;
-
-	if (scancode < 0 || scancode >= 0x100)
-		return;
-
-	if (scancode == KBD_ALL_KEYS_UP)
-		return;
-
-	if (scancode & KBD_KEY_RELEASE) {
-		scancode &= ~KBD_KEY_RELEASE;
-		type = KEY_RELEASE;
-	} else {
-		type = KEY_PRESS;
-	}
-
-	key = scanmap_simple[scancode];
-	if (key != 0)
-		kbd_push_ev(type, key);
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-/** Primary meaning of scancodes. */
-static int scanmap_simple[] = {
-	[0x00] = 0,
-	[0x01] = 0,
-	[0x02] = 0,
-	[0x03] = 0,
-	[0x04] = 0,
-	[0x05] = KC_F1,
-	[0x06] = KC_F2,
-	[0x07] = KC_F10,
-	[0x08] = KC_F3,
-	[0x09] = KC_F11,
-	[0x0a] = KC_F4,
-	[0x0b] = KC_F12,
-	[0x0c] = KC_F5,
-	[0x0d] = KC_RALT,
-	[0x0e] = KC_F6,
-	[0x0f] = 0,
-	[0x10] = KC_F7,
-	[0x11] = KC_F8,
-	[0x12] = KC_F9,
-	[0x13] = KC_LALT,
-	[0x14] = KC_UP,
-	[0x15] = KC_PAUSE,
-	[0x16] = 0,
-	[0x17] = KC_SCROLL_LOCK,
-	[0x18] = KC_LEFT,
-	[0x19] = 0,
-	[0x1a] = 0,
-	[0x1b] = KC_DOWN,
-	[0x1c] = KC_RIGHT,
-	[0x1d] = KC_ESCAPE,
-	[0x1e] = KC_1,
-	[0x1f] = KC_2,
-	[0x20] = KC_3,
-	[0x21] = KC_4,
-	[0x22] = KC_5,
-	[0x23] = KC_6,
-	[0x24] = KC_7,
-	[0x25] = KC_8,
-	[0x26] = KC_9,
-	[0x27] = KC_0,
-	[0x28] = KC_MINUS,
-	[0x29] = KC_EQUALS,
-	[0x2a] = KC_BACKTICK,
-	[0x2b] = KC_BACKSPACE,
-	[0x2c] = KC_INSERT,
-	[0x2d] = 0,
-	[0x2e] = KC_NSLASH,
-	[0x2f] = KC_NTIMES,
-	[0x30] = 0,
-	[0x31] = 0,
-	[0x32] = KC_NPERIOD,
-	[0x33] = 0,
-	[0x34] = KC_HOME,
-	[0x35] = KC_TAB,
-	[0x36] = KC_Q,
-	[0x37] = KC_W,
-	[0x38] = KC_E,
-	[0x39] = KC_R,
-	[0x3a] = KC_T,
-	[0x3b] = KC_Y,
-	[0x3c] = KC_U,
-	[0x3d] = KC_I,
-	[0x3e] = KC_O,
-	[0x3f] = KC_P,
-	[0x40] = KC_LBRACKET,
-	[0x41] = KC_RBRACKET,
-	[0x42] = KC_DELETE,
-	[0x43] = 0,
-	[0x44] = KC_N7,
-	[0x45] = KC_N8,
-	[0x46] = KC_N9,
-	[0x47] = KC_NMINUS,
-	[0x48] = 0,
-	[0x49] = 0,
-	[0x4a] = KC_END,
-	[0x4b] = 0,
-	[0x4c] = KC_LCTRL,
-	[0x4d] = KC_A,
-	[0x4e] = KC_S,
-	[0x4f] = KC_D,
-	[0x50] = KC_F,
-	[0x51] = KC_G,
-	[0x52] = KC_H,
-	[0x53] = KC_J,
-	[0x54] = KC_K,
-	[0x55] = KC_L,
-	[0x56] = KC_SEMICOLON,
-	[0x57] = KC_QUOTE,
-	[0x58] = KC_BACKSLASH,
-	[0x59] = KC_ENTER,
-	[0x5a] = KC_NENTER,
-	[0x5b] = KC_N4,
-	[0x5c] = KC_N5,
-	[0x5d] = KC_N6,
-	[0x5e] = KC_N0,
-	[0x5f] = 0,
-	[0x60] = KC_PAGE_UP,
-	[0x61] = 0,
-	[0x62] = KC_NUM_LOCK,
-	[0x63] = KC_LSHIFT,
-	[0x64] = KC_Z,
-	[0x65] = KC_X,
-	[0x66] = KC_C,
-	[0x67] = KC_V,
-	[0x68] = KC_B,
-	[0x69] = KC_N,
-	[0x6a] = KC_M,
-	[0x6b] = KC_COMMA,
-	[0x6c] = KC_PERIOD,
-	[0x6d] = KC_SLASH,
-	[0x6e] = KC_RSHIFT,
-	[0x6f] = 0,
-	[0x70] = KC_N1,
-	[0x71] = KC_N2,
-	[0x72] = KC_N3,
-	[0x73] = 0,
-	[0x74] = 0,
-	[0x75] = 0,
-	[0x76] = 0,
-	[0x77] = KC_CAPS_LOCK,
-	[0x78] = 0,
-	[0x79] = KC_SPACE,
-	[0x7a] = 0,
-	[0x7b] = KC_PAGE_DOWN,
-	[0x7c] = 0,
-	[0x7d] = KC_NPLUS,
-	[0x7e] = 0,
-	[0x7f] = 0
-};
-
-/** @}
- */
Index: pace/srv/hid/kbd/genarch/gsp.c
===================================================================
--- uspace/srv/hid/kbd/genarch/gsp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,289 +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 kbdgen generic
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- * @brief	Generic scancode parser.
- *
- * The scancode parser is a simple finite state machine. It is described
- * using sequences of input symbols (scancodes) and the corresponding output
- * value (mods, key pair). When the parser recognizes a sequence,
- * it outputs the value and restarts. If a transition is undefined,
- * the parser restarts, too.
- *
- * Apart from precise values, GSP_DEFAULT allows to catch general cases.
- * I.e. if we knew that after 0x1b 0x4f there always follow two more
- * scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END)
- * with null output. This will force the parser to read the entire sequence,
- * not leaving garbage on the input if it does not recognize the specific
- * sequence.
- */
-
-#include <gsp.h>
-#include <adt/hash_table.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define TRANS_TABLE_CHAINS 256
-
-/*
- * Hash table operations for the transition function.
- */
-
-static hash_index_t trans_op_hash(unsigned long key[]);
-static int trans_op_compare(unsigned long key[], hash_count_t keys,
-    link_t *item);
-static void trans_op_remove_callback(link_t *item);
-
-static hash_table_operations_t trans_ops = {
-	.hash = trans_op_hash,
-	.compare = trans_op_compare,
-	.remove_callback = trans_op_remove_callback
-};
-
-static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
-static void trans_insert(gsp_t *p, gsp_trans_t *t);
-static gsp_trans_t *trans_new(void);
-
-/** Initialise scancode parser. */
-void gsp_init(gsp_t *p)
-{
-	p->states = 1;
-	hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);
-}
-
-/** Insert a series of definitions into the parser.
- *
- * @param p	The parser.
- * @param defs	Definition list. Each definition starts with two output values
- *		(mods, key) and continues with a sequence of input values
- *		terminated with GSP_END. The definition list is terminated
- *		with two zeroes (0, 0) for output values.
- */
-int gsp_insert_defs(gsp_t *p, const int *defs)
-{
-	unsigned mods, key;
-	const int *dp;
-	int rc;
-
-	dp = defs;
-
-	while (1) {
-		/* Read the output values. */
-		mods = *dp++;
-		key = *dp++;
-		if (key == 0) break;
-
-		/* Insert one sequence. */		
-		rc = gsp_insert_seq(p, dp, mods, key);
-		if (rc != 0)
-			return rc;
-
-		/* Skip to the next definition. */
-		while (*dp != GSP_END)
-			++dp;
-		++dp;
-	}
-
-	return 0;
-}
-
-/** Insert one sequence into the parser.
- *
- * @param p	The parser.
- * @param seq	Sequence of input values terminated with GSP_END.
- * @param mods	Corresponsing output value.
- * @param key	Corresponsing output value.
- */
-int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
-{
-	int state;
-	gsp_trans_t *t;
-
-	state = 0;
-	t = NULL;
-
-	/* Input sequence must be non-empty. */
-	if (*seq == GSP_END)
-		return -1;
-
-	while (*(seq + 1) != GSP_END) {
-		t = trans_lookup(p, state, *seq);
-		if (t == NULL) {
-			/* Create new state. */
-			t = trans_new();
-			t->old_state = state;
-			t->input = *seq;
-			t->new_state = p->states++;
-
-			t->out_mods = 0;
-			t->out_key = 0;
-
-			trans_insert(p, t);
-		}
-		state = t->new_state;
-		++seq;
-	}
-
-	/* Process the last transition. */
-	t = trans_lookup(p, state, *seq);
-	if (t != NULL) {
-		exit(1);
-		return -1;	/* Conflicting definition. */
-	}
-
-	t = trans_new();
-	t->old_state = state;
-	t->input = *seq;
-	t->new_state = 0;
-
-	t->out_mods = mods;
-	t->out_key = key;
-
-	trans_insert(p, t);
-
-	return 0;
-}
-
-/** Compute one parser step.
- *
- * Computes the next state and output values for a given state and input.
- * This handles everything including restarts and default branches.
- *
- * @param p		The parser.
- * @param state		Old state.
- * @param input		Input symbol (scancode).
- * @param mods		Output value (modifier).
- * @param key		Output value (key).
- * @return		New state.
- */
-int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
-{
-	gsp_trans_t *t;
-
-	t = trans_lookup(p, state, input);
-	if (t == NULL) {
-		t = trans_lookup(p, state, GSP_DEFAULT);
-	}
-
-	if (t == NULL) {
-		printf("gsp_step: not found\n");
-		*mods = 0;
-		*key = 0;
-		return 0;
-	}
-
-	*mods = t->out_mods;
-	*key = t->out_key;
-	return t->new_state;
-}
-
-/** Transition function lookup.
- *
- * Returns the value of the transition function for the given state
- * and input. Note that the transition must be specified precisely,
- * to obtain the default branch use input = GSP_DEFAULT.
- *
- * @param p		Parser.
- * @param state		Current state.
- * @param input		Input value.
- * @return		The transition or @c NULL if not defined.
- */
-static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
-{
-	link_t *item;
-	unsigned long key[2];
-
-	key[0] = state;
-	key[1] = input;
-
-	item = hash_table_find(&p->trans, key);
-	if (item == NULL) return NULL;
-
-	return hash_table_get_instance(item, gsp_trans_t, link);
-}
-
-/** Define a new transition.
- *
- * @param p	The parser.
- * @param t	Transition with all fields defined.
- */
-static void trans_insert(gsp_t *p, gsp_trans_t *t)
-{
-	unsigned long key[2];
-
-	key[0] = t->old_state;
-	key[1] = t->input;
-
-	hash_table_insert(&p->trans, key, &t->link);
-}
-
-/** Allocate transition structure. */
-static gsp_trans_t *trans_new(void)
-{
-	gsp_trans_t *t;
-
-	t = malloc(sizeof(gsp_trans_t));
-	if (t == NULL) {
-		printf("Memory allocation failed.\n");
-		exit(1);
-	}
-
-	return t;
-}
-
-/*
- * Transition function hash table operations.
- */
-
-static hash_index_t trans_op_hash(unsigned long key[])
-{
-	return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS;
-}
-
-static int trans_op_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	gsp_trans_t *t;
-
-	t = hash_table_get_instance(item, gsp_trans_t, link);
-	return ((key[0] == (unsigned long) t->old_state)
-	    && (key[1] == (unsigned long) t->input));
-}
-
-static void trans_op_remove_callback(link_t *item)
-{
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/genarch/stroke.c
===================================================================
--- uspace/srv/hid/kbd/genarch/stroke.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,85 +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 kbd
- * @{
- */
-/**
- * @file
- * @brief Stroke simulator.
- *
- * When simulating a keyboard using a serial TTY we need to convert the
- * recognized strokes (such as Shift-A) to sequences of key presses and
- * releases (such as 'press Shift, press A, release A, release Shift').
- *
- */
-
-#include <stroke.h>
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-
-/** Correspondence between modifers and the modifier keycodes. */
-static unsigned int mods_keys[][2] = {
-	{ KM_LSHIFT, KC_LSHIFT },
-	{ 0, 0 }
-};
-
-/** Simulate keystroke using sequences of key presses and releases. */
-void stroke_sim(unsigned mod, unsigned key)
-{
-	int i;
-
-	/* Simulate modifier presses. */
-	i = 0;
-	while (mods_keys[i][0] != 0) {
-		if (mod & mods_keys[i][0]) {
-			kbd_push_ev(KEY_PRESS, mods_keys[i][1]);
-		}
-		++i;
-	}
-
-	/* Simulate key press and release. */
-	if (key != 0) {
-		kbd_push_ev(KEY_PRESS, key);
-		kbd_push_ev(KEY_RELEASE, key);
-	}
-
-	/* Simulate modifier releases. */
-	i = 0;
-	while (mods_keys[i][0] != 0) {
-		if (mod & mods_keys[i][0]) {
-			kbd_push_ev(KEY_RELEASE, mods_keys[i][1]);
-		}
-		++i;
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/kbd/generic/kbd.c
===================================================================
--- uspace/srv/hid/kbd/generic/kbd.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,264 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup kbdgen generic
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#include <ipc/services.h>
-#include <ipc/kbd.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ipc/ns.h>
-#include <async.h>
-#include <errno.h>
-#include <adt/fifo.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <devmap.h>
-
-#include <kbd.h>
-#include <kbd_port.h>
-#include <kbd_ctl.h>
-#include <layout.h>
-
-#define NAME       "kbd"
-#define NAMESPACE  "hid_in"
-
-int client_phone = -1;
-
-/** Currently active modifiers. */
-static unsigned mods = KM_NUM_LOCK;
-
-/** Currently pressed lock keys. We track these to tackle autorepeat. */
-static unsigned lock_keys;
-
-int cir_service = 0;
-int cir_phone = -1;
-
-#define NUM_LAYOUTS 3
-
-static layout_op_t *layout[NUM_LAYOUTS] = {
-	&us_qwerty_op,
-	&us_dvorak_op,
-	&cz_op
-};
-
-static int active_layout = 0;
-
-void kbd_push_scancode(int scancode)
-{
-/*	printf("scancode: 0x%x\n", scancode);*/
-	kbd_ctl_parse_scancode(scancode);
-}
-
-void kbd_push_ev(int type, unsigned int key)
-{
-	console_event_t ev;
-	unsigned mod_mask;
-
-	switch (key) {
-	case KC_LCTRL: mod_mask = KM_LCTRL; break;
-	case KC_RCTRL: mod_mask = KM_RCTRL; break;
-	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
-	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
-	case KC_LALT: mod_mask = KM_LALT; break;
-	case KC_RALT: mod_mask = KM_RALT; break;
-	default: mod_mask = 0; break;
-	}
-
-	if (mod_mask != 0) {
-		if (type == KEY_PRESS)
-			mods = mods | mod_mask;
-		else
-			mods = mods & ~mod_mask;
-	}
-
-	switch (key) {
-	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
-	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
-	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
-	default: mod_mask = 0; break;
-	}
-
-	if (mod_mask != 0) {
-		if (type == KEY_PRESS) {
-			/*
-			 * Only change lock state on transition from released
-			 * to pressed. This prevents autorepeat from messing
-			 * up the lock state.
-			 */
-			mods = mods ^ (mod_mask & ~lock_keys);
-			lock_keys = lock_keys | mod_mask;
-
-			/* Update keyboard lock indicator lights. */
-			kbd_ctl_set_ind(mods);
-		} else {
-			lock_keys = lock_keys & ~mod_mask;
-		}
-	}
-/*
-	printf("type: %d\n", type);
-	printf("mods: 0x%x\n", mods);
-	printf("keycode: %u\n", key);
-*/
-	if (type == KEY_PRESS && (mods & KM_LCTRL) &&
-		key == KC_F1) {
-		active_layout = 0;
-		layout[active_layout]->reset();
-		return;
-	}
-
-	if (type == KEY_PRESS && (mods & KM_LCTRL) &&
-		key == KC_F2) {
-		active_layout = 1;
-		layout[active_layout]->reset();
-		return;
-	}
-
-	if (type == KEY_PRESS && (mods & KM_LCTRL) &&
-		key == KC_F3) {
-		active_layout = 2;
-		layout[active_layout]->reset();
-		return;
-	}
-
-	ev.type = type;
-	ev.key = key;
-	ev.mods = mods;
-
-	ev.c = layout[active_layout]->parse_ev(&ev);
-
-	async_msg_4(client_phone, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c);
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			if (client_phone != -1) {
-				async_hangup(client_phone);
-				client_phone = -1;
-			}
-			
-			async_answer_0(callid, EOK);
-			return;
-		case IPC_M_CONNECT_TO_ME:
-			if (client_phone != -1) {
-				retval = ELIMIT;
-				break;
-			}
-			client_phone = IPC_GET_ARG5(call);
-			retval = 0;
-			break;
-		case KBD_YIELD:
-			kbd_port_yield();
-			retval = 0;
-			break;
-		case KBD_RECLAIM:
-			kbd_port_reclaim();
-			retval = 0;
-			break;
-		default:
-			retval = EINVAL;
-		}
-		async_answer_0(callid, retval);
-	}	
-}
-
-
-int main(int argc, char **argv)
-{
-	printf("%s: HelenOS Keyboard service\n", NAME);
-	
-	sysarg_t fhc;
-	sysarg_t obio;
-	
-	if ((sysinfo_get_value("kbd.cir.fhc", &fhc) == EOK) && (fhc))
-		cir_service = SERVICE_FHC;
-	else if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio))
-		cir_service = SERVICE_OBIO;
-	
-	if (cir_service) {
-		while (cir_phone < 0)
-			cir_phone = service_connect_blocking(cir_service, 0, 0);
-	}
-	
-	/* Initialize port driver. */
-	if (kbd_port_init() != 0)
-		return -1;
-
-	/* Initialize controller driver. */
-	if (kbd_ctl_init() != 0)
-		return -1;
-
-	/* Initialize (reset) layout. */
-	layout[active_layout]->reset();
-	
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
-	if (rc < 0) {
-		printf("%s: Unable to register driver (%d)\n", NAME, rc);
-		return -1;
-	}
-	
-	char kbd[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(kbd, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
-	
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(kbd, &devmap_handle) != EOK) {
-		printf("%s: Unable to register device %s\n", NAME, kbd);
-		return -1;
-	}
-
-	printf(NAME ": Accepting connections\n");
-	async_manager();
-
-	/* Not reached. */
-	return 0;
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/include/gsp.h
===================================================================
--- uspace/srv/hid/kbd/include/gsp.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,84 +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 kbdgen generic
- * @brief	Generic scancode parser.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_GSP_H_
-#define KBD_GSP_H_
-
-#include <adt/hash_table.h>
-
-enum {
-	GSP_END		= -1,	/**< Terminates a sequence. */
-	GSP_DEFAULT	= -2	/**< Wildcard, catches unhandled cases. */
-};
-
-/** Scancode parser description */
-typedef struct {
-	/** Transition table, (state, input) -> (state, output) */
-	hash_table_t trans;
-
-	/** Number of states */
-	int states;
-} gsp_t;
-
-/** Scancode parser transition. */
-typedef struct {
-	link_t link;		/**< Link to hash table in @c gsp_t */ 
-
-	/* Preconditions */
-
-	int old_state;		/**< State before transition */
-	int input;		/**< Input symbol (scancode) */
-
-	/* Effects */
-
-	int new_state;		/**< State after transition */
-
-	/* Output emitted during transition */
-
-	unsigned out_mods;	/**< Modifier to emit */
-	unsigned out_key;	/**< Keycode to emit */
-} gsp_trans_t;
-
-extern void gsp_init(gsp_t *);
-extern int gsp_insert_defs(gsp_t *, const int *);
-extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned);
-extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *);
-
-#endif
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/include/kbd.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen generic
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_KBD_H_
-#define KBD_KBD_H_
-
-extern int cir_service;
-extern int cir_phone;
-
-extern void kbd_push_scancode(int);
-extern void kbd_push_ev(int, unsigned int);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/kbd/include/kbd_ctl.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd_ctl.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,49 +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 kbdgen generic
- * @brief	HelenOS generic uspace keyboard handler.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_CTL_H_
-#define KBD_CTL_H_
-
-extern void kbd_ctl_parse_scancode(int);
-extern int kbd_ctl_init(void);
-extern void kbd_ctl_set_ind(unsigned);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: pace/srv/hid/kbd/include/kbd_port.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd_port.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(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 kbdgen generic
- * @brief	HelenOS generic uspace keyboard handler.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_PORT_H_
-#define KBD_PORT_H_
-
-#include <sys/types.h>
-
-extern int kbd_port_init(void);
-extern void kbd_port_yield(void);
-extern void kbd_port_reclaim(void);
-extern void kbd_port_write(uint8_t);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: pace/srv/hid/kbd/include/layout.h
===================================================================
--- uspace/srv/hid/kbd/include/layout.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,56 +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 kbdgen generic
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_LAYOUT_H_
-#define KBD_LAYOUT_H_
-
-#include <sys/types.h>
-#include <io/console.h>
-
-typedef struct {
-	void (*reset)(void);
-	wchar_t (*parse_ev)(console_event_t *);
-} layout_op_t;
-
-extern layout_op_t us_qwerty_op;
-extern layout_op_t us_dvorak_op;
-extern layout_op_t cz_op;
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/kbd/include/stroke.h
===================================================================
--- uspace/srv/hid/kbd/include/stroke.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,47 +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 kbdgen generic
- * @brief	Generic scancode parser.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_STROKE_H_
-#define KBD_STROKE_H_
-
-extern void stroke_sim(unsigned, unsigned);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: pace/srv/hid/kbd/include/sun.h
===================================================================
--- uspace/srv/hid/kbd/include/sun.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-/** @addtogroup kbdgen generic
- * @brief Sun keyboard virtual port driver.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_SUN_H_
-#define KBD_SUN_H_
-
-extern int ns16550_port_init(void);
-extern int z8530_port_init(void);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/hid/kbd/layout/cz.c
===================================================================
--- uspace/srv/hid/kbd/layout/cz.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,408 +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 kbd
- * @brief Czech QWERTZ layout.
- * @{
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <bool.h>
-#include <layout.h>
-
-static void layout_reset(void);
-static wchar_t layout_parse_ev(console_event_t *ev);
-
-enum m_state {
-	ms_start,
-	ms_hacek,
-	ms_carka
-};
-
-static enum m_state mstate;
-
-layout_op_t cz_op = {
-	layout_reset,
-	layout_parse_ev
-};
-
-static wchar_t map_lcase[] = {
-	[KC_Q] = 'q',
-	[KC_W] = 'w',
-	[KC_E] = 'e',
-	[KC_R] = 'r',
-	[KC_T] = 't',
-	[KC_Y] = 'z',
-	[KC_U] = 'u',
-	[KC_I] = 'i',
-	[KC_O] = 'o',
-	[KC_P] = 'p',
-
-	[KC_A] = 'a',
-	[KC_S] = 's',
-	[KC_D] = 'd',
-	[KC_F] = 'f',
-	[KC_G] = 'g',
-	[KC_H] = 'h',
-	[KC_J] = 'j',
-	[KC_K] = 'k',
-	[KC_L] = 'l',
-
-	[KC_Z] = 'y',
-	[KC_X] = 'x',
-	[KC_C] = 'c',
-	[KC_V] = 'v',
-	[KC_B] = 'b',
-	[KC_N] = 'n',
-	[KC_M] = 'm',
-};
-
-static wchar_t map_ucase[] = {
-	[KC_Q] = 'Q',
-	[KC_W] = 'W',
-	[KC_E] = 'E',
-	[KC_R] = 'R',
-	[KC_T] = 'T',
-	[KC_Y] = 'Z',
-	[KC_U] = 'U',
-	[KC_I] = 'I',
-	[KC_O] = 'O',
-	[KC_P] = 'P',
-
-	[KC_A] = 'A',
-	[KC_S] = 'S',
-	[KC_D] = 'D',
-	[KC_F] = 'F',
-	[KC_G] = 'G',
-	[KC_H] = 'H',
-	[KC_J] = 'J',
-	[KC_K] = 'K',
-	[KC_L] = 'L',
-
-	[KC_Z] = 'Y',
-	[KC_X] = 'X',
-	[KC_C] = 'C',
-	[KC_V] = 'V',
-	[KC_B] = 'B',
-	[KC_N] = 'N',
-	[KC_M] = 'M',
-};
-
-static wchar_t map_not_shifted[] = {
-	[KC_BACKTICK] = ';',
-
-	[KC_1] = '+',
-
-	[KC_MINUS] = '=',
-
-	[KC_RBRACKET] = ')',
-
-	[KC_QUOTE] = L'§',
-
-	[KC_COMMA] = ',',
-	[KC_PERIOD] = '.',
-	[KC_SLASH] = '-',
-};
-
-static wchar_t map_shifted[] = {
-	[KC_1] = '1',
-	[KC_2] = '2',
-	[KC_3] = '3',
-	[KC_4] = '4',
-	[KC_5] = '5',
-	[KC_6] = '6',
-	[KC_7] = '7',
-	[KC_8] = '8',
-	[KC_9] = '9',
-	[KC_0] = '0',
-
-	[KC_MINUS] = '%',
-
-	[KC_LBRACKET] = '/',
-	[KC_RBRACKET] = '(',
-
-	[KC_SEMICOLON] = '"',
-	[KC_QUOTE] = '!',
-	[KC_BACKSLASH] = '\'',
-
-	[KC_COMMA] = '?',
-	[KC_PERIOD] = ':',
-	[KC_SLASH] = '_',
-};
-
-static wchar_t map_ns_nocaps[] = {
-	[KC_2] = L'ě',
-	[KC_3] = L'š',
-	[KC_4] = L'č',
-	[KC_5] = L'ř',
-	[KC_6] = L'ž',
-	[KC_7] = L'ý',
-	[KC_8] = L'á',
-	[KC_9] = L'í',
-	[KC_0] = L'é',
-
-	[KC_LBRACKET] = L'ú',
-	[KC_SEMICOLON] = L'ů'
-};
-
-static wchar_t map_ns_caps[] = {
-	[KC_2] = L'Ě',
-	[KC_3] = L'Š',
-	[KC_4] = L'Č',
-	[KC_5] = L'Ř',
-	[KC_6] = L'Ž',
-	[KC_7] = L'Ý',
-	[KC_8] = L'Á',
-	[KC_9] = L'Í',
-	[KC_0] = L'É',
-
-	[KC_LBRACKET] = L'Ú',
-	[KC_SEMICOLON] = L'Ů'
-};
-
-static wchar_t map_neutral[] = {
-	[KC_BACKSPACE] = '\b',
-	[KC_TAB] = '\t',
-	[KC_ENTER] = '\n',
-	[KC_SPACE] = ' ',
-
-	[KC_NSLASH] = '/',
-	[KC_NTIMES] = '*',
-	[KC_NMINUS] = '-',
-	[KC_NPLUS] = '+',
-	[KC_NENTER] = '\n'
-};
-
-static wchar_t map_numeric[] = {
-	[KC_N7] = '7',
-	[KC_N8] = '8',
-	[KC_N9] = '9',
-	[KC_N4] = '4',
-	[KC_N5] = '5',
-	[KC_N6] = '6',
-	[KC_N1] = '1',
-	[KC_N2] = '2',
-	[KC_N3] = '3',
-
-	[KC_N0] = '0',
-	[KC_NPERIOD] = '.'
-};
-
-static wchar_t map_hacek_lcase[] = {
-	[KC_E] = L'ě',
-	[KC_R] = L'ř',
-	[KC_T] = L'ť',
-	[KC_Y] = L'ž',
-	[KC_U] = L'ů',
-
-	[KC_S] = L'š',
-	[KC_D] = L'ď',
-
-	[KC_C] = L'č',
-	[KC_N] = L'ň'
-};
-
-static wchar_t map_hacek_ucase[] = {
-	[KC_E] = L'Ě',
-	[KC_R] = L'Ř',
-	[KC_T] = L'Ť',
-	[KC_Y] = L'Ž',
-	[KC_U] = L'Ů',
-
-	[KC_S] = L'Š',
-	[KC_D] = L'Ď',
-
-	[KC_C] = L'Č',
-	[KC_N] = L'Ň'
-};
-
-static wchar_t map_carka_lcase[] = {
-	[KC_E] = L'é',
-	[KC_U] = L'ú',
-	[KC_I] = L'í',
-	[KC_O] = L'ó',
-
-	[KC_A] = L'á',
-
-	[KC_Z] = L'ý',
-};
-
-static wchar_t map_carka_ucase[] = {
-	[KC_E] = L'É',
-	[KC_U] = L'Ú',
-	[KC_I] = L'Í',
-	[KC_O] = L'Ó',
-
-	[KC_A] = L'Á',
-
-	[KC_Z] = L'Ý',
-};
-
-static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
-{
-	if (key >= map_length)
-		return 0;
-	return map[key];
-}
-
-static wchar_t parse_ms_hacek(console_event_t *ev)
-{
-	wchar_t c;
-
-	mstate = ms_start;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t));
-
-	return c;
-}
-
-static wchar_t parse_ms_carka(console_event_t *ev)
-{
-	wchar_t c;
-
-	mstate = ms_start;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t));
-
-	return c;
-}
-
-static wchar_t parse_ms_start(console_event_t *ev)
-{
-	wchar_t c;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	if (ev->key == KC_EQUALS) {
-		if ((ev->mods & KM_SHIFT) != 0)
-			mstate = ms_hacek;
-		else
-			mstate = ms_carka;
-
-		return 0;
-	}
-
-	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_SHIFT) == 0) {
-		if ((ev->mods & KM_CAPS_LOCK) != 0)
-			c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t));
-		else
-			c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t));
-
-		if (c != 0)
-			return c;
-	}	
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_SHIFT) != 0)
-		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_NUM_LOCK) != 0)
-		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
-	else
-		c = 0;
-
-	return c;
-}
-
-static bool key_is_mod(unsigned key)
-{
-	switch (key) {
-	case KC_LSHIFT:
-	case KC_RSHIFT:
-	case KC_LALT:
-	case KC_RALT:
-	case KC_LCTRL:
-	case KC_RCTRL:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static void layout_reset(void)
-{
-	mstate = ms_start;
-}
-
-static wchar_t layout_parse_ev(console_event_t *ev)
-{
-	if (ev->type != KEY_PRESS)
-		return 0;
-	
-	if (key_is_mod(ev->key))
-		return 0;
-	
-	switch (mstate) {
-	case ms_start:
-		return parse_ms_start(ev);
-	case ms_hacek:
-		return parse_ms_hacek(ev);
-	case ms_carka:
-		return parse_ms_carka(ev);
-	}
-	
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/kbd/layout/us_dvorak.c
===================================================================
--- uspace/srv/hid/kbd/layout/us_dvorak.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,250 +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 kbd
- * @brief US Dvorak Simplified Keyboard layout.
- * @{
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <layout.h>
-
-static void layout_reset(void);
-static wchar_t layout_parse_ev(console_event_t *ev);
-
-layout_op_t us_dvorak_op = {
-	layout_reset,
-	layout_parse_ev
-};
-
-static wchar_t map_lcase[] = {
-	[KC_R] = 'p',
-	[KC_T] = 'y',
-	[KC_Y] = 'f',
-	[KC_U] = 'g',
-	[KC_I] = 'c',
-	[KC_O] = 'r',
-	[KC_P] = 'l',
-
-	[KC_A] = 'a',
-	[KC_S] = 'o',
-	[KC_D] = 'e',
-	[KC_F] = 'u',
-	[KC_G] = 'i',
-	[KC_H] = 'd',
-	[KC_J] = 'h',
-	[KC_K] = 't',
-	[KC_L] = 'n',
-
-	[KC_SEMICOLON] = 's',
-
-	[KC_X] = 'q',
-	[KC_C] = 'j',
-	[KC_V] = 'k',
-	[KC_B] = 'x',
-	[KC_N] = 'b',
-	[KC_M] = 'm',
-
-	[KC_COMMA] = 'w',
-	[KC_PERIOD] = 'v',
-	[KC_SLASH] = 'z',
-};
-
-static wchar_t map_ucase[] = {
-	[KC_R] = 'P',
-	[KC_T] = 'Y',
-	[KC_Y] = 'F',
-	[KC_U] = 'G',
-	[KC_I] = 'C',
-	[KC_O] = 'R',
-	[KC_P] = 'L',
-
-	[KC_A] = 'A',
-	[KC_S] = 'O',
-	[KC_D] = 'E',
-	[KC_F] = 'U',
-	[KC_G] = 'I',
-	[KC_H] = 'D',
-	[KC_J] = 'H',
-	[KC_K] = 'T',
-	[KC_L] = 'N',
-
-	[KC_SEMICOLON] = 'S',
-
-	[KC_X] = 'Q',
-	[KC_C] = 'J',
-	[KC_V] = 'K',
-	[KC_B] = 'X',
-	[KC_N] = 'B',
-	[KC_M] = 'M',
-
-	[KC_COMMA] = 'W',
-	[KC_PERIOD] = 'V',
-	[KC_SLASH] = 'Z',
-};
-
-static wchar_t map_not_shifted[] = {
-	[KC_BACKTICK] = '`',
-
-	[KC_1] = '1',
-	[KC_2] = '2',
-	[KC_3] = '3',
-	[KC_4] = '4',
-	[KC_5] = '5',
-	[KC_6] = '6',
-	[KC_7] = '7',
-	[KC_8] = '8',
-	[KC_9] = '9',
-	[KC_0] = '0',
-
-	[KC_MINUS] = '[',
-	[KC_EQUALS] = ']',
-
-	[KC_Q] = '\'',
-	[KC_W] = ',',
-	[KC_E] = '.',
-
-	[KC_LBRACKET] = '/',
-	[KC_RBRACKET] = '=',
-
-	[KC_QUOTE] = '-',
-	[KC_BACKSLASH] = '\\',
-
-	[KC_Z] = ';',
-};
-
-static wchar_t map_shifted[] = {
-	[KC_BACKTICK] = '~',
-
-	[KC_1] = '!',
-	[KC_2] = '@',
-	[KC_3] = '#',
-	[KC_4] = '$',
-	[KC_5] = '%',
-	[KC_6] = '^',
-	[KC_7] = '&',
-	[KC_8] = '*',
-	[KC_9] = '(',
-	[KC_0] = ')',
-
-	[KC_MINUS] = '{',
-	[KC_EQUALS] = '}',
-
-	[KC_Q] = '"',
-	[KC_W] = '<',
-	[KC_E] = '>',
-
-	[KC_LBRACKET] = '?',
-	[KC_RBRACKET] = '+',
-
-	[KC_QUOTE] = '_',
-	[KC_BACKSLASH] = '|',
-
-	[KC_Z] = ':',
-};
-
-static wchar_t map_neutral[] = {
-	[KC_BACKSPACE] = '\b',
-	[KC_TAB] = '\t',
-	[KC_ENTER] = '\n',
-	[KC_SPACE] = ' ',
-
-	[KC_NSLASH] = '/',
-	[KC_NTIMES] = '*',
-	[KC_NMINUS] = '-',
-	[KC_NPLUS] = '+',
-	[KC_NENTER] = '\n'
-};
-
-static wchar_t map_numeric[] = {
-	[KC_N7] = '7',
-	[KC_N8] = '8',
-	[KC_N9] = '9',
-	[KC_N4] = '4',
-	[KC_N5] = '5',
-	[KC_N6] = '6',
-	[KC_N1] = '1',
-	[KC_N2] = '2',
-	[KC_N3] = '3',
-
-	[KC_N0] = '0',
-	[KC_NPERIOD] = '.'
-};
-
-static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
-{
-	if (key >= map_length)
-		return 0;
-	return map[key];
-}
-
-static void layout_reset(void)
-{
-}
-
-static wchar_t layout_parse_ev(console_event_t *ev)
-{
-	wchar_t c;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
-	if (c != 0)
-		return c;
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_SHIFT) != 0)
-		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_NUM_LOCK) != 0)
-		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
-	else
-		c = 0;
-
-	return c;
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/kbd/layout/us_qwerty.c
===================================================================
--- uspace/srv/hid/kbd/layout/us_qwerty.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,244 +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 kbd
- * @brief	US QWERTY layout.
- * @{
- */ 
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <layout.h>
-
-static void layout_reset(void);
-static wchar_t layout_parse_ev(console_event_t *ev);
-
-layout_op_t us_qwerty_op = {
-	layout_reset,
-	layout_parse_ev
-};
-
-static wchar_t map_lcase[] = {
-	[KC_Q] = 'q',
-	[KC_W] = 'w',
-	[KC_E] = 'e',
-	[KC_R] = 'r',
-	[KC_T] = 't',
-	[KC_Y] = 'y',
-	[KC_U] = 'u',
-	[KC_I] = 'i',
-	[KC_O] = 'o',
-	[KC_P] = 'p',
-
-	[KC_A] = 'a',
-	[KC_S] = 's',
-	[KC_D] = 'd',
-	[KC_F] = 'f',
-	[KC_G] = 'g',
-	[KC_H] = 'h',
-	[KC_J] = 'j',
-	[KC_K] = 'k',
-	[KC_L] = 'l',
-
-	[KC_Z] = 'z',
-	[KC_X] = 'x',
-	[KC_C] = 'c',
-	[KC_V] = 'v',
-	[KC_B] = 'b',
-	[KC_N] = 'n',
-	[KC_M] = 'm',
-};
-
-static wchar_t map_ucase[] = {
-	[KC_Q] = 'Q',
-	[KC_W] = 'W',
-	[KC_E] = 'E',
-	[KC_R] = 'R',
-	[KC_T] = 'T',
-	[KC_Y] = 'Y',
-	[KC_U] = 'U',
-	[KC_I] = 'I',
-	[KC_O] = 'O',
-	[KC_P] = 'P',
-
-	[KC_A] = 'A',
-	[KC_S] = 'S',
-	[KC_D] = 'D',
-	[KC_F] = 'F',
-	[KC_G] = 'G',
-	[KC_H] = 'H',
-	[KC_J] = 'J',
-	[KC_K] = 'K',
-	[KC_L] = 'L',
-
-	[KC_Z] = 'Z',
-	[KC_X] = 'X',
-	[KC_C] = 'C',
-	[KC_V] = 'V',
-	[KC_B] = 'B',
-	[KC_N] = 'N',
-	[KC_M] = 'M',
-};
-
-static wchar_t map_not_shifted[] = {
-	[KC_BACKTICK] = '`',
-
-	[KC_1] = '1',
-	[KC_2] = '2',
-	[KC_3] = '3',
-	[KC_4] = '4',
-	[KC_5] = '5',
-	[KC_6] = '6',
-	[KC_7] = '7',
-	[KC_8] = '8',
-	[KC_9] = '9',
-	[KC_0] = '0',
-
-	[KC_MINUS] = '-',
-	[KC_EQUALS] = '=',
-
-	[KC_LBRACKET] = '[',
-	[KC_RBRACKET] = ']',
-
-	[KC_SEMICOLON] = ';',
-	[KC_QUOTE] = '\'',
-	[KC_BACKSLASH] = '\\',
-
-	[KC_COMMA] = ',',
-	[KC_PERIOD] = '.',
-	[KC_SLASH] = '/',
-};
-
-static wchar_t map_shifted[] = {
-	[KC_BACKTICK] = '~',
-
-	[KC_1] = '!',
-	[KC_2] = '@',
-	[KC_3] = '#',
-	[KC_4] = '$',
-	[KC_5] = '%',
-	[KC_6] = '^',
-	[KC_7] = '&',
-	[KC_8] = '*',
-	[KC_9] = '(',
-	[KC_0] = ')',
-
-	[KC_MINUS] = '_',
-	[KC_EQUALS] = '+',
-
-	[KC_LBRACKET] = '{',
-	[KC_RBRACKET] = '}',
-
-	[KC_SEMICOLON] = ':',
-	[KC_QUOTE] = '"',
-	[KC_BACKSLASH] = '|',
-
-	[KC_COMMA] = '<',
-	[KC_PERIOD] = '>',
-	[KC_SLASH] = '?',
-};
-
-static wchar_t map_neutral[] = {
-	[KC_BACKSPACE] = '\b',
-	[KC_TAB] = '\t',
-	[KC_ENTER] = '\n',
-	[KC_SPACE] = ' ',
-
-	[KC_NSLASH] = '/',
-	[KC_NTIMES] = '*',
-	[KC_NMINUS] = '-',
-	[KC_NPLUS] = '+',
-	[KC_NENTER] = '\n'
-};
-
-static wchar_t map_numeric[] = {
-	[KC_N7] = '7',
-	[KC_N8] = '8',
-	[KC_N9] = '9',
-	[KC_N4] = '4',
-	[KC_N5] = '5',
-	[KC_N6] = '6',
-	[KC_N1] = '1',
-	[KC_N2] = '2',
-	[KC_N3] = '3',
-
-	[KC_N0] = '0',
-	[KC_NPERIOD] = '.'
-};
-
-static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
-{
-	if (key >= map_length)
-		return 0;
-	return map[key];
-}
-
-static void layout_reset(void)
-{
-}
-
-static wchar_t layout_parse_ev(console_event_t *ev)
-{
-	wchar_t c;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
-	if (c != 0)
-		return c;
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_SHIFT) != 0)
-		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_NUM_LOCK) != 0)
-		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
-	else
-		c = 0;
-
-	return c;
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/port/adb.c
===================================================================
--- uspace/srv/hid/kbd/port/adb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,132 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup kbd
- * @{
- */ 
-/** @file
- * @brief ADB keyboard port driver.
- */
-
-#include <ipc/adb.h>
-#include <async.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <vfs/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall);
-static void adb_kbd_reg0_data(uint16_t data);
-
-static int dev_phone;
-
-#define NAME "kbd"
-
-int kbd_port_init(void)
-{
-	const char *input = "/dev/adb/kbd";
-	int input_fd;
-
-	printf(NAME ": open %s\n", input);
-
-	input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s (%d)\n", input, input_fd);
-		return false;
-	}
-
-	dev_phone = fd_phone(input_fd);
-	if (dev_phone < 0) {
-		printf(NAME ": Failed to connect to device\n");
-		return false;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(dev_phone, 0, 0, 0, kbd_port_events) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return false;
-	}
-
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	/*async_msg_1(dev_phone, CHAR_WRITE_BYTE, data);*/
-}
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case ADB_REG_NOTIF:
-			adb_kbd_reg0_data(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-static void adb_kbd_reg0_data(uint16_t data)
-{
-	uint8_t b0, b1;
-
-	b0 = (data >> 8) & 0xff;
-	b1 = data & 0xff;
-
-	if (b0 != 0xff)
-		kbd_push_scancode(b0);
-	if (b1 != 0xff)
-		kbd_push_scancode(b1);
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/kbd/port/chardev.c
===================================================================
--- uspace/srv/hid/kbd/port/chardev.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,140 +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 kbd_port
- * @ingroup kbd
- * @{
- */ 
-/** @file
- * @brief Chardev keyboard port driver.
- */
-
-#include <ipc/char.h>
-#include <async.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <vfs/vfs.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall);
-
-static int dev_phone;
-
-#define NAME "kbd"
-
-/** List of devices to try connecting to. */
-static const char *in_devs[] = {
-	"/dev/char/ps2a",
-	"/dev/char/s3c24ser"
-};
-
-static const int num_devs = sizeof(in_devs) / sizeof(in_devs[0]);
-
-int kbd_port_init(void)
-{
-	int input_fd;
-	int i;
-
-	input_fd = -1;
-	for (i = 0; i < num_devs; i++) {
-		struct stat s;
-
-		if (stat(in_devs[i], &s) == EOK)
-			break;
-	}
-
-	if (i >= num_devs) {
-		printf(NAME ": Could not find any suitable input device.\n");
-		return -1;
-	}
-
-	input_fd = open(in_devs[i], O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": failed opening device %s (%d).\n", in_devs[i],
-		    input_fd);
-		return -1;
-	}
-
-	dev_phone = fd_phone(input_fd);
-	if (dev_phone < 0) {
-		printf(NAME ": Failed connecting to device\n");
-		return -1;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(dev_phone, 0, 0, 0, kbd_port_events) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	async_msg_1(dev_phone, CHAR_WRITE_BYTE, data);
-}
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case CHAR_NOTIF_BYTE:
-			kbd_push_scancode(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/port/dummy.c
===================================================================
--- uspace/srv/hid/kbd/port/dummy.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,59 +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 kbd_port
- * @brief	Dummy keyboard port driver.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#include <kbd_port.h>
-#include <kbd.h>
-
-int kbd_port_init(void)
-{
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: pace/srv/hid/kbd/port/gxemul.c
===================================================================
--- uspace/srv/hid/kbd/port/gxemul.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,107 +1,0 @@
-/*
- * Copyright (c) 2007 Michal Kebrt
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @{
- * @ingroup  kbd
- */ 
-/** @file
- * @brief	GXEmul keyboard port driver.
- */
-
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <ddi.h>
-#include <errno.h>
-
-static irq_cmd_t gxemul_cmds[] = {
-	{ 
-		.cmd = CMD_PIO_READ_8, 
-		.addr = (void *) 0, 	/* will be patched in run-time */
-		.dstarg = 2,
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-static irq_code_t gxemul_kbd = {
-	sizeof(gxemul_cmds) / sizeof(irq_cmd_t),
-	gxemul_cmds
-};
-
-static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-/** Initializes keyboard handler. */
-int kbd_port_init(void)
-{
-	sysarg_t addr;
-	if (sysinfo_get_value("kbd.address.virtual", &addr) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	async_set_interrupt_received(gxemul_irq_handler);
-	gxemul_cmds[0].addr = (void *) addr;
-	register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** Process data sent when a key is pressed.
- *  
- *  @param keybuffer Buffer of pressed keys.
- *  @param call      IPC call.
- *
- *  @return Always 1.
- */
-static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-
-	kbd_push_scancode(scan_code);
-}
-
-/** @}
- */
Index: pace/srv/hid/kbd/port/msim.c
===================================================================
--- uspace/srv/hid/kbd/port/msim.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,100 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Msim keyboard port driver.
- */
-
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <ddi.h>
-#include <errno.h>
-
-irq_cmd_t msim_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-	
-};
-
-irq_code_t msim_kbd = {
-	sizeof(msim_cmds) / sizeof(irq_cmd_t),
-	msim_cmds
-};
-
-static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-int kbd_port_init(void)
-{
-	sysarg_t vaddr;
-	if (sysinfo_get_value("kbd.address.virtual", &vaddr) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	msim_cmds[0].addr = (void *) vaddr;
-	async_set_interrupt_received(msim_irq_handler);
-	register_irq(inr, device_assign_devno(), 0, &msim_kbd);
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
-}
-
-/** @}
-*/
Index: pace/srv/hid/kbd/port/niagara.c
===================================================================
--- uspace/srv/hid/kbd/port/niagara.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,152 +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.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- * @brief	Niagara console keyboard port driver.
- */
-
-#include <as.h>
-#include <ddi.h>
-#include <async.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <thread.h>
-#include <bool.h>
-#include <errno.h>
-
-#define POLL_INTERVAL  10000
-
-/**
- * Virtual address mapped to the buffer shared with the kernel counterpart.
- */
-static uintptr_t input_buffer_addr;
-
-/*
- * 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)
-
-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 */
-input_buffer_t input_buffer;
-
-static volatile bool polling_disabled = false;
-static void niagara_thread_impl(void *arg);
-
-/**
- * Initializes the Niagara driver.
- * Maps the shared buffer and creates the polling thread. 
- */
-int kbd_port_init(void)
-{
-	sysarg_t paddr;
-	if (sysinfo_get_value("niagara.inbuf.address", &paddr) != EOK)
-		return -1;
-	
-	input_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
-	int rc = physmem_map((void *) paddr, (void *) input_buffer_addr,
-	    1, AS_AREA_READ | AS_AREA_WRITE);
-	
-	if (rc != 0) {
-		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
-		    rc);
-		return rc;
-	}
-	
-	input_buffer = (input_buffer_t) input_buffer_addr;
-	
-	thread_id_t tid;
-	rc = thread_create(niagara_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0)
-		return rc;
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-void kbd_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/**
- * Called regularly by the polling thread. Reads codes of all the
- * pressed keys from the buffer. 
- */
-static void niagara_key_pressed(void)
-{
-	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;
-		kbd_push_scancode(c);
-	}
-}
-
-/**
- * Thread to poll SGCN for keypresses.
- */
-static void niagara_thread_impl(void *arg)
-{
-	(void) arg;
-
-	while (1) {
-		if (polling_disabled == false)
-			niagara_key_pressed();
-		usleep(POLL_INTERVAL);
-	}
-}
-/** @}
- */
Index: pace/srv/hid/kbd/port/ns16550.c
===================================================================
--- uspace/srv/hid/kbd/port/ns16550.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,129 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief NS16550 port driver.
- */
-
-#include <ipc/irc.h>
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <ddi.h>
-#include <errno.h>
-
-/* NS16550 registers */
-#define RBR_REG  0  /** Receiver Buffer Register. */
-#define IER_REG  1  /** Interrupt Enable Register. */
-#define IIR_REG  2  /** Interrupt Ident Register (read). */
-#define FCR_REG  2  /** FIFO control register (write). */
-#define LCR_REG  3  /** Line Control register. */
-#define MCR_REG  4  /** Modem Control Register. */
-#define LSR_REG  5  /** Line Status Register. */
-
-#define LSR_DATA_READY  0x01
-
-static irq_cmd_t ns16550_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = LSR_DATA_READY,
-		.srcarg = 1,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-irq_code_t ns16550_kbd = {
-	sizeof(ns16550_cmds) / sizeof(irq_cmd_t),
-	ns16550_cmds
-};
-
-static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-static uintptr_t ns16550_physical;
-static uintptr_t ns16550_kernel; 
-
-int ns16550_port_init(void)
-{
-	void *vaddr;
-
-	if (sysinfo_get_value("kbd.address.physical", &ns16550_physical) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("kbd.address.kernel", &ns16550_kernel) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG);
-	ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG);
-	
-	async_set_interrupt_received(ns16550_irq_handler);
-	register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
-	
-	return pio_enable((void *) ns16550_physical, 8, &vaddr);
-}
-
-static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
-	
-	if (cir_service)
-		async_msg_1(cir_phone, IRC_CLEAR_INTERRUPT,
-		    IPC_GET_IMETHOD(*call));
-}
-
-/**
- * @}
- */
Index: pace/srv/hid/kbd/port/pl050.c
===================================================================
--- uspace/srv/hid/kbd/port/pl050.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Copyright (c) 2009 Vineeth Pillai
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup kbd
- * @{
- */ 
-/** @file
- * @brief pl050 port driver.
- */
-
-#include <ddi.h>
-#include <libarch/ddi.h>
-#include <async.h>
-#include <unistd.h>
-#include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <ddi.h>
-#include <stdio.h>
-#include <errno.h>
-
-#define PL050_STAT_RXFULL  (1 << 4)
-
-static irq_cmd_t pl050_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = PL050_STAT_RXFULL,
-		.srcarg = 1,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,  /* Will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-static irq_code_t pl050_kbd = {
-	sizeof(pl050_cmds) / sizeof(irq_cmd_t),
-	pl050_cmds
-};
-
-static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-int kbd_port_init(void)
-{
-	sysarg_t addr;
-	if (sysinfo_get_value("kbd.address.status", &addr) != EOK)
-		return -1;
-	
-	pl050_kbd.cmds[0].addr = (void *) addr;
-	
-	if (sysinfo_get_value("kbd.address.data", &addr) != EOK)
-		return -1;
-	
-	pl050_kbd.cmds[3].addr = (void *) addr;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	async_set_interrupt_received(pl050_irq_handler);
-	register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-
-	kbd_push_scancode(scan_code);
-	return;
-}
-
-/**
- * @}
- */ 
Index: pace/srv/hid/kbd/port/sgcn.c
===================================================================
--- uspace/srv/hid/kbd/port/sgcn.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,188 +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.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief SGCN (Serengeti Console) keyboard port driver.
- */
-
-#include <as.h>
-#include <ddi.h>
-#include <async.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <thread.h>
-#include <bool.h>
-#include <errno.h>
-
-#define POLL_INTERVAL  10000
-
-/**
- * SGCN buffer header. It is placed at the very beginning of the SGCN
- * buffer.
- */
-typedef struct {
-	/** hard-wired to "CON" */
-	char magic[4];
-	
-	/** we don't need this */
-	char unused[8];
-	
-	/** offset within the SGCN buffer of the input buffer start */
-	uint32_t in_begin;
-	
-	/** offset within the SGCN buffer of the input buffer end */
-	uint32_t in_end;
-	
-	/** offset within the SGCN buffer of the input buffer read pointer */
-	uint32_t in_rdptr;
-	
-	/** offset within the SGCN buffer of the input buffer write pointer */
-	uint32_t in_wrptr;
-} __attribute__ ((packed)) sgcn_buffer_header_t;
-
-/*
- * Returns a pointer to the object of a given type which is placed at the given
- * offset from the console buffer beginning.
- */
-#define SGCN_BUFFER(type, offset) \
-		((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
-
-/** Returns a pointer to the console buffer header. */
-#define SGCN_BUFFER_HEADER	(SGCN_BUFFER(sgcn_buffer_header_t, 0))
-
-/**
- * Virtual address mapped to SRAM.
- */
-static uintptr_t sram_virt_addr;
-
-/**
- * SGCN buffer offset within SGCN.
- */
-static uintptr_t sram_buffer_offset;
-
-/* polling thread */
-static void sgcn_thread_impl(void *arg);
-
-static volatile bool polling_disabled = false;
-
-/**
- * Initializes the SGCN driver.
- * Maps the physical memory (SRAM) and creates the polling thread. 
- */
-int kbd_port_init(void)
-{
-	sysarg_t sram_paddr;
-	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
-		return -1;
-	
-	sysarg_t sram_size;
-	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
-		sram_buffer_offset = 0;
-	
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
-	
-	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
-	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0) {
-		printf("SGCN: uspace driver could not map physical memory.");
-		return -1;
-	}
-	
-	thread_id_t tid;
-	int rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0)
-		return rc;
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-void kbd_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/**
- * Handler of the "key pressed" event. Reads codes of all the pressed keys from
- * the buffer. 
- */
-static void sgcn_key_pressed(void)
-{
-	char c;
-	
-	uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
-	uint32_t end = SGCN_BUFFER_HEADER->in_end;
-	uint32_t size = end - begin;
-	
-	volatile char *buf_ptr = (volatile char *)
-		SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-	volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
-	volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
-	
-	while (*in_rdptr_ptr != *in_wrptr_ptr) {
-		c = *buf_ptr;
-		*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
-		buf_ptr = (volatile char *)
-			SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-		kbd_push_scancode(c);
-	}
-}
-
-/**
- * Thread to poll SGCN for keypresses.
- */
-static void sgcn_thread_impl(void *arg)
-{
-	(void) arg;
-
-	while (1) {
-		if (polling_disabled == false)
-			sgcn_key_pressed();
-		usleep(POLL_INTERVAL);
-	}
-}
-
-/** @}
- */
Index: pace/srv/hid/kbd/port/ski.c
===================================================================
--- uspace/srv/hid/kbd/port/ski.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,128 +1,0 @@
-/*
- * Copyright (c) 2005 Jakub Jermar
- * 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 kbd_port
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- * @brief	Ski console keyboard port driver.
- */
-
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sys/types.h>
-#include <thread.h>
-#include <bool.h>
-
-#define SKI_GETCHAR		21
-
-#define POLL_INTERVAL		10000
-
-static void ski_thread_impl(void *arg);
-static int32_t ski_getchar(void);
-
-static volatile bool polling_disabled = false;
-
-/** Initialize Ski port driver. */
-int kbd_port_init(void)
-{
-	thread_id_t tid;
-	int rc;
-
-	rc = thread_create(ski_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0) {
-		return rc;
-	}
-
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-void kbd_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** Thread to poll Ski for keypresses. */
-static void ski_thread_impl(void *arg)
-{
-	int32_t c;
-	(void) arg;
-
-	while (1) {
-		while (polling_disabled == false) {
-			c = ski_getchar();
-			if (c == 0)
-				break;
-			kbd_push_scancode(c);
-		}
-
-		usleep(POLL_INTERVAL);
-	}
-}
-
-/** Ask Ski if a key was pressed.
- *
- * Use SSC (Simulator System Call) to get character from the debug console.
- * This call is non-blocking.
- *
- * @return ASCII code of pressed key or 0 if no key pressed.
- */
-static int32_t ski_getchar(void)
-{
-	uint64_t ch;
-	
-	asm volatile (
-		"mov r15 = %1\n"
-		"break 0x80000;;\n"	/* modifies r8 */
-		"mov %0 = r8;;\n"		
-
-		: "=r" (ch)
-		: "i" (SKI_GETCHAR)
-		: "r15", "r8"
-	);
-
-	return (int32_t) ch;
-}
-
-/** @}
- */
Index: pace/srv/hid/kbd/port/sun.c
===================================================================
--- uspace/srv/hid/kbd/port/sun.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Sun keyboard virtual port driver.
- */
-
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <sysinfo.h>
-#include <errno.h>
-#include <bool.h>
-
-/** Sun keyboard virtual port driver.
- *
- * This is a virtual port driver which can use
- * both ns16550_port_init and z8530_port_init
- * according to the information passed from the
- * kernel. This is just a temporal hack.
- *
- */
-int kbd_port_init(void)
-{
-	sysarg_t z8530;
-	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
-		z8530 = false;
-	
-	sysarg_t ns16550;
-	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
-		ns16550 = false;
-	
-	if (z8530) {
-		if (z8530_port_init() == 0)
-			return 0;
-	}
-	
-	if (ns16550) {
-		if (ns16550_port_init() == 0)
-			return 0;
-	}
-	
-	return -1;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: pace/srv/hid/kbd/port/z8530.c
===================================================================
--- uspace/srv/hid/kbd/port/z8530.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,116 +1,0 @@
-/*
- * Copyright (c) 2006 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.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Z8530 keyboard port driver.
- */
-
-#include <ipc/irc.h>
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <sys/types.h>
-#include <ddi.h>
-#include <errno.h>
-
-#define CHAN_A_STATUS  4
-#define CHAN_A_DATA    6
-
-#define RR0_RCA  1
-
-static irq_cmd_t z8530_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = RR0_RCA,
-		.srcarg = 1,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-	
-irq_code_t z8530_kbd = {
-	sizeof(z8530_cmds) / sizeof(irq_cmd_t),
-	z8530_cmds
-};
-
-static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-int z8530_port_init(void)
-{
-	sysarg_t kaddr;
-	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	z8530_cmds[0].addr = (void *) kaddr + CHAN_A_STATUS;
-	z8530_cmds[3].addr = (void *) kaddr + CHAN_A_DATA;
-	
-	async_set_interrupt_received(z8530_irq_handler);
-	register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
-	
-	return 0;
-}
-
-static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
-	
-	if (cir_service)
-		async_msg_1(cir_phone, IRC_CLEAR_INTERRUPT,
-		    IPC_GET_IMETHOD(*call));
-}
-
-/** @}
- */
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,9 +39,10 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <devmap.h>
+#include <loc.h>
 #include <io/console.h>
 #include <vfs/vfs.h>
-#include <ipc/mouse.h>
+#include <ipc/mouseev.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -50,9 +51,11 @@
 #include <errno.h>
 #include <inttypes.h>
-
 #include "s3c24xx_ts.h"
 
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
+
 #define NAME "s3c24ser"
-#define NAMESPACE "hid_in"
+#define NAMESPACE "hid"
 
 static irq_cmd_t ts_irq_cmds[] = {
@@ -70,5 +73,6 @@
 static s3c24xx_ts_t *ts;
 
-static void s3c24xx_ts_connection(ipc_callid_t iid, ipc_call_t *icall);
+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);
 static void s3c24xx_ts_pen_down(s3c24xx_ts_t *ts);
@@ -86,5 +90,5 @@
 	printf(NAME ": S3C24xx touchscreen driver\n");
 
-	rc = devmap_driver_register(NAME, s3c24xx_ts_connection);
+	rc = loc_server_register(NAME, s3c24xx_ts_connection);
 	if (rc < 0) {
 		printf(NAME ": Unable to register driver.\n");
@@ -99,5 +103,5 @@
 		return -1;
 
-	rc = devmap_device_register(NAMESPACE "/mouse", &ts->devmap_handle);
+	rc = loc_service_register(NAMESPACE "/mouse", &ts->service_id);
 	if (rc != EOK) {
 		printf(NAME ": Unable to register device %s.\n",
@@ -280,5 +284,5 @@
 	button = 1;
 	press = 0;
-	async_msg_2(ts->client_phone, MEVENT_BUTTON, button, press);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_BUTTON_EVENT, button, press);
 
 	s3c24xx_ts_wait_for_int_mode(ts, updn_down);
@@ -321,6 +325,6 @@
 
 	/* Send notifications to client. */
-	async_msg_2(ts->client_phone, MEVENT_MOVE, dx, dy);
-	async_msg_2(ts->client_phone, MEVENT_BUTTON, button, press);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_MOVE_EVENT, dx, dy);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_BUTTON_EVENT, button, press);
 
 	ts->last_x = x_pos;
@@ -370,5 +374,6 @@
 
 /** Handle mouse client connection. */
-static void s3c24xx_ts_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void s3c24xx_ts_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	ipc_callid_t callid;
@@ -380,8 +385,8 @@
 	while (1) {
 		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!IPC_GET_IMETHOD(call)) {
 			if (ts->client_phone != -1) {
-				async_hangup(ts->client_phone);
+				async_obsolete_hangup(ts->client_phone);
 				ts->client_phone = -1;
 			}
@@ -389,4 +394,7 @@
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case IPC_M_CONNECT_TO_ME:
 			if (ts->client_phone != -1) {
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.h
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -124,6 +124,6 @@
 	int client_phone;
 
-	/** Device handle */
-	devmap_handle_t devmap_handle;
+	/** Service ID */
+	service_id_t service_id;
 
 	/** Device/driver state */
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,15 +43,19 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <devmap.h>
+#include <loc.h>
 #include <sysinfo.h>
 #include <errno.h>
 #include <ipc/adb.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <assert.h>
 #include "cuda_adb.h"
 
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
+
 #define NAME "cuda_adb"
 
-static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static int cuda_init(void);
 static void cuda_irq_handler(ipc_callid_t iid, ipc_call_t *call);
@@ -143,5 +147,5 @@
 int main(int argc, char *argv[])
 {
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	int rc;
 	int i;
@@ -151,29 +155,29 @@
 	for (i = 0; i < ADB_MAX_ADDR; ++i) {
 		adb_dev[i].client_phone = -1;
-		adb_dev[i].devmap_handle = 0;
-	}
-
-	rc = devmap_driver_register(NAME, cuda_connection);
+		adb_dev[i].service_id = 0;
+	}
+
+	rc = loc_server_register(NAME, cuda_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return rc;
 	}
 
-	rc = devmap_device_register("adb/kbd", &devmap_handle);
+	rc = loc_service_register("adb/kbd", &service_id);
 	if (rc != EOK) {
-		printf(NAME ": Unable to register device %s.\n", "adb/kdb");
+		printf(NAME ": Unable to register service %s.\n", "adb/kdb");
 		return rc;
 	}
 
-	adb_dev[2].devmap_handle = devmap_handle;
-	adb_dev[8].devmap_handle = devmap_handle;
-
-	rc = devmap_device_register("adb/mouse", &devmap_handle);
+	adb_dev[2].service_id = service_id;
+	adb_dev[8].service_id = service_id;
+
+	rc = loc_service_register("adb/mouse", &service_id);
 	if (rc != EOK) {
-		printf(NAME ": Unable to register device %s.\n", "adb/mouse");
+		printf(NAME ": Unable to register servise %s.\n", "adb/mouse");
 		return rc;
 	}
 
-	adb_dev[9].devmap_handle = devmap_handle;
+	adb_dev[9].service_id = service_id;
 
 	if (cuda_init() < 0) {
@@ -189,20 +193,20 @@
 
 /** Character device connection handler */
-static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dsid;
 	int retval;
 	int dev_addr, i;
 
 	/* Get the device handle. */
-	dh = IPC_GET_ARG1(*icall);
+	dsid = IPC_GET_ARG1(*icall);
 
 	/* Determine which disk device is the client connecting to. */
 	dev_addr = -1;
 	for (i = 0; i < ADB_MAX_ADDR; i++) {
-		if (adb_dev[i].devmap_handle == dh)
+		if (adb_dev[i].service_id == dsid)
 			dev_addr = i;
 	}
@@ -219,9 +223,12 @@
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case IPC_M_CONNECT_TO_ME:
 			if (adb_dev[dev_addr].client_phone != -1) {
@@ -235,5 +242,5 @@
 			 */
 			for (i = 0; i < ADB_MAX_ADDR; ++i) {
-				if (adb_dev[i].devmap_handle == dh) {
+				if (adb_dev[i].service_id == dsid) {
 					adb_dev[i].client_phone = IPC_GET_ARG5(call);
 				}
@@ -367,9 +374,9 @@
 static void cuda_irq_rcv_end(void *buf, size_t *len)
 {
-	uint8_t data, b;
-
+	uint8_t b;
+	
 	b = pio_read_8(&dev->b);
-	data = pio_read_8(&dev->sr);
-
+	pio_read_8(&dev->sr);
+	
 	if ((b & TREQ) == 0) {
 		instance->xstate = cx_receive;
@@ -379,7 +386,7 @@
 		cuda_send_start();
 	}
-
-        memcpy(buf, instance->rcv_buf, instance->bidx);
-        *len = instance->bidx;
+	
+	memcpy(buf, instance->rcv_buf, instance->bidx);
+	*len = instance->bidx;
 	instance->bidx = 0;
 }
@@ -479,5 +486,5 @@
 		return;
 
-	async_msg_1(adb_dev[dev_addr].client_phone, ADB_REG_NOTIF, reg_val);
+	async_obsolete_msg_1(adb_dev[dev_addr].client_phone, ADB_REG_NOTIF, reg_val);
 }
 
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.h
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 
 #include <sys/types.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 #include <fibril_synch.h>
 
@@ -104,5 +104,5 @@
 
 typedef struct {
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	int client_phone;
 } adb_dev_t;
Index: uspace/srv/hw/char/i8042/i8042.c
===================================================================
--- uspace/srv/hw/char/i8042/i8042.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/char/i8042/i8042.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,6 +39,7 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <devmap.h>
+#include <loc.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <unistd.h>
 #include <sysinfo.h>
@@ -46,6 +47,8 @@
 #include <errno.h>
 #include <inttypes.h>
-
 #include "i8042.h"
+
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
 
 #define NAME "i8042"
@@ -119,5 +122,5 @@
 
 static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static int i8042_init(void);
 static void i8042_port_write(int devid, uint8_t data);
@@ -132,7 +135,7 @@
 	printf(NAME ": i8042 PS/2 port driver\n");
 
-	rc = devmap_driver_register(NAME, i8042_connection);
+	rc = loc_server_register(NAME, i8042_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return rc;
 	}
@@ -145,5 +148,5 @@
 
 		snprintf(name, 16, "%s/ps2%c", NAMESPACE, dchar[i]);
-		rc = devmap_device_register(name, &i8042_port[i].devmap_handle);
+		rc = loc_service_register(name, &i8042_port[i].service_id);
 		if (rc != EOK) {
 			printf(NAME ": Unable to register device %s.\n", name);
@@ -213,10 +216,10 @@
 
 /** Character device connection handler */
-static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
 	ipc_call_t call;
 	sysarg_t method;
-	devmap_handle_t dh;
+	service_id_t dsid;
 	int retval;
 	int dev_id, i;
@@ -225,10 +228,10 @@
 
 	/* Get the device handle. */
-	dh = IPC_GET_ARG1(*icall);
+	dsid = IPC_GET_ARG1(*icall);
 
 	/* Determine which disk device is the client connecting to. */
 	dev_id = -1;
 	for (i = 0; i < MAX_DEVS; i++) {
-		if (i8042_port[i].devmap_handle == dh)
+		if (i8042_port[i].service_id == dsid)
 			dev_id = i;
 	}
@@ -247,9 +250,12 @@
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case IPC_M_CONNECT_TO_ME:
 			printf(NAME ": creating callback connection\n");
@@ -300,5 +306,5 @@
 
 	if (i8042_port[devid].client_phone != -1) {
-		async_msg_1(i8042_port[devid].client_phone,
+		async_obsolete_msg_1(i8042_port[devid].client_phone,
 		    IPC_FIRST_USER_METHOD, data);
 	}
Index: uspace/srv/hw/char/i8042/i8042.h
===================================================================
--- uspace/srv/hw/char/i8042/i8042.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/char/i8042/i8042.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,5 +52,5 @@
 /** Softstate structure, one for each serial port (primary and aux). */
 typedef struct {
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 	int client_phone;
 } i8042_port_t;
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,7 +39,8 @@
 #include <ddi.h>
 #include <libarch/ddi.h>
-#include <devmap.h>
+#include <loc.h>
 #include <ipc/char.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -48,6 +49,8 @@
 #include <errno.h>
 #include <inttypes.h>
-
 #include "s3c24xx_uart.h"
+
+// FIXME: remove this header
+#include <abi/ipc/methods.h>
 
 #define NAME "s3c24ser"
@@ -68,5 +71,6 @@
 static s3c24xx_uart_t *uart;
 
-static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg);
 static void s3c24xx_uart_irq_handler(ipc_callid_t iid, ipc_call_t *call);
 static int s3c24xx_uart_init(s3c24xx_uart_t *uart);
@@ -79,7 +83,7 @@
 	printf(NAME ": S3C24xx on-chip UART driver\n");
 
-	rc = devmap_driver_register(NAME, s3c24xx_uart_connection);
+	rc = loc_server_register(NAME, s3c24xx_uart_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver.\n");
+		printf(NAME ": Unable to register server.\n");
 		return -1;
 	}
@@ -92,5 +96,5 @@
 		return -1;
 
-	rc = devmap_device_register(NAMESPACE "/" NAME, &uart->devmap_handle);
+	rc = loc_service_register(NAMESPACE "/" NAME, &uart->service_id);
 	if (rc != EOK) {
 		printf(NAME ": Unable to register device %s.\n",
@@ -110,5 +114,6 @@
 
 /** Character device connection handler. */
-static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	ipc_callid_t callid;
@@ -123,9 +128,12 @@
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case IPC_M_CONNECT_TO_ME:
 			printf(NAME ": creating callback connection\n");
@@ -156,5 +164,5 @@
 
 		if (uart->client_phone != -1) {
-			async_msg_1(uart->client_phone, CHAR_NOTIF_BYTE,
+			async_obsolete_msg_1(uart->client_phone, CHAR_NOTIF_BYTE,
 			    data);
 		}
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -87,6 +87,6 @@
 	int client_phone;
 
-	/** Device handle */
-	devmap_handle_t devmap_handle;
+	/** Service ID */
+	service_id_t service_id;
 } s3c24xx_uart_t;
 
Index: uspace/srv/hw/irc/apic/apic.c
===================================================================
--- uspace/srv/hw/irc/apic/apic.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/irc/apic/apic.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,24 +38,118 @@
 #include <ipc/services.h>
 #include <ipc/irc.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <sysinfo.h>
 #include <as.h>
 #include <ddi.h>
-#include <libarch/ddi.h>
-#include <align.h>
 #include <bool.h>
 #include <errno.h>
 #include <async.h>
-#include <align.h>
-#include <async.h>
 #include <stdio.h>
-#include <ipc/devmap.h>
 
 #define NAME  "apic"
 
+#define APIC_MAX_IRQ	15
+
+#define IOREGSEL  (0x00U / sizeof(uint32_t))
+#define IOWIN     (0x10U / sizeof(uint32_t))
+
+#define IOREDTBL   0x10U
+
+/** I/O Register Select Register. */
+typedef union {
+	uint32_t value;
+	struct {
+		uint8_t reg_addr;	/**< APIC Register Address. */
+		unsigned int : 24;	/**< Reserved. */
+	} __attribute__ ((packed));
+} io_regsel_t;
+
+/** I/O Redirection Register. */
+typedef struct io_redirection_reg {
+	union {
+		uint32_t lo;
+		struct {
+			uint8_t intvec;			/**< Interrupt Vector. */
+			unsigned int delmod : 3;	/**< Delivery Mode. */
+			unsigned int destmod : 1;	/**< Destination mode. */
+			unsigned int delivs : 1;	/**< Delivery status (RO). */
+			unsigned int intpol : 1;	/**< Interrupt Input Pin Polarity. */
+			unsigned int irr : 1;		/**< Remote IRR (RO). */
+			unsigned int trigger_mode : 1;	/**< Trigger Mode. */
+			unsigned int masked : 1;	/**< Interrupt Mask. */
+			unsigned int : 15;		/**< Reserved. */
+		} __attribute__ ((packed));
+	};
+	union {
+		uint32_t hi;
+		struct {
+			unsigned int : 24;	/**< Reserved. */
+			uint8_t dest : 8;  	/**< Destination Field. */
+		} __attribute__ ((packed));
+	};
+} __attribute__ ((packed)) io_redirection_reg_t;
+
+// FIXME: get the address from the kernel
+#define IO_APIC_BASE	0xfec00000UL
+#define IO_APIC_SIZE	20
+
+ioport32_t *io_apic = NULL;
+
+/** Read from IO APIC register.
+ *
+ * @param address IO APIC register address.
+ *
+ * @return Content of the addressed IO APIC register.
+ *
+ */
+static uint32_t io_apic_read(uint8_t address)
+{
+	io_regsel_t regsel;
+
+	regsel.value = io_apic[IOREGSEL];
+	regsel.reg_addr = address;
+	io_apic[IOREGSEL] = regsel.value;
+	return io_apic[IOWIN];
+}
+
+/** Write to IO APIC register.
+ *
+ * @param address IO APIC register address.
+ * @param val     Content to be written to the addressed IO APIC register.
+ *
+ */
+static void io_apic_write(uint8_t address, uint32_t val)
+{
+	io_regsel_t regsel;
+
+	regsel.value = io_apic[IOREGSEL];
+	regsel.reg_addr = address;
+	io_apic[IOREGSEL] = regsel.value;
+	io_apic[IOWIN] = val;
+}
+
+static int irq_to_pin(int irq)
+{
+	// FIXME: get the map from the kernel, even though this may work
+	//	  for simple cases
+	return irq;
+}
+
 static int apic_enable_irq(sysarg_t irq)
 {
-	// FIXME: TODO
-	return ENOTSUP;
+	io_redirection_reg_t reg;
+
+	if (irq > APIC_MAX_IRQ)
+		return ELIMIT;
+
+	int pin = irq_to_pin(irq);
+ 	if (pin == -1)
+		return ENOENT;
+
+	reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
+	reg.masked = false;
+	io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo);
+
+	return EOK;
 }
 
@@ -64,7 +158,7 @@
  * @param iid   Hash of the request that opened the connection.
  * @param icall Call data of the request that opened the connection.
- *
- */
-static void apic_connection(ipc_callid_t iid, ipc_call_t *icall)
+ * @param arg	Local argument.
+ */
+static void apic_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -78,4 +172,10 @@
 	while (true) {
 		callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
 		
 		switch (IPC_GET_IMETHOD(call)) {
@@ -102,10 +202,14 @@
 	
 	if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) {
-		printf(NAME ": No APIC found\n");
+		printf("%s: No APIC found\n", NAME);
 		return false;
 	}
+
+	if (pio_enable((void *) IO_APIC_BASE, IO_APIC_SIZE,
+	    (void **) &io_apic) != EOK)
+		return false;	
 	
 	async_set_client_connection(apic_connection);
-	service_register(SERVICE_APIC);
+	service_register(SERVICE_IRC);
 	
 	return true;
@@ -114,10 +218,11 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS APIC driver\n");
+	printf("%s: HelenOS APIC driver\n", NAME);
 	
 	if (!apic_init())
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
 	
Index: pace/srv/hw/irc/fhc/Makefile
===================================================================
--- uspace/srv/hw/irc/fhc/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,36 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-BINARY = fhc
-
-SOURCES = \
-	fhc.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/hw/irc/fhc/fhc.c
===================================================================
--- uspace/srv/hw/irc/fhc/fhc.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,159 +1,0 @@
-/*
- * Copyright (c) 2009 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 fhc
- * @{
- */
-
-/**
- * @file fhc.c
- * @brief FHC bus controller driver.
- */
-
-#include <ipc/services.h>
-#include <ipc/irc.h>
-#include <ipc/ns.h>
-#include <sysinfo.h>
-#include <as.h>
-#include <ddi.h>
-#include <align.h>
-#include <bool.h>
-#include <errno.h>
-#include <async.h>
-#include <align.h>
-#include <async.h>
-#include <stdio.h>
-#include <ipc/devmap.h>
-
-#define NAME "fhc"
-
-#define FHC_UART_INR	0x39	
-
-#define FHC_UART_IMAP	0x0
-#define FHC_UART_ICLR	0x4
-
-static void *fhc_uart_phys;
-static volatile uint32_t *fhc_uart_virt;
-static size_t fhc_uart_size;
-
-/** Handle one connection to fhc.
- *
- * @param iid		Hash of the request that opened the connection.
- * @param icall		Call data of the request that opened the connection.
- */
-static void fhc_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-
-	/*
-	 * Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		int inr;
-	
-		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IRC_ENABLE_INTERRUPT:
-			/* Noop */
-			async_answer_0(callid, EOK);
-			break;
-		case IRC_CLEAR_INTERRUPT:
-			inr = IPC_GET_ARG1(call);
-			switch (inr) {
-			case FHC_UART_INR:
-				fhc_uart_virt[FHC_UART_ICLR] = 0;
-				async_answer_0(callid, EOK);
-				break;
-			default:
-				async_answer_0(callid, ENOTSUP);
-				break;
-			}
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-			break;
-		}
-	}
-}
-
-/** Initialize the FHC driver.
- *
- * So far, the driver heavily depends on information provided by the kernel via
- * sysinfo. In the future, there should be a standalone FHC driver.
- */
-static bool fhc_init(void)
-{
-	sysarg_t paddr;
-
-	if ((sysinfo_get_value("fhc.uart.physical", &paddr) != EOK)
-	    || (sysinfo_get_value("fhc.uart.size", &fhc_uart_size) != EOK)) {
-		printf(NAME ": no FHC UART registers found\n");
-		return false;
-	}
-	
-	fhc_uart_phys = (void *) paddr;
-	fhc_uart_virt = as_get_mappable_page(fhc_uart_size);
-	
-	int flags = AS_AREA_READ | AS_AREA_WRITE;
-	int retval = physmem_map(fhc_uart_phys, (void *) fhc_uart_virt,
-	    ALIGN_UP(fhc_uart_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
-	
-	if (retval < 0) {
-		printf(NAME ": Error mapping FHC UART registers\n");
-		return false;
-	}
-	
-	printf(NAME ": FHC UART registers at %p, %zu bytes\n", fhc_uart_phys,
-	    fhc_uart_size);
-	
-	async_set_client_connection(fhc_connection);
-	service_register(SERVICE_FHC);
-	
-	return true;
-}
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": HelenOS FHC bus controller driver\n");
-	
-	if (!fhc_init())
-		return -1;
-	
-	printf(NAME ": Accepting connections\n");
-	async_manager();
-
-	/* Never reached */
-	return 0;
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hw/irc/i8259/i8259.c
===================================================================
--- uspace/srv/hw/irc/i8259/i8259.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/irc/i8259/i8259.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,5 +38,5 @@
 #include <ipc/services.h>
 #include <ipc/irc.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <sysinfo.h>
 #include <as.h>
@@ -50,5 +50,5 @@
 #include <async.h>
 #include <stdio.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 
 #define NAME  "i8259"
@@ -98,7 +98,7 @@
  * @param iid   Hash of the request that opened the connection.
  * @param icall Call data of the request that opened the connection.
- *
+ * @param arg	Local argument.
  */
-static void i8259_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void i8259_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -112,4 +112,10 @@
 	while (true) {
 		callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
 		
 		switch (IPC_GET_IMETHOD(call)) {
@@ -136,5 +142,5 @@
 	
 	if ((sysinfo_get_value("i8259", &i8259) != EOK) || (!i8259)) {
-		printf(NAME ": No i8259 found\n");
+		printf("%s: No i8259 found\n", NAME);
 		return false;
 	}
@@ -144,10 +150,10 @@
 	    (pio_enable((void *) IO_RANGE1_START, IO_RANGE1_SIZE,
 	    (void **) &io_range1) != EOK)) {
-		printf(NAME ": i8259 not accessible\n");
+		printf("%s: i8259 not accessible\n", NAME);
 		return false;
 	}
 	
 	async_set_client_connection(i8259_connection);
-	service_register(SERVICE_I8259);
+	service_register(SERVICE_IRC);
 	
 	return true;
@@ -156,10 +162,11 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS i8259 driver\n");
+	printf("%s: HelenOS i8259 driver\n", NAME);
 	
 	if (!i8259_init())
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
 	
Index: uspace/srv/hw/irc/obio/obio.c
===================================================================
--- uspace/srv/hw/irc/obio/obio.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/irc/obio/obio.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,5 +44,5 @@
 #include <ipc/services.h>
 #include <ipc/irc.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <sysinfo.h>
 #include <as.h>
@@ -55,5 +55,5 @@
 #include <async.h>
 #include <stdio.h>
-#include <ipc/devmap.h>
+#include <ipc/loc.h>
 
 #define NAME "obio"
@@ -76,6 +76,7 @@
  * @param iid		Hash of the request that opened the connection.
  * @param icall		Call data of the request that opened the connection.
+ * @param arg		Local argument.
  */
-static void obio_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void obio_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -118,5 +119,5 @@
 	
 	if (sysinfo_get_value("obio.base.physical", &paddr) != EOK) {
-		printf(NAME ": no OBIO registers found\n");
+		printf("%s: No OBIO registers found\n", NAME);
 		return false;
 	}
@@ -130,12 +131,12 @@
 	
 	if (retval < 0) {
-		printf(NAME ": Error mapping OBIO registers\n");
+		printf("%s: Error mapping OBIO registers\n", NAME);
 		return false;
 	}
 	
-	printf(NAME ": OBIO registers with base at %p\n", base_phys);
+	printf("%s: OBIO registers with base at %p\n", NAME, base_phys);
 	
 	async_set_client_connection(obio_connection);
-	service_register(SERVICE_OBIO);
+	service_register(SERVICE_IRC);
 	
 	return true;
@@ -144,12 +145,13 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS OBIO driver\n");
+	printf("%s: HelenOS OBIO driver\n", NAME);
 	
 	if (!obio_init())
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
-
+	
 	/* Never reached */
 	return 0;
@@ -158,3 +160,3 @@
 /**
  * @}
- */ 
+ */
Index: uspace/srv/hw/netif/ne2000/dp8390.c
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/netif/ne2000/dp8390.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -53,4 +53,5 @@
 #include <byteorder.h>
 #include <errno.h>
+#include <stdio.h>
 #include <libarch/ddi.h>
 #include <net/packet.h>
@@ -391,4 +392,5 @@
 	
 	if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) {
+		fibril_mutex_unlock(&ne2k->sq_mutex);
 		fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n",
 		    NAME, size);
@@ -481,5 +483,5 @@
 }
 
-static link_t *ne2k_receive(ne2k_t *ne2k)
+static list_t *ne2k_receive(ne2k_t *ne2k)
 {
 	/*
@@ -488,5 +490,5 @@
 	 * frames from the network, but they will be lost.
 	 */
-	link_t *frames = (link_t *) malloc(sizeof(link_t));
+	list_t *frames = (list_t *) malloc(sizeof(list_t));
 	if (frames != NULL)
 		list_initialize(frames);
@@ -565,8 +567,8 @@
 }
 
-link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
+list_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
 {
 	/* List of received frames */
-	link_t *frames = NULL;
+	list_t *frames = NULL;
 	
 	if (isr & (ISR_PTX | ISR_TXE)) {
Index: uspace/srv/hw/netif/ne2000/dp8390.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/netif/ne2000/dp8390.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -241,5 +241,5 @@
 extern void ne2k_down(ne2k_t *);
 extern void ne2k_send(ne2k_t *, packet_t *);
-extern link_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
+extern list_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
 
 #endif
Index: uspace/srv/hw/netif/ne2000/ne2000.c
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/hw/netif/ne2000/ne2000.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,6 +43,6 @@
 #include <malloc.h>
 #include <sysinfo.h>
+#include <ns.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
 #include <ipc/irc.h>
 #include <net/modules.h>
@@ -75,6 +75,6 @@
 #define IRQ_GET_TSR(call)  ((int) IPC_GET_ARG3(call))
 
-static int irc_service = 0;
-static int irc_phone = -1;
+static bool irc_service = false;
+static async_sess_t *irc_sess = NULL;
 
 /** NE2000 kernel interrupt command sequence.
@@ -152,13 +152,14 @@
 	device_id_t device_id = IRQ_GET_DEVICE(*call);
 	netif_device_t *device;
-	int nil_phone;
+	async_sess_t *nil_sess;
 	ne2k_t *ne2k;
 	
 	fibril_rwlock_read_lock(&netif_globals.lock);
 	
-	if (find_device(device_id, &device) == EOK) {
-		nil_phone = device->nil_phone;
+	nil_sess = netif_globals.nil_sess;
+	
+	if (find_device(device_id, &device) == EOK)
 		ne2k = (ne2k_t *) device->specific;
-	} else
+	else
 		ne2k = NULL;
 	
@@ -166,14 +167,14 @@
 	
 	if (ne2k != NULL) {
-		link_t *frames =
+		list_t *frames =
 		    ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
 		
 		if (frames != NULL) {
 			while (!list_empty(frames)) {
-				frame_t *frame =
-				    list_get_instance(frames->next, frame_t, link);
+				frame_t *frame = list_get_instance(
+				    list_first(frames), frame_t, link);
 				
 				list_remove(&frame->link);
-				nil_received_msg(nil_phone, device_id, frame->packet,
+				nil_received_msg(nil_sess, device_id, frame->packet,
 				    SERVICE_NONE);
 				free(frame);
@@ -276,5 +277,4 @@
 	
 	device->device_id = device_id;
-	device->nil_phone = -1;
 	device->specific = (void *) ne2k;
 	device->state = NETIF_STOPPED;
@@ -329,6 +329,9 @@
 		change_state(device, NETIF_ACTIVE);
 		
-		if (irc_service)
-			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
+		if (irc_service) {
+			async_exch_t *exch = async_exchange_begin(irc_sess);
+			async_msg_1(exch, IRC_ENABLE_INTERRUPT, ne2k->irq);
+			async_exchange_end(exch);
+		}
 	}
 	
@@ -383,17 +386,17 @@
 	sysarg_t i8259;
 	
-	if ((sysinfo_get_value("apic", &apic) == EOK) && (apic))
-		irc_service = SERVICE_APIC;
-	else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))
-		irc_service = SERVICE_I8259;
+	if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
+	    || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)))
+		irc_service = true;
 	
 	if (irc_service) {
-		while (irc_phone < 0)
-			irc_phone = service_connect_blocking(irc_service, 0, 0);
+		while (!irc_sess)
+			irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+			    SERVICE_IRC, 0, 0);
 	}
 	
 	async_set_interrupt_received(irq_handler);
 	
-	return async_connect_to_me(PHONE_NS, SERVICE_NE2000, 0, 0, NULL);
+	return service_register(SERVICE_NE2000);
 }
 
Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/loader/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,16 +36,12 @@
 -include $(COMMON_MAKEFILE)
 -include $(CONFIG_MAKEFILE)
--include arch/$(UARCH)/Makefile.inc
 
-LINKER_SCRIPT = arch/$(UARCH)/_link.ld
-EXTRA_CLEAN = $(LINKER_SCRIPT)
-
-EXTRA_CFLAGS = -Iinclude
+LINKER_SCRIPT = $(LIBC_PREFIX)/arch/$(UARCH)/_link-loader.ld
 
 BINARY = loader
+STATIC_ONLY = y
 
 GENERIC_SOURCES = \
 	main.c \
-	elf_load.c \
 	interp.s
 
@@ -55,5 +51,2 @@
 
 include $(USPACE_PREFIX)/Makefile.common
-
-$(LINKER_SCRIPT): $(LINKER_SCRIPT).in
-	$(GCC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@
Index: pace/srv/loader/arch/abs32le/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/abs32le/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,29 +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.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/abs32le.c
Index: pace/srv/loader/arch/abs32le/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/abs32le/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,60 +1,0 @@
-/*
- * The difference from _link.ld.in for regular statically-linked apps
- * is the base address and the special interp section.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FILEHDR PHDRS FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70001000;
-	
-	.text : {
-		*(.text);
-		*(.rodata*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.data);
-		*(.data.rel*);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		*(.gnu.linkonce.tb.*);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.sbss : {
-		*(.scommon);
-		*(.sbss);
-	}
-	
-	.bss : {
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: pace/srv/loader/arch/abs32le/abs32le.c
===================================================================
--- uspace/srv/loader/arch/abs32le/abs32le.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,42 +1,0 @@
-/*
- * Copyright (c) 2010 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 <bool.h>
-#include "arch.h"
-
-void program_run(void *entry_point, void *pcb)
-{
-	while (true);
-}
-
-/**
- * @}
- */
Index: pace/srv/loader/arch/amd64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/amd64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,29 +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.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/amd64.s
Index: pace/srv/loader/arch/amd64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/amd64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * The difference from _link.ld.in for regular statically-linked apps
- * is the base address and the special interp section.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-	debug PT_NOTE;
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	/* . = 0x0000700000001000; */
-	. = 0x70001000;
-	
-	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text);
-		*(.rodata*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.data);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-#ifdef CONFIG_LINE_DEBUG
-	.comment 0 : { *(.comment); } :debug
-	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
-	.debug_aranges 0 : { *(.debug_aranges); } :debug
-	.debug_info 0 : { *(.debug_info); } :debug
-	.debug_line 0 : { *(.debug_line); } :debug
-	.debug_loc 0 : { *(.debug_loc); } :debug
-	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
-	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
-	.debug_ranges 0 : { *(.debug_ranges); } :debug
-	.debug_str 0 : { *(.debug_str); } :debug
-#endif
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: pace/srv/loader/arch/amd64/amd64.s
===================================================================
--- uspace/srv/loader/arch/amd64/amd64.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,43 +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.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# %rdi	contains entry_point
-# %rsi	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	# pcb must be passed in %rdi, use %rdx as a scratch register
-	mov %rdi, %rdx
-	mov %rsi, %rdi
-
-	# jump to entry point
-	jmp %rdx
Index: pace/srv/loader/arch/arm32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/arm32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,29 +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.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/arm32.s
Index: pace/srv/loader/arch/arm32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/arm32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * The only difference from _link.ld.in for regular statically-linked apps
- * is the base address.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} : interp
-	
-	. = 0x70001000;
-	
-	.init ALIGN(0x1000): SUBALIGN(0x1000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text);
-		*(.rodata*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.opd);
-		*(.data .data.*);
-		*(.sdata);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(.sbss);
-		*(.scommon);
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: pace/srv/loader/arch/arm32/arm32.s
===================================================================
--- uspace/srv/loader/arch/arm32/arm32.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,42 +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.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# r0	contains entry_point
-# r1	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	# load ras_page address to r2
-	ldr r2, =ras_page
-	ldr r2, [r2]
-	# pcb is passed to the entry point in r1 (where it already is)
-	mov r15, r0
Index: pace/srv/loader/arch/ia32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ia32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,29 +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.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/ia32.s
Index: pace/srv/loader/arch/ia32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * The difference from _link.ld.in for regular statically-linked apps
- * is the base address and the special interp section.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FILEHDR PHDRS FLAGS(5);
-	data PT_LOAD FLAGS(6);
-	debug PT_NOTE;
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70001000;
-	
-	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text);
-		*(.rodata*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.data);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		*(.gnu.linkonce.tb.*);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-#ifdef CONFIG_LINE_DEBUG
-	.comment 0 : { *(.comment); } :debug
-	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
-	.debug_aranges 0 : { *(.debug_aranges); } :debug
-	.debug_info 0 : { *(.debug_info); } :debug
-	.debug_line 0 : { *(.debug_line); } :debug
-	.debug_loc 0 : { *(.debug_loc); } :debug
-	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
-	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
-	.debug_ranges 0 : { *(.debug_ranges); } :debug
-	.debug_str 0 : { *(.debug_str); } :debug
-#endif
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: pace/srv/loader/arch/ia32/ia32.s
===================================================================
--- uspace/srv/loader/arch/ia32/ia32.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,49 +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.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# Jump to a program entry point
-program_run:
-	# Use standard ia32 prologue not to confuse anybody
-	push %ebp
-	movl %esp, %ebp
-
-	# %eax := entry_point
-	movl 0x8(%ebp), %eax
-
-	# %edi := pcb
-	# pcb is passed to the entry point in %edi
-	mov 0xc(%ebp), %edi
-
-	# Save a tiny bit of stack space
-	pop %ebp
-
-	jmp *%eax
Index: pace/srv/loader/arch/ia64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ia64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,30 +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.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/ia64.s
-AFLAGS += -xexplicit
Index: pace/srv/loader/arch/ia64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,64 +1,0 @@
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	/* On Itanium code sections must be aligned to 16 bytes. */
-	. = ALIGN(0x800000000 + SIZEOF_HEADERS, 16);
-	
-	.init : {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text);
-		*(.rodata*);
-	} :text
-	
-	. = . + 0x4000;
-	
-	.got : {
-		_gp = .;
-		*(.got*);
-	} :data
-	
-	.data : {
-		*(.opd);
-		*(.data .data.*);
-		*(.sdata);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(.sbss);
-		*(.scommon);
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: pace/srv/loader/arch/ia64/ia64.s
===================================================================
--- uspace/srv/loader/arch/ia64/ia64.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,43 +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.
-#
-
-.text
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# in0 (r32)	contains entry_point
-# in1 (r33)	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	# Pass pcb to the entry point in r2
-
-	mov b6 = r32
-	mov r2 = r33 ;;
-	br b6 ;;
Index: pace/srv/loader/arch/mips32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/mips32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,29 +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.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/mips32.s
Index: pace/srv/loader/arch/mips32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/mips32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,70 +1,0 @@
-/*
- * The only difference from _link.ld.in for regular statically-linked apps
- * is the base address.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70004000;
-	
-	.init ALIGN(0x4000) : SUBALIGN(0x4000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text);
-		*(.rodata*);
-	} :text
-	
-	. = . + 0x4000;
-	
-	.data : {
-		*(.data);
-		*(.data.rel*);
-	} :data
-	
-	.got : {
-		_gp = .;
-		*(.got);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.sbss : {
-		*(.scommon);
-		*(.sbss);
-	}
-	
-	.bss : {
-		*(.bss);
-		*(COMMON);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: pace/srv/loader/arch/mips32/mips32.s
===================================================================
--- uspace/srv/loader/arch/mips32/mips32.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,49 +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.
-#
-
-.text
-.section .text
-.global program_run
-.set noreorder
-
-## void program_run(void *entry_point, void *pcb);
-#
-# $a0 (=$4)	contains entry_point
-# $a1 (=$5)	contains pcb
-#
-# Jump to a program entry point
-.ent program_run
-program_run:
-	# tmp := entry_point
-	move $25, $a0
-
-	# Pass pcb to the entry point in $a0
-	move $a0, $a1
-	jr $25
-	nop
-.end
Index: pace/srv/loader/arch/mips32eb
===================================================================
--- uspace/srv/loader/arch/mips32eb	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,1 +1,0 @@
-mips32
Index: pace/srv/loader/arch/ppc32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ppc32/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,29 +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.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/ppc32.s
Index: pace/srv/loader/arch/ppc32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ppc32/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * The only difference from _link.ld.in for regular statically-linked apps
- * is the base address.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70001000;
-	
-	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text);
-		*(.rodata*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.data);
-		*(.sdata);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(.sbss);
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: pace/srv/loader/arch/ppc32/ppc32.s
===================================================================
--- uspace/srv/loader/arch/ppc32/ppc32.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,40 +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.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# %r3	contains entry_point
-# %r4	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	mtctr %r3
-	mr %r6, %r4	# Pass pcb to the entry point in %r6
-	bctr
Index: pace/srv/loader/arch/sparc64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/sparc64/Makefile.inc	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,29 +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.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/sparc64.s
Index: pace/srv/loader/arch/sparc64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/sparc64/_link.ld.in	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,61 +1,0 @@
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70004000 + SIZEOF_HEADERS;
-	
-	.init : {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text);
-		*(.rodata*);
-	} :text
-	
-	. = . + 0x4000;
-	
-	.got : {
-		 _gp = .;
-		 *(.got*);
-	} :data
-	
-	.data : {
-		*(.data);
-		*(.sdata);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(.sbss);
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: pace/srv/loader/arch/sparc64/sparc64.s
===================================================================
--- uspace/srv/loader/arch/sparc64/sparc64.s	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,42 +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.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# %o0	contains entry_point
-# %o1	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	# Pass pcb pointer to entry point in %o1. As it is already
-	# there, no action is needed.
-	call %o0
-	nop
-	# fixme: use branch instead of call
Index: pace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,477 +1,0 @@
-/*
- * Copyright (c) 2006 Sergey Bondari
- * Copyright (c) 2006 Jakub Jermar
- * 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 generic	
- * @{
- */
-
-/**
- * @file
- * @brief	Userspace ELF loader.
- *
- * This module allows loading ELF binaries (both executables and
- * shared objects) from VFS. The current implementation allocates
- * anonymous memory, fills it with segment data and then adjusts
- * the memory areas' flags to the final value. In the future,
- * the segments will be mapped directly from the file.
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <align.h>
-#include <assert.h>
-#include <as.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <smc.h>
-#include <loader/pcb.h>
-
-#include "elf.h"
-#include "elf_load.h"
-#include "arch.h"
-
-#define DPRINTF(...)
-
-static const char *error_codes[] = {
-	"no error",
-	"invalid image",
-	"address space error",
-	"incompatible image",
-	"unsupported image type",
-	"irrecoverable error"
-};
-
-static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
-static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
-static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
-static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
-
-/** Read until the buffer is read in its entirety. */
-static int my_read(int fd, void *buf, size_t len)
-{
-	int cnt = 0;
-	do {
-		buf += cnt;
-		len -= cnt;
-		cnt = read(fd, buf, len);
-	} while ((cnt > 0) && ((len - cnt) > 0));
-
-	return cnt;
-}
-
-/** Load ELF binary from a file.
- *
- * Load an ELF binary from the specified file. If the file is
- * an executable program, it is loaded unbiased. If it is a shared
- * object, it is loaded with the bias @a so_bias. Some information
- * extracted from the binary is stored in a elf_info_t structure
- * pointed to by @a info.
- *
- * @param file_name Path to the ELF file.
- * @param so_bias   Bias to use if the file is a shared object.
- * @param info      Pointer to a structure for storing information
- *                  extracted from the binary.
- *
- * @return EOK on success or negative error code.
- *
- */
-int elf_load_file(const char *file_name, size_t so_bias, elf_info_t *info)
-{
-	elf_ld_t elf;
-
-	int fd;
-	int rc;
-	
-	fd = open(file_name, O_RDONLY);
-	if (fd < 0) {
-		DPRINTF("failed opening file\n");
-		return -1;
-	}
-
-	elf.fd = fd;
-	elf.info = info;
-
-	rc = elf_load(&elf, so_bias);
-
-	close(fd);
-
-	return rc;
-}
-
-/** Run an ELF executable.
- *
- * Transfers control to the entry point of an ELF executable loaded
- * earlier with elf_load_file(). This function does not return.
- *
- * @param info Info structure filled earlier by elf_load_file()
- *
- */
-void elf_run(elf_info_t *info, pcb_t *pcb)
-{
-	program_run(info->entry, pcb);
-
-	/* not reached */
-}
-
-/** Create the program control block (PCB).
- *
- * Fills the program control block @a pcb with information from
- * @a info.
- *
- * @param info	Program info structure
- * @return EOK on success or negative error code
- */
-void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
-{
-	pcb->entry = info->entry;
-	pcb->dynamic = info->dynamic;
-}
-
-
-/** Load an ELF binary.
- *
- * The @a elf structure contains the loader state, including
- * an open file, from which the binary will be loaded,
- * a pointer to the @c info structure etc.
- *
- * @param elf		Pointer to loader state buffer.
- * @param so_bias	Bias to use if the file is a shared object.
- * @return EE_OK on success or EE_xx error code.
- */
-static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
-{
-	elf_header_t header_buf;
-	elf_header_t *header = &header_buf;
-	int i, rc;
-
-	rc = my_read(elf->fd, header, sizeof(elf_header_t));
-	if (rc < 0) {
-		DPRINTF("Read error.\n"); 
-		return EE_INVALID;
-	}
-
-	elf->header = header;
-
-	/* Identify ELF */
-	if (header->e_ident[EI_MAG0] != ELFMAG0 ||
-	    header->e_ident[EI_MAG1] != ELFMAG1 || 
-	    header->e_ident[EI_MAG2] != ELFMAG2 ||
-	    header->e_ident[EI_MAG3] != ELFMAG3) {
-		DPRINTF("Invalid header.\n");
-		return EE_INVALID;
-	}
-	
-	/* Identify ELF compatibility */
-	if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
-	    header->e_machine != ELF_MACHINE || 
-	    header->e_ident[EI_VERSION] != EV_CURRENT ||
-	    header->e_version != EV_CURRENT ||
-	    header->e_ident[EI_CLASS] != ELF_CLASS) {
-		DPRINTF("Incompatible data/version/class.\n");
-		return EE_INCOMPATIBLE;
-	}
-
-	if (header->e_phentsize != sizeof(elf_segment_header_t)) {
-		DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
-		    sizeof(elf_segment_header_t));
-		return EE_INCOMPATIBLE;
-	}
-
-	if (header->e_shentsize != sizeof(elf_section_header_t)) {
-		DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
-		    sizeof(elf_section_header_t));
-		return EE_INCOMPATIBLE;
-	}
-
-	/* Check if the object type is supported. */
-	if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
-		DPRINTF("Object type %d is not supported\n", header->e_type);
-		return EE_UNSUPPORTED;
-	}
-
-	/* Shared objects can be loaded with a bias */
-	if (header->e_type == ET_DYN)
-		elf->bias = so_bias;
-	else
-		elf->bias = 0;
-
-	elf->info->interp = NULL;
-	elf->info->dynamic = NULL;
-
-	/* Walk through all segment headers and process them. */
-	for (i = 0; i < header->e_phnum; i++) {
-		elf_segment_header_t segment_hdr;
-
-		/* Seek to start of segment header */
-		lseek(elf->fd, header->e_phoff
-		        + i * sizeof(elf_segment_header_t), SEEK_SET);
-
-		rc = my_read(elf->fd, &segment_hdr,
-		    sizeof(elf_segment_header_t));
-		if (rc < 0) {
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		rc = segment_header(elf, &segment_hdr);
-		if (rc != EE_OK)
-			return rc;
-	}
-
-	DPRINTF("Parse sections.\n");
-
-	/* Inspect all section headers and proccess them. */
-	for (i = 0; i < header->e_shnum; i++) {
-		elf_section_header_t section_hdr;
-
-		/* Seek to start of section header */
-		lseek(elf->fd, header->e_shoff
-		    + i * sizeof(elf_section_header_t), SEEK_SET);
-
-		rc = my_read(elf->fd, &section_hdr,
-		    sizeof(elf_section_header_t));
-		if (rc < 0) {
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		rc = section_header(elf, &section_hdr);
-		if (rc != EE_OK)
-			return rc;
-	}
-
-	elf->info->entry =
-	    (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
-
-	DPRINTF("Done.\n");
-
-	return EE_OK;
-}
-
-/** Print error message according to error code.
- *
- * @param rc Return code returned by elf_load().
- *
- * @return NULL terminated description of error.
- */
-const char *elf_error(unsigned int rc)
-{
-	assert(rc < sizeof(error_codes) / sizeof(char *));
-
-	return error_codes[rc];
-}
-
-/** Process segment header.
- *
- * @param entry	Segment header.
- *
- * @return EE_OK on success, error code otherwise.
- */
-static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
-{
-	switch (entry->p_type) {
-	case PT_NULL:
-	case PT_PHDR:
-	case PT_NOTE:
-		break;
-	case PT_LOAD:
-		return load_segment(elf, entry);
-		break;
-	case PT_INTERP:
-		/* Assume silently interp == "/rtld.so" */
-		elf->info->interp = "/rtld.so";
-		break;
-	case PT_DYNAMIC:
-	case PT_SHLIB:
-	case PT_LOPROC:
-	case PT_HIPROC:
-	default:
-		DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
-		return EE_UNSUPPORTED;
-		break;
-	}
-	return EE_OK;
-}
-
-/** Load segment described by program header entry.
- *
- * @param elf	Loader state.
- * @param entry Program header entry describing segment to be loaded.
- *
- * @return EE_OK on success, error code otherwise.
- */
-int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
-{
-	void *a;
-	int flags = 0;
-	uintptr_t bias;
-	uintptr_t base;
-	void *seg_ptr;
-	uintptr_t seg_addr;
-	size_t mem_sz;
-	int rc;
-
-	bias = elf->bias;
-
-	seg_addr = entry->p_vaddr + bias;
-	seg_ptr = (void *) seg_addr;
-
-	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
-		entry->p_memsz);
-
-	if (entry->p_align > 1) {
-		if ((entry->p_offset % entry->p_align) !=
-		    (seg_addr % entry->p_align)) {
-			DPRINTF("Align check 1 failed offset%%align=%d, "
-			    "vaddr%%align=%d\n",
-			    entry->p_offset % entry->p_align,
-			    seg_addr % entry->p_align
-			);
-			return EE_INVALID;
-		}
-	}
-
-	/* Final flags that will be set for the memory area */
-
-	if (entry->p_flags & PF_X)
-		flags |= AS_AREA_EXEC;
-	if (entry->p_flags & PF_W)
-		flags |= AS_AREA_WRITE;
-	if (entry->p_flags & PF_R)
-		flags |= AS_AREA_READ;
-	flags |= AS_AREA_CACHEABLE;
-	
-	base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
-	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
-
-	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
-	    (void *) (entry->p_vaddr + bias +
-	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
-
-	/*
-	 * For the course of loading, the area needs to be readable
-	 * and writeable.
-	 */
-	a = as_area_create((uint8_t *)base + bias, mem_sz,
-	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
-	if (a == (void *)(-1)) {
-		DPRINTF("Memory mapping failed.\n");
-		return EE_MEMORY;
-	}
-
-	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
-	    (void *) (base + bias), mem_sz, flags, (void *) a);
-
-	/*
-	 * Load segment data
-	 */
-	rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
-	if (rc < 0) {
-		printf("seek error\n");
-		return EE_INVALID;
-	}
-
-/*	rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
-	if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
-
-	/* Long reads are not possible yet. Load segment piecewise. */
-
-	unsigned left, now;
-	uint8_t *dp;
-
-	left = entry->p_filesz;
-	dp = seg_ptr;
-
-	while (left > 0) {
-		now = 16384;
-		if (now > left) now = left;
-
-		rc = my_read(elf->fd, dp, now);
-
-		if (rc < 0) { 
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		left -= now;
-		dp += now;
-	}
-
-	rc = as_area_change_flags(seg_ptr, flags);
-	if (rc != 0) {
-		DPRINTF("Failed to set memory area flags.\n");
-		return EE_MEMORY;
-	}
-
-	if (flags & AS_AREA_EXEC) {
-		/* Enforce SMC coherence for the segment */
-		if (smc_coherence(seg_ptr, entry->p_filesz))
-			return EE_MEMORY;
-	}
-
-	return EE_OK;
-}
-
-/** Process section header.
- *
- * @param elf	Loader state.
- * @param entry Segment header.
- *
- * @return EE_OK on success, error code otherwise.
- */
-static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
-{
-	switch (entry->sh_type) {
-	case SHT_PROGBITS:
-		if (entry->sh_flags & SHF_TLS) {
-			/* .tdata */
-		}
-		break;
-	case SHT_NOBITS:
-		if (entry->sh_flags & SHF_TLS) {
-			/* .tbss */
-		}
-		break;
-	case SHT_DYNAMIC:
-		/* Record pointer to dynamic section into info structure */
-		elf->info->dynamic =
-		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
-		DPRINTF("Dynamic section found at %p.\n",
-		    (void *) elf->info->dynamic);
-		break;
-	default:
-		break;
-	}
-	
-	return EE_OK;
-}
-
-/** @}
- */
Index: pace/srv/loader/include/arch.h
===================================================================
--- uspace/srv/loader/include/arch.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,45 +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 fs
- * @{
- */
-/** @file
- * @brief
- */
-
-#ifndef LOADER_ARCH_H_
-#define LOADER_ARCH_H_
-
-extern void program_run(void *entry_point, void *pcb);
-
-#endif
-
-/**
- * @}
- */
Index: pace/srv/loader/include/elf.h
===================================================================
--- uspace/srv/loader/include/elf.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,344 +1,0 @@
-/*
- * Copyright (c) 2006 Sergey Bondari
- * 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 ELF_H_
-#define ELF_H_
-
-#include <arch/elf.h>
-#include <sys/types.h>
-
-/**
- * current ELF version
- */
-#define	EV_CURRENT	1
-
-/** 
- * ELF types 
- */
-#define ET_NONE		0	/* No type */
-#define ET_REL		1	/* Relocatable file */
-#define ET_EXEC		2	/* Executable */
-#define ET_DYN		3	/* Shared object */
-#define ET_CORE		4	/* Core */
-#define ET_LOPROC	0xff00	/* Processor specific */
-#define ET_HIPROC	0xffff	/* Processor specific */
-
-/** 
- * ELF machine types
- */
-#define EM_NO		0	/* No machine */
-#define EM_SPARC	2	/* SPARC */
-#define EM_386		3	/* i386 */
-#define EM_MIPS		8	/* MIPS RS3000 */
-#define EM_MIPS_RS3_LE	10	/* MIPS RS3000 LE */
-#define EM_PPC		20	/* PPC32 */
-#define EM_PPC64	21	/* PPC64 */
-#define EM_ARM		40	/* ARM */
-#define EM_SPARCV9	43	/* SPARC64 */
-#define EM_IA_64	50	/* IA-64 */
-#define EM_X86_64	62	/* AMD64/EMT64 */
-
-/**
- * ELF identification indexes
- */
-#define EI_MAG0		0
-#define EI_MAG1		1
-#define EI_MAG2		2
-#define EI_MAG3		3
-#define EI_CLASS	4		/* File class */
-#define EI_DATA		5		/* Data encoding */
-#define EI_VERSION	6		/* File version */
-#define EI_OSABI	7
-#define EI_ABIVERSION	8
-#define EI_PAD		9		/* Start of padding bytes */
-#define EI_NIDENT	16		/* ELF identification table size */
-
-/**
- * ELF magic number
- */
-#define ELFMAG0		0x7f
-#define ELFMAG1		'E'
-#define ELFMAG2		'L'
-#define ELFMAG3		'F'
-
-/**
- * ELF file classes
- */
-#define ELFCLASSNONE	0
-#define ELFCLASS32	1
-#define ELFCLASS64	2
-
-/**
- * ELF data encoding types
- */
-#define ELFDATANONE	0
-#define ELFDATA2LSB	1		/* Least significant byte first (little endian) */
-#define ELFDATA2MSB	2		/* Most signigicant byte first (big endian) */
-
-/**
- * ELF error return codes
- */
-#define EE_OK			0	/* No error */
-#define EE_INVALID		1	/* Invalid ELF image */
-#define	EE_MEMORY		2	/* Cannot allocate address space */
-#define EE_INCOMPATIBLE		3	/* ELF image is not compatible with current architecture */
-#define EE_UNSUPPORTED		4	/* Non-supported ELF (e.g. dynamic ELFs) */
-#define EE_IRRECOVERABLE	5
-
-/**
- * ELF section types
- */
-#define SHT_NULL		0
-#define SHT_PROGBITS		1
-#define SHT_SYMTAB		2
-#define SHT_STRTAB		3
-#define SHT_RELA		4
-#define SHT_HASH		5
-#define SHT_DYNAMIC		6
-#define SHT_NOTE		7
-#define SHT_NOBITS		8
-#define SHT_REL			9
-#define SHT_SHLIB		10
-#define SHT_DYNSYM		11
-#define SHT_LOOS		0x60000000
-#define SHT_HIOS		0x6fffffff
-#define SHT_LOPROC		0x70000000
-#define SHT_HIPROC		0x7fffffff
-#define SHT_LOUSER		0x80000000
-#define SHT_HIUSER		0xffffffff
-
-/**
- * ELF section flags
- */
-#define SHF_WRITE		0x1 
-#define SHF_ALLOC		0x2
-#define SHF_EXECINSTR		0x4
-#define SHF_TLS			0x400
-#define SHF_MASKPROC		0xf0000000
-
-/**
- * Symbol binding
- */
-#define STB_LOCAL		0
-#define STB_GLOBAL		1
-#define STB_WEAK		2
-#define STB_LOPROC		13
-#define STB_HIPROC		15
-
-/**
- * Symbol types
- */
-#define STT_NOTYPE		0
-#define STT_OBJECT		1
-#define STT_FUNC		2
-#define STT_SECTION		3
-#define STT_FILE		4
-#define STT_LOPROC		13
-#define STT_HIPROC		15
-
-/**
- * Program segment types
- */
-#define PT_NULL			0
-#define PT_LOAD			1
-#define PT_DYNAMIC		2
-#define PT_INTERP		3
-#define PT_NOTE			4
-#define PT_SHLIB		5
-#define PT_PHDR			6
-#define PT_LOPROC		0x70000000
-#define PT_HIPROC		0x7fffffff
-
-/**
- * Program segment attributes.
- */
-#define PF_X	1
-#define PF_W	2
-#define PF_R	4
-
-/**
- * ELF data types
- *
- * These types are found to be identical in both 32-bit and 64-bit
- * ELF object file specifications. They are the only types used
- * in ELF header.
- */
-typedef uint64_t elf_xword;
-typedef int64_t elf_sxword;
-typedef uint32_t elf_word;
-typedef int32_t elf_sword;
-typedef uint16_t elf_half;
-
-/**
- * 32-bit ELF data types.
- *
- * These types are specific for 32-bit format.
- */
-typedef uint32_t elf32_addr;
-typedef uint32_t elf32_off;
-
-/**
- * 64-bit ELF data types.
- *
- * These types are specific for 64-bit format.
- */
-typedef uint64_t elf64_addr;
-typedef uint64_t elf64_off;
-
-/** ELF header */
-struct elf32_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf32_addr e_entry;
-	elf32_off e_phoff;
-	elf32_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-struct elf64_header {
-	uint8_t e_ident[EI_NIDENT];
-	elf_half e_type;
-	elf_half e_machine;
-	elf_word e_version;
-	elf64_addr e_entry;
-	elf64_off e_phoff;
-	elf64_off e_shoff;
-	elf_word e_flags;
-	elf_half e_ehsize;
-	elf_half e_phentsize;
-	elf_half e_phnum;
-	elf_half e_shentsize;
-	elf_half e_shnum;
-	elf_half e_shstrndx;
-};
-
-/*
- * ELF segment header.
- * Segments headers are also known as program headers.
- */
-struct elf32_segment_header {
-	elf_word p_type;
-	elf32_off p_offset;
-	elf32_addr p_vaddr;
-	elf32_addr p_paddr;
-	elf_word p_filesz;
-	elf_word p_memsz;
-	elf_word p_flags;
-	elf_word p_align;
-};
-struct elf64_segment_header {
-	elf_word p_type;
-	elf_word p_flags;
-	elf64_off p_offset;
-	elf64_addr p_vaddr;
-	elf64_addr p_paddr;
-	elf_xword p_filesz;
-	elf_xword p_memsz;
-	elf_xword p_align;
-};
-
-/*
- * ELF section header
- */
-struct elf32_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_word sh_flags;
-	elf32_addr sh_addr;
-	elf32_off sh_offset;
-	elf_word sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_word sh_addralign;
-	elf_word sh_entsize;
-};
-struct elf64_section_header {
-	elf_word sh_name;
-	elf_word sh_type;
-	elf_xword sh_flags;
-	elf64_addr sh_addr;
-	elf64_off sh_offset;
-	elf_xword sh_size;
-	elf_word sh_link;
-	elf_word sh_info;
-	elf_xword sh_addralign;
-	elf_xword sh_entsize;
-};
-
-/*
- * ELF symbol table entry
- */
-struct elf32_symbol {
-	elf_word st_name;
-	elf32_addr st_value;
-	elf_word st_size;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-};
-struct elf64_symbol {
-	elf_word st_name;
-	uint8_t st_info;
-	uint8_t st_other;
-	elf_half st_shndx;
-	elf64_addr st_value;
-	elf_xword st_size;
-};
-
-#ifdef __32_BITS__ 
-typedef struct elf32_header elf_header_t;
-typedef struct elf32_segment_header elf_segment_header_t;
-typedef struct elf32_section_header elf_section_header_t;
-typedef struct elf32_symbol elf_symbol_t;
-#endif
-#ifdef __64_BITS__
-typedef struct elf64_header elf_header_t;
-typedef struct elf64_segment_header elf_segment_header_t;
-typedef struct elf64_section_header elf_section_header_t;
-typedef struct elf64_symbol elf_symbol_t;
-#endif
-
-extern const char *elf_error(unsigned int rc);
-
-#endif
-
-/** @}
- */
Index: pace/srv/loader/include/elf_load.h
===================================================================
--- uspace/srv/loader/include/elf_load.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ 	(revision )
@@ -1,83 +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 generic
- * @{
- */
-/** @file
- * @brief ELF loader structures and public functions.
- */
-
-#ifndef ELF_LOAD_H_
-#define ELF_LOAD_H_
-
-#include <arch/elf.h>
-#include <sys/types.h>
-#include <loader/pcb.h>
-
-#include "elf.h"
-
-/**
- * Some data extracted from the headers are stored here
- */
-typedef struct {
-	/** Entry point */
-	entry_point_t entry;
-
-	/** ELF interpreter name or NULL if statically-linked */
-	const char *interp;
-
-	/** Pointer to the dynamic section */
-	void *dynamic;
-} elf_info_t;
-
-/**
- * Holds information about an ELF binary being loaded.
- */
-typedef struct {
-	/** Filedescriptor of the file from which we are loading */
-	int fd;
-
-	/** Difference between run-time addresses and link-time addresses */
-	uintptr_t bias;
-
-	/** A copy of the ELF file header */
-	elf_header_t *header;
-
-	/** Store extracted info here */
-	elf_info_t *info;
-} elf_ld_t;
-
-int elf_load_file(const char *file_name, size_t so_bias, elf_info_t *info);
-void elf_run(elf_info_t *info, pcb_t *pcb);
-void elf_create_pcb(elf_info_t *info, pcb_t *pcb);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/loader/main.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,14 +52,22 @@
 #include <ipc/services.h>
 #include <ipc/loader.h>
-#include <ipc/ns.h>
-#include <macros.h>
+#include <ns.h>
 #include <loader/pcb.h>
+#include <entry_point.h>
 #include <errno.h>
 #include <async.h>
 #include <str.h>
 #include <as.h>
-
-#include <elf.h>
-#include <elf_load.h>
+#include <elf/elf.h>
+#include <elf/elf_load.h>
+#include <vfs/vfs.h>
+
+#ifdef CONFIG_RTLD
+#include <rtld/rtld.h>
+#include <rtld/dynamic.h>
+#include <rtld/module.h>
+
+static int ldr_load_dyn_linked(elf_info_t *p_info);
+#endif
 
 #define DPRINTF(...)
@@ -82,17 +90,16 @@
 
 /** Number of preset files */
-static int filc = 0;
-/** Preset files vector */
-static fdi_node_t **filv = NULL;
-/** Buffer holding all preset files */
-static fdi_node_t *fil_buf = NULL;
+static unsigned int filc = 0;
 
 static elf_info_t prog_info;
-static elf_info_t interp_info;
-
-static bool is_dyn_linked;
 
 /** Used to limit number of connections to one. */
 static bool connected = false;
+
+#ifdef CONFIG_RTLD
+/** State structure of the dynamic linker. */
+runtime_env_t dload_re;
+static module_t prog_mod;
+#endif
 
 static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
@@ -229,45 +236,23 @@
 static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
 {
-	fdi_node_t *buf;
-	size_t buf_size;
-	int rc = async_data_write_accept((void **) &buf, false, 0, 0,
-	    sizeof(fdi_node_t), &buf_size);
-	
-	if (rc == EOK) {
-		int count = buf_size / sizeof(fdi_node_t);
-		
-		/*
-		 * Allocate new filv
-		 */
-		fdi_node_t **_filv = (fdi_node_t **) calloc(count + 1, sizeof(fdi_node_t *));
-		if (_filv == NULL) {
-			free(buf);
-			async_answer_0(rid, ENOMEM);
-			return;
+	size_t count = IPC_GET_ARG1(*request);
+
+	async_exch_t *vfs_exch = vfs_exchange_begin();
+
+	for (filc = 0; filc < count; filc++) {
+		ipc_callid_t callid;
+		int fd;
+
+		if (!async_state_change_receive(&callid, NULL, NULL, NULL)) {
+			async_answer_0(callid, EINVAL);
+			break;
 		}
-		
-		/*
-		 * Fill the new filv with argument pointers
-		 */
-		int i;
-		for (i = 0; i < count; i++)
-			_filv[i] = &buf[i];
-		
-		_filv[count] = NULL;
-		
-		/*
-		 * Copy temporary data to global variables
-		 */
-		if (fil_buf != NULL)
-			free(fil_buf);
-		
-		if (filv != NULL)
-			free(filv);
-		
-		filc = count;
-		fil_buf = buf;
-		filv = _filv;
-	}
-	
+		async_state_change_finalize(callid, vfs_exch);
+		fd = fd_wait();
+		assert(fd == (int) filc);
+	}
+
+	vfs_exchange_end(vfs_exch);
+
 	async_answer_0(rid, EOK);
 }
@@ -283,5 +268,5 @@
 	int rc;
 	
-	rc = elf_load_file(pathname, 0, &prog_info);
+	rc = elf_load_file(pathname, 0, 0, &prog_info);
 	if (rc != EE_OK) {
 		DPRINTF("Failed to load executable '%s'.\n", pathname);
@@ -298,27 +283,73 @@
 	
 	pcb.filc = filc;
-	pcb.filv = filv;
 	
 	if (prog_info.interp == NULL) {
 		/* Statically linked program */
-		is_dyn_linked = false;
 		async_answer_0(rid, EOK);
 		return 0;
 	}
 	
-	rc = elf_load_file(prog_info.interp, 0, &interp_info);
-	if (rc != EE_OK) {
-		DPRINTF("Failed to load interpreter '%s.'\n",
-		    prog_info.interp);
-		async_answer_0(rid, EINVAL);
-		return 1;
-	}
-	
-	is_dyn_linked = true;
-	async_answer_0(rid, EOK);
-	
+	DPRINTF("Binary is dynamically linked.\n");
+#ifdef CONFIG_RTLD
+	DPRINTF(" - pcb address: %p\n", &pcb);
+	DPRINTF( "- prog dynamic: %p\n", prog_info.dynamic);
+
+	rc = ldr_load_dyn_linked(&prog_info);
+#else
+	rc = ENOTSUP;
+#endif
+	async_answer_0(rid, rc);
 	return 0;
 }
 
+#ifdef CONFIG_RTLD
+
+static int ldr_load_dyn_linked(elf_info_t *p_info)
+{
+	runtime_env = &dload_re;
+
+	DPRINTF("Load dynamically linked program.\n");
+
+	/*
+	 * First we need to process dynamic sections of the executable
+	 * program and insert it into the module graph.
+	 */
+
+	DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
+	dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
+	prog_mod.bias = 0;
+	prog_mod.dyn.soname = "[program]";
+
+	/* Initialize list of loaded modules */
+	list_initialize(&runtime_env->modules);
+	list_append(&prog_mod.modules_link, &runtime_env->modules);
+
+	/* Pointer to program module. Used as root of the module graph. */
+	runtime_env->program = &prog_mod;
+
+	/* Work around non-existent memory space allocation. */
+	runtime_env->next_bias = 0x1000000;
+
+	/*
+	 * Now we can continue with loading all other modules.
+	 */
+
+	DPRINTF("Load all program dependencies\n");
+	module_load_deps(&prog_mod);
+
+	/*
+	 * Now relocate/link all modules together.
+	 */
+
+	/* Process relocations in all modules */
+	DPRINTF("Relocate all modules\n");
+	modules_process_relocs(&prog_mod);
+
+	/* Pass runtime evironment pointer through PCB. */
+	pcb.rtld_runtime = (void *) runtime_env;
+
+	return 0;
+}
+#endif
 
 /** Run the previously loaded program.
@@ -332,4 +363,6 @@
 	const char *cp;
 	
+	DPRINTF("Set task name\n");
+
 	/* Set the task name. */
 	cp = str_rchr(pathname, '/');
@@ -337,16 +370,9 @@
 	task_set_name(cp);
 	
-	if (is_dyn_linked == true) {
-		/* Dynamically linked program */
-		DPRINTF("Run ELF interpreter.\n");
-		DPRINTF("Entry point: %p\n", interp_info.entry);
-		
-		async_answer_0(rid, EOK);
-		elf_run(&interp_info, &pcb);
-	} else {
-		/* Statically linked program */
-		async_answer_0(rid, EOK);
-		elf_run(&prog_info, &pcb);
-	}
+	/* Run program */
+	DPRINTF("Reply OK\n");
+	async_answer_0(rid, EOK);
+	DPRINTF("Jump to entry point at %p\n", pcb.entry);
+	entry_point_jmp(prog_info.entry, &pcb);
 	
 	/* Not reached */
@@ -358,10 +384,6 @@
  * to execute the loaded program).
  */
-static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-	
+static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
 	/* Already have a connection? */
 	if (connected) {
@@ -376,13 +398,15 @@
 	
 	/* Ignore parameters, the connection is already open */
-	(void) iid;
 	(void) icall;
 	
-	while (1) {
-		callid = async_get_call(&call);
+	while (true) {
+		int retval;
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			exit(0);
 		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			exit(0);
 		case LOADER_GET_TASKID:
 			ldr_get_taskid(callid, &call);
@@ -407,12 +431,9 @@
 			/* Not reached */
 		default:
-			retval = ENOENT;
+			retval = EINVAL;
 			break;
 		}
-		if (IPC_GET_IMETHOD(call) != IPC_M_PHONE_HUNGUP) {
-			DPRINTF("Responding EINVAL to method %d.\n",
-			    IPC_GET_IMETHOD(call));
-			async_answer_0(callid, EINVAL);
-		}
+		
+		async_answer_0(callid, retval);
 	}
 }
@@ -427,5 +448,5 @@
 	/* Introduce this task to the NS (give it our task ID). */
 	task_id_t id = task_get_id();
-	int rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
+	int rc = ns_intro(id);
 	if (rc != EOK)
 		return -1;
Index: uspace/srv/loc/Makefile
===================================================================
--- uspace/srv/loc/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/loc/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+BINARY = loc
+STATIC_NEEDED = y
+
+SOURCES = \
+	category.c \
+	loc.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/loc/category.c
===================================================================
--- uspace/srv/loc/category.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/loc/category.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup loc
+ * @{
+ */
+/** @file Categories for location service.
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "category.h"
+#include "loc.h"
+
+/** Initialize category directory. */
+void categ_dir_init(categ_dir_t *cdir)
+{
+	fibril_mutex_initialize(&cdir->mutex);
+	list_initialize(&cdir->categories);
+}
+
+/** Add new category to directory. */
+void categ_dir_add_cat(categ_dir_t *cdir, category_t *cat)
+{
+	list_append(&cat->cat_list, &cdir->categories);
+}
+
+/** Get list of categories. */
+int categ_dir_get_categories(categ_dir_t *cdir, category_id_t *id_buf,
+    size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_mutex_is_locked(&cdir->mutex));
+
+	buf_cnt = buf_size / sizeof(category_id_t);
+
+	act_cnt = list_count(&cdir->categories);
+	*act_size = act_cnt * sizeof(category_id_t);
+
+	if (buf_size % sizeof(category_id_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(cdir->categories, item) {
+		category_t *cat =
+		    list_get_instance(item, category_t, cat_list);
+
+		if (pos < buf_cnt)
+			id_buf[pos] = cat->id;
+		pos++;
+	}
+
+	return EOK;
+}
+
+
+/** Initialize category structure. */
+static void category_init(category_t *cat, const char *name)
+{
+	fibril_mutex_initialize(&cat->mutex);
+	cat->name = str_dup(name);
+	cat->id = loc_create_id();
+	link_initialize(&cat->cat_list);
+	list_initialize(&cat->svc_memb);
+}
+
+/** Allocate new category. */
+category_t *category_new(const char *name)
+{
+	category_t *cat;
+
+	cat = malloc(sizeof(category_t));
+	if (cat == NULL)
+		return NULL;
+
+	category_init(cat, name);
+	return cat;
+}
+
+/** Add service to category. */
+int category_add_service(category_t *cat, loc_service_t *svc)
+{
+	assert(fibril_mutex_is_locked(&cat->mutex));
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	/* Verify that category does not contain this service yet. */
+	list_foreach(cat->svc_memb, item) {
+		svc_categ_t *memb = list_get_instance(item, svc_categ_t,
+		    cat_link);
+		if (memb->svc == svc) {
+			return EEXIST;
+		}
+	}
+
+	svc_categ_t *nmemb = malloc(sizeof(svc_categ_t));
+	if (nmemb == NULL)
+		return ENOMEM;
+
+	nmemb->svc = svc;
+	nmemb->cat = cat;
+
+	list_append(&nmemb->cat_link, &cat->svc_memb);
+	list_append(&nmemb->svc_link, &svc->cat_memb);
+
+	return EOK;
+}
+
+/** Remove service from category. */
+void category_remove_service(svc_categ_t *memb)
+{
+	assert(fibril_mutex_is_locked(&memb->cat->mutex));
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	list_remove(&memb->cat_link);
+	list_remove(&memb->svc_link);
+
+	free(memb);
+}
+
+/** Get category by ID. */
+category_t *category_get(categ_dir_t *cdir, catid_t catid)
+{
+	assert(fibril_mutex_is_locked(&cdir->mutex));
+
+	list_foreach(cdir->categories, item) {
+		category_t *cat = list_get_instance(item, category_t,
+		    cat_list);
+		if (cat->id == catid)
+			return cat;
+	}
+
+	return NULL;
+}
+
+/** Find category by name. */
+category_t *category_find_by_name(categ_dir_t *cdir, const char *name)
+{
+	assert(fibril_mutex_is_locked(&cdir->mutex));
+
+	list_foreach(cdir->categories, item) {
+		category_t *cat = list_get_instance(item, category_t,
+		    cat_list);
+		if (str_cmp(cat->name, name) == 0)
+			return cat;
+	}
+
+	return NULL;
+}
+
+/** Get list of services in category. */
+int category_get_services(category_t *cat, service_id_t *id_buf,
+    size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_mutex_is_locked(&cat->mutex));
+
+	buf_cnt = buf_size / sizeof(service_id_t);
+
+	act_cnt = list_count(&cat->svc_memb);
+	*act_size = act_cnt * sizeof(service_id_t);
+
+	if (buf_size % sizeof(service_id_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(cat->svc_memb, item) {
+		svc_categ_t *memb =
+		    list_get_instance(item, svc_categ_t, cat_link);
+
+		if (pos < buf_cnt)
+			id_buf[pos] = memb->svc->id;
+		pos++;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/loc/category.h
===================================================================
--- uspace/srv/loc/category.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/loc/category.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup loc
+ * @{
+ */
+/** @file Categories for location service.
+ */
+
+#ifndef CATEGORY_H_
+#define CATEGORY_H_
+
+#include <adt/list.h>
+#include "loc.h"
+
+typedef sysarg_t catid_t;
+
+/** Service category */
+typedef struct {
+	/** Protects this structure, list of services */
+	fibril_mutex_t mutex;
+
+	/** Identifier */
+	catid_t id;
+
+	/** Category name */
+	const char *name;
+
+	/** Link to list of categories (categ_dir_t.categories) */
+	link_t cat_list;
+
+	/** List of service memberships in this category (svc_categ_t) */
+	list_t svc_memb;
+} category_t;
+
+/** Service directory ogranized by categories (yellow pages) */
+typedef struct {
+	/** Protects this structure, list of categories */
+	fibril_mutex_t mutex;
+	/** List of all categories (category_t) */
+	list_t categories;
+} categ_dir_t;
+
+/** Service in category membership. */
+typedef struct {
+	/** Link to category_t.svc_memb list */
+	link_t cat_link;
+	/** Link to loc_service_t.cat_memb list */
+	link_t svc_link;
+	
+	/** Category */
+	category_t *cat;
+	/** Service */
+	loc_service_t *svc;
+} svc_categ_t;
+
+extern void categ_dir_init(categ_dir_t *);
+extern void categ_dir_add_cat(categ_dir_t *, category_t *);
+extern int categ_dir_get_categories(categ_dir_t *, service_id_t *, size_t,
+    size_t *);
+extern category_t *category_new(const char *);
+extern int category_add_service(category_t *, loc_service_t *);
+extern void category_remove_service(svc_categ_t *);
+extern category_t *category_get(categ_dir_t *, catid_t);
+extern category_t *category_find_by_name(categ_dir_t *, const char *);
+extern int category_get_services(category_t *, service_id_t *, size_t,
+    size_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/loc/loc.c
===================================================================
--- uspace/srv/loc/loc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/loc/loc.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,1457 @@
+/*
+ * Copyright (c) 2007 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @defgroup loc Location Service.
+ * @brief HelenOS location service.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <stdio.h>
+#include <errno.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <macros.h>
+#include <stdlib.h>
+#include <str.h>
+#include <ipc/loc.h>
+#include <assert.h>
+
+#include "category.h"
+#include "loc.h"
+
+#define NAME          "loc"
+#define NULL_SERVICES  256
+
+LIST_INITIALIZE(services_list);
+LIST_INITIALIZE(namespaces_list);
+LIST_INITIALIZE(servers_list);
+
+/* Locking order:
+ *  servers_list_mutex
+ *  services_list_mutex
+ *  (loc_server_t *)->services_mutex
+ *  create_id_mutex
+ **/
+
+FIBRIL_MUTEX_INITIALIZE(services_list_mutex);
+static FIBRIL_CONDVAR_INITIALIZE(services_list_cv);
+static FIBRIL_MUTEX_INITIALIZE(servers_list_mutex);
+static FIBRIL_MUTEX_INITIALIZE(create_id_mutex);
+static FIBRIL_MUTEX_INITIALIZE(null_services_mutex);
+
+static service_id_t last_id = 0;
+static loc_service_t *null_services[NULL_SERVICES];
+
+/*
+ * Dummy list for null services. This is necessary so that null services can
+ * be used just as any other services, e.g. in loc_service_unregister_core().
+ */
+static LIST_INITIALIZE(dummy_null_services);
+
+/** Service directory ogranized by categories (yellow pages) */
+static categ_dir_t cdir;
+
+static FIBRIL_MUTEX_INITIALIZE(callback_sess_mutex);
+static async_sess_t *callback_sess = NULL;
+
+service_id_t loc_create_id(void)
+{
+	/* TODO: allow reusing old ids after their unregistration
+	 * and implement some version of LRU algorithm, avoid overflow
+	 */
+	
+	fibril_mutex_lock(&create_id_mutex);
+	last_id++;
+	fibril_mutex_unlock(&create_id_mutex);
+	
+	return last_id;
+}
+
+/** Convert fully qualified service name to namespace and service name.
+ *
+ * A fully qualified service name can be either a plain service name
+ * (then the namespace is considered to be an empty string) or consist
+ * of two components separated by a slash. No more than one slash
+ * is allowed.
+ *
+ */
+static bool loc_fqsn_split(const char *fqsn, char **ns_name, char **name)
+{
+	size_t cnt = 0;
+	size_t slash_offset = 0;
+	size_t slash_after = 0;
+	
+	size_t offset = 0;
+	size_t offset_prev = 0;
+	wchar_t c;
+	
+	while ((c = str_decode(fqsn, &offset, STR_NO_LIMIT)) != 0) {
+		if (c == '/') {
+			cnt++;
+			slash_offset = offset_prev;
+			slash_after = offset;
+		}
+		offset_prev = offset;
+	}
+	
+	/* More than one slash */
+	if (cnt > 1)
+		return false;
+	
+	/* No slash -> namespace is empty */
+	if (cnt == 0) {
+		*ns_name = str_dup("");
+		if (*ns_name == NULL)
+			return false;
+		
+		*name = str_dup(fqsn);
+		if (*name == NULL) {
+			free(*ns_name);
+			return false;
+		}
+		
+		if (str_cmp(*name, "") == 0) {
+			free(*name);
+			free(*ns_name);
+			return false;
+		}
+		
+		return true;
+	}
+	
+	/* Exactly one slash */
+	*ns_name = str_ndup(fqsn, slash_offset);
+	if (*ns_name == NULL)
+		return false;
+	
+	*name = str_dup(fqsn + slash_after);
+	if (*name == NULL) {
+		free(*ns_name);
+		return false;
+	}
+	
+	if (str_cmp(*name, "") == 0) {
+		free(*name);
+		free(*ns_name);
+		return false;
+	}
+	
+	return true;
+}
+
+/** Find namespace with given name. */
+static loc_namespace_t *loc_namespace_find_name(const char *name)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	list_foreach(namespaces_list, item) {
+		loc_namespace_t *namespace =
+		    list_get_instance(item, loc_namespace_t, namespaces);
+		if (str_cmp(namespace->name, name) == 0)
+			return namespace;
+	}
+	
+	return NULL;
+}
+
+/** Find namespace with given ID.
+ *
+ * @todo: use hash table
+ *
+ */
+static loc_namespace_t *loc_namespace_find_id(service_id_t id)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	list_foreach(namespaces_list, item) {
+		loc_namespace_t *namespace =
+		    list_get_instance(item, loc_namespace_t, namespaces);
+		if (namespace->id == id)
+			return namespace;
+	}
+	
+	return NULL;
+}
+
+/** Find service with given name. */
+static loc_service_t *loc_service_find_name(const char *ns_name,
+    const char *name)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	list_foreach(services_list, item) {
+		loc_service_t *service =
+		    list_get_instance(item, loc_service_t, services);
+		if ((str_cmp(service->namespace->name, ns_name) == 0)
+		    && (str_cmp(service->name, name) == 0))
+			return service;
+	}
+	
+	return NULL;
+}
+
+/** Find service with given ID.
+ *
+ * @todo: use hash table
+ *
+ */
+static loc_service_t *loc_service_find_id(service_id_t id)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	list_foreach(services_list, item) {
+		loc_service_t *service =
+		    list_get_instance(item, loc_service_t, services);
+		if (service->id == id)
+			return service;
+	}
+	
+	return NULL;
+}
+
+/** Create a namespace (if not already present). */
+static loc_namespace_t *loc_namespace_create(const char *ns_name)
+{
+	loc_namespace_t *namespace;
+	
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	
+	namespace = loc_namespace_find_name(ns_name);
+	if (namespace != NULL)
+		return namespace;
+	
+	namespace = (loc_namespace_t *) malloc(sizeof(loc_namespace_t));
+	if (namespace == NULL)
+		return NULL;
+	
+	namespace->name = str_dup(ns_name);
+	if (namespace->name == NULL) {
+		free(namespace);
+		return NULL;
+	}
+	
+	namespace->id = loc_create_id();
+	namespace->refcnt = 0;
+	
+	/*
+	 * Insert new namespace into list of registered namespaces
+	 */
+	list_append(&(namespace->namespaces), &namespaces_list);
+	
+	return namespace;
+}
+
+/** Destroy a namespace (if it is no longer needed). */
+static void loc_namespace_destroy(loc_namespace_t *namespace)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	if (namespace->refcnt == 0) {
+		list_remove(&(namespace->namespaces));
+		
+		free(namespace->name);
+		free(namespace);
+	}
+}
+
+/** Increase namespace reference count by including service. */
+static void loc_namespace_addref(loc_namespace_t *namespace,
+    loc_service_t *service)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	service->namespace = namespace;
+	namespace->refcnt++;
+}
+
+/** Decrease namespace reference count. */
+static void loc_namespace_delref(loc_namespace_t *namespace)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+
+	namespace->refcnt--;
+	loc_namespace_destroy(namespace);
+}
+
+/** Unregister service and free it. */
+static void loc_service_unregister_core(loc_service_t *service)
+{
+	assert(fibril_mutex_is_locked(&services_list_mutex));
+	assert(fibril_mutex_is_locked(&cdir.mutex));
+	
+	loc_namespace_delref(service->namespace);
+	list_remove(&(service->services));
+	list_remove(&(service->server_services));
+	
+	/* Remove service from all categories. */
+	while (!list_empty(&service->cat_memb)) {
+		link_t *link = list_first(&service->cat_memb);
+		svc_categ_t *memb = list_get_instance(link, svc_categ_t,
+		    svc_link);
+		fibril_mutex_lock(&memb->cat->mutex);
+		category_remove_service(memb);
+		fibril_mutex_unlock(&memb->cat->mutex);
+	}
+	
+	free(service->name);
+	free(service);
+}
+
+/**
+ * Read info about new server and add it into linked list of registered
+ * servers.
+ */
+static loc_server_t *loc_server_register(void)
+{
+	ipc_call_t icall;
+	ipc_callid_t iid = async_get_call(&icall);
+	
+	if (IPC_GET_IMETHOD(icall) != LOC_SERVER_REGISTER) {
+		async_answer_0(iid, EREFUSED);
+		return NULL;
+	}
+	
+	loc_server_t *server =
+	    (loc_server_t *) malloc(sizeof(loc_server_t));
+	if (server == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return NULL;
+	}
+	
+	/*
+	 * Get server name
+	 */
+	int rc = async_data_write_accept((void **) &server->name, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		free(server);
+		async_answer_0(iid, rc);
+		return NULL;
+	}
+	
+	/*
+	 * Create connection to the server
+	 */
+	server->sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (!server->sess) {
+		free(server->name);
+		free(server);
+		async_answer_0(iid, ENOTSUP);
+		return NULL;
+	}
+	
+	/*
+	 * Initialize mutex for list of services
+	 * supplied by this server
+	 */
+	fibril_mutex_initialize(&server->services_mutex);
+	
+	/*
+	 * Initialize list of supplied services
+	 */
+	list_initialize(&server->services);
+
+	link_initialize(&server->servers);
+	
+	fibril_mutex_lock(&servers_list_mutex);
+	
+	/* TODO:
+	 * Check that no server with name equal to
+	 * server->name is registered
+	 */
+	
+	/*
+	 * Insert new server into list of registered servers
+	 */
+	list_append(&(server->servers), &servers_list);
+	fibril_mutex_unlock(&servers_list_mutex);
+	
+	async_answer_0(iid, EOK);
+	
+	return server;
+}
+
+/**
+ * Unregister server, unregister all its services and free server
+ * structure.
+ *
+ */
+static int loc_server_unregister(loc_server_t *server)
+{
+	if (server == NULL)
+		return EEXISTS;
+	
+	fibril_mutex_lock(&servers_list_mutex);
+	
+	if (server->sess)
+		async_hangup(server->sess);
+	
+	/* Remove it from list of servers */
+	list_remove(&(server->servers));
+	
+	/* Unregister all its services */
+	fibril_mutex_lock(&services_list_mutex);
+	fibril_mutex_lock(&server->services_mutex);
+	fibril_mutex_lock(&cdir.mutex);
+	
+	while (!list_empty(&server->services)) {
+		loc_service_t *service = list_get_instance(
+		    list_first(&server->services), loc_service_t,
+		    server_services);
+		loc_service_unregister_core(service);
+	}
+	
+	fibril_mutex_unlock(&cdir.mutex);
+	fibril_mutex_unlock(&server->services_mutex);
+	fibril_mutex_unlock(&services_list_mutex);
+	fibril_mutex_unlock(&servers_list_mutex);
+	
+	/* Free name and server */
+	if (server->name != NULL)
+		free(server->name);
+	
+	free(server);
+	
+	return EOK;
+}
+
+/** Register service
+ *
+ */
+static void loc_service_register(ipc_callid_t iid, ipc_call_t *icall,
+    loc_server_t *server)
+{
+	if (server == NULL) {
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	/* Create new service entry */
+	loc_service_t *service =
+	    (loc_service_t *) malloc(sizeof(loc_service_t));
+	if (service == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	/* Set the interface, if any. */
+	service->forward_interface = IPC_GET_ARG1(*icall);
+
+	/* Get fqsn */
+	char *fqsn;
+	int rc = async_data_write_accept((void **) &fqsn, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		free(service);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	char *ns_name;
+	if (!loc_fqsn_split(fqsn, &ns_name, &service->name)) {
+		free(fqsn);
+		free(service);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	free(fqsn);
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace = loc_namespace_create(ns_name);
+	free(ns_name);
+	if (namespace == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		free(service->name);
+		free(service);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	link_initialize(&service->services);
+	link_initialize(&service->server_services);
+	list_initialize(&service->cat_memb);
+	
+	/* Check that service is not already registered */
+	if (loc_service_find_name(namespace->name, service->name) != NULL) {
+		printf("%s: Service '%s/%s' already registered\n", NAME,
+		    namespace->name, service->name);
+		loc_namespace_destroy(namespace);
+		fibril_mutex_unlock(&services_list_mutex);
+		free(service->name);
+		free(service);
+		async_answer_0(iid, EEXISTS);
+		return;
+	}
+	
+	/* Get unique service ID */
+	service->id = loc_create_id();
+
+	loc_namespace_addref(namespace, service);
+	service->server = server;
+	
+	/* Insert service into list of all services  */
+	list_append(&service->services, &services_list);
+	
+	/* Insert service into list of services supplied by one server */
+	fibril_mutex_lock(&service->server->services_mutex);
+	
+	list_append(&service->server_services, &service->server->services);
+	
+	fibril_mutex_unlock(&service->server->services_mutex);
+	fibril_condvar_broadcast(&services_list_cv);
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	async_answer_1(iid, EOK, service->id);
+}
+
+/**
+ *
+ */
+static void loc_service_unregister(ipc_callid_t iid, ipc_call_t *icall, 
+    loc_server_t *server)
+{
+	loc_service_t *svc;
+	
+	fibril_mutex_lock(&services_list_mutex);
+	svc = loc_service_find_id(IPC_GET_ARG1(*icall));
+	if (svc == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	loc_service_unregister_core(svc);
+	fibril_mutex_unlock(&cdir.mutex);
+	fibril_mutex_unlock(&services_list_mutex);
+	async_answer_0(iid, EOK);
+}
+
+static void loc_category_get_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	category_t *cat;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	
+	cat = category_get(&cdir, IPC_GET_ARG1(*icall));
+	if (cat == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	act_size = str_size(cat->name);
+	if (act_size > size) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, cat->name,
+	    min(size, act_size));
+	
+	fibril_mutex_unlock(&cdir.mutex);
+	
+	async_answer_0(iid, retval);
+}
+
+static void loc_service_get_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	loc_service_t *svc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	svc = loc_service_find_id(IPC_GET_ARG1(*icall));
+	if (svc == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	act_size = str_size(svc->name);
+	if (act_size > size) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, svc->name,
+	    min(size, act_size));
+	
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	async_answer_0(iid, retval);
+}
+
+/** Connect client to the service.
+ *
+ * Find server supplying requested service and forward
+ * the message to it.
+ *
+ */
+static void loc_forward(ipc_callid_t callid, ipc_call_t *call)
+{
+	fibril_mutex_lock(&services_list_mutex);
+	
+	/*
+	 * Get ID from request
+	 */
+	service_id_t id = IPC_GET_ARG2(*call);
+	loc_service_t *svc = loc_service_find_id(id);
+	
+	if ((svc == NULL) || (svc->server == NULL) || (!svc->server->sess)) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(svc->server->sess);
+	
+	if (svc->forward_interface == 0)
+		async_forward_fast(callid, exch, svc->id, 0, 0, IPC_FF_NONE);
+	else
+		async_forward_fast(callid, exch, svc->forward_interface,
+		    svc->id, 0, IPC_FF_NONE);
+	
+	async_exchange_end(exch);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+}
+
+/** Find ID for service identified by name.
+ *
+ * In answer will be send EOK and service ID in arg1 or a error
+ * code from errno.h.
+ *
+ */
+static void loc_service_get_id(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *fqsn;
+	
+	/* Get fqsn */
+	int rc = async_data_write_accept((void **) &fqsn, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	char *ns_name;
+	char *name;
+	if (!loc_fqsn_split(fqsn, &ns_name, &name)) {
+		free(fqsn);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	free(fqsn);
+	
+	fibril_mutex_lock(&services_list_mutex);
+	const loc_service_t *svc;
+	
+recheck:
+	
+	/*
+	 * Find service name in the list of known services.
+	 */
+	svc = loc_service_find_name(ns_name, name);
+	
+	/*
+	 * Device was not found.
+	 */
+	if (svc == NULL) {
+		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
+			/* Blocking lookup */
+			fibril_condvar_wait(&services_list_cv,
+			    &services_list_mutex);
+			goto recheck;
+		}
+		
+		async_answer_0(iid, ENOENT);
+		free(ns_name);
+		free(name);
+		fibril_mutex_unlock(&services_list_mutex);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, svc->id);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+	free(ns_name);
+	free(name);
+}
+
+/** Find ID for namespace identified by name.
+ *
+ * In answer will be send EOK and service ID in arg1 or a error
+ * code from errno.h.
+ *
+ */
+static void loc_namespace_get_id(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *name;
+	
+	/* Get service name */
+	int rc = async_data_write_accept((void **) &name, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	const loc_namespace_t *namespace;
+	
+recheck:
+	
+	/*
+	 * Find namespace name in the list of known namespaces.
+	 */
+	namespace = loc_namespace_find_name(name);
+	
+	/*
+	 * Namespace was not found.
+	 */
+	if (namespace == NULL) {
+		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
+			/* Blocking lookup */
+			fibril_condvar_wait(&services_list_cv,
+			    &services_list_mutex);
+			goto recheck;
+		}
+		
+		async_answer_0(iid, ENOENT);
+		free(name);
+		fibril_mutex_unlock(&services_list_mutex);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, namespace->id);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+	free(name);
+}
+
+/** Find ID for category specified by name.
+ *
+ * On success, answer will contain EOK int retval and service ID in arg1.
+ * On failure, error code will be sent in retval.
+ *
+ */
+static void loc_callback_create(ipc_callid_t iid, ipc_call_t *icall)
+{
+	async_sess_t *cb_sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (cb_sess == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&callback_sess_mutex);
+	if (callback_sess != NULL) {
+		fibril_mutex_unlock(&callback_sess_mutex);
+		async_answer_0(iid, EEXIST);
+		return;
+	}
+	
+	callback_sess = cb_sess;
+	fibril_mutex_unlock(&callback_sess_mutex);
+	
+	async_answer_0(iid, EOK);
+}
+
+void loc_category_change_event(void)
+{
+	fibril_mutex_lock(&callback_sess_mutex);
+
+	if (callback_sess != NULL) {
+		async_exch_t *exch = async_exchange_begin(callback_sess);
+		async_msg_0(exch, LOC_EVENT_CAT_CHANGE);
+		async_exchange_end(exch);
+	}
+
+	fibril_mutex_unlock(&callback_sess_mutex);
+}
+
+/** Find ID for category specified by name.
+ *
+ * On success, answer will contain EOK int retval and service ID in arg1.
+ * On failure, error code will be sent in retval.
+ *
+ */
+static void loc_category_get_id(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *name;
+	category_t *cat;
+	
+	/* Get service name */
+	int rc = async_data_write_accept((void **) &name, true, 0,
+	    LOC_NAME_MAXLEN, 0, NULL);
+	if (rc != EOK) {
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+
+	cat = category_find_by_name(&cdir, name);
+	if (cat == NULL) {
+		/* Category not found */
+		async_answer_0(iid, ENOENT);
+		goto cleanup;
+	}
+	
+	async_answer_1(iid, EOK, cat->id);
+cleanup:
+	fibril_mutex_unlock(&cdir.mutex);
+	free(name);
+}
+
+static void loc_id_probe(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace =
+	    loc_namespace_find_id(IPC_GET_ARG1(*icall));
+	if (namespace == NULL) {
+		loc_service_t *svc =
+		    loc_service_find_id(IPC_GET_ARG1(*icall));
+		if (svc == NULL)
+			async_answer_1(iid, EOK, LOC_OBJECT_NONE);
+		else
+			async_answer_1(iid, EOK, LOC_OBJECT_SERVICE);
+	} else
+		async_answer_1(iid, EOK, LOC_OBJECT_NAMESPACE);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+}
+
+static void loc_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&services_list_mutex);
+	async_answer_1(iid, EOK, list_count(&namespaces_list));
+	fibril_mutex_unlock(&services_list_mutex);
+}
+
+static void loc_get_service_count(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace =
+	    loc_namespace_find_id(IPC_GET_ARG1(*icall));
+	if (namespace == NULL)
+		async_answer_0(iid, EEXISTS);
+	else
+		async_answer_1(iid, EOK, namespace->refcnt);
+	
+	fibril_mutex_unlock(&services_list_mutex);
+}
+
+static void loc_get_categories(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	category_id_t *id_buf = (category_id_t *) malloc(size);
+	if (id_buf == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	
+	rc = categ_dir_get_categories(&cdir, id_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_unlock(&cdir.mutex);
+	
+	sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
+	free(id_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+static void loc_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if ((size % sizeof(loc_sdesc_t)) != 0) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	size_t count = size / sizeof(loc_sdesc_t);
+	if (count != list_count(&namespaces_list)) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	loc_sdesc_t *desc = (loc_sdesc_t *) malloc(size);
+	if (desc == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	size_t pos = 0;
+	list_foreach(namespaces_list, item) {
+		loc_namespace_t *namespace =
+		    list_get_instance(item, loc_namespace_t, namespaces);
+		
+		desc[pos].id = namespace->id;
+		str_cpy(desc[pos].name, LOC_NAME_MAXLEN, namespace->name);
+		pos++;
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, desc, size);
+	
+	free(desc);
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	async_answer_0(iid, retval);
+}
+
+static void loc_get_services(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* FIXME: Use faster algorithm which can make better use
+	   of namespaces */
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	if ((size % sizeof(loc_sdesc_t)) != 0) {
+		async_answer_0(callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace =
+	    loc_namespace_find_id(IPC_GET_ARG1(*icall));
+	if (namespace == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	size_t count = size / sizeof(loc_sdesc_t);
+	if (count != namespace->refcnt) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, EOVERFLOW);
+		async_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	loc_sdesc_t *desc = (loc_sdesc_t *) malloc(size);
+	if (desc == NULL) {
+		fibril_mutex_unlock(&services_list_mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	size_t pos = 0;
+	list_foreach(services_list, item) {
+		loc_service_t *service =
+		    list_get_instance(item, loc_service_t, services);
+		
+		if (service->namespace == namespace) {
+			desc[pos].id = service->id;
+			str_cpy(desc[pos].name, LOC_NAME_MAXLEN, service->name);
+			pos++;
+		}
+	}
+	
+	sysarg_t retval = async_data_read_finalize(callid, desc, size);
+	
+	free(desc);
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	async_answer_0(iid, retval);
+}
+
+static void loc_category_get_svcs(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_mutex_lock(&cdir.mutex);
+	
+	category_t *cat = category_get(&cdir, IPC_GET_ARG1(*icall));
+	if (cat == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	category_id_t *id_buf = (category_id_t *) malloc(size);
+	if (id_buf == NULL) {
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&cat->mutex);
+	
+	rc = category_get_services(cat, id_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&cat->mutex);
+		fibril_mutex_unlock(&cdir.mutex);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_unlock(&cat->mutex);
+	fibril_mutex_unlock(&cdir.mutex);
+	
+	sysarg_t retval = async_data_read_finalize(callid, id_buf, size);
+	free(id_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+
+static void loc_null_create(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&null_services_mutex);
+	
+	unsigned int i;
+	bool fnd = false;
+	
+	for (i = 0; i < NULL_SERVICES; i++) {
+		if (null_services[i] == NULL) {
+			fnd = true;
+			break;
+		}
+	}
+	
+	if (!fnd) {
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	char null[LOC_NAME_MAXLEN];
+	snprintf(null, LOC_NAME_MAXLEN, "%u", i);
+	
+	char *dev_name = str_dup(null);
+	if (dev_name == NULL) {
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	loc_service_t *service =
+	    (loc_service_t *) malloc(sizeof(loc_service_t));
+	if (service == NULL) {
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	
+	loc_namespace_t *namespace = loc_namespace_create("null");
+	if (namespace == NULL) {
+		fibril_mutex_lock(&services_list_mutex);
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	link_initialize(&service->services);
+	link_initialize(&service->server_services);
+	
+	/* Get unique service ID */
+	service->id = loc_create_id();
+	service->server = NULL;
+	
+	loc_namespace_addref(namespace, service);
+	service->name = dev_name;
+	
+	/*
+	 * Insert service into list of all services and into null services array.
+	 * Insert service into a dummy list of null server's services so that it
+	 * can be safely removed later.
+	 */
+	list_append(&service->services, &services_list);
+	list_append(&service->server_services, &dummy_null_services);
+	null_services[i] = service;
+	
+	fibril_mutex_unlock(&services_list_mutex);
+	fibril_mutex_unlock(&null_services_mutex);
+	
+	async_answer_1(iid, EOK, (sysarg_t) i);
+}
+
+static void loc_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
+{
+	sysarg_t i = IPC_GET_ARG1(*icall);
+	if (i >= NULL_SERVICES) {
+		async_answer_0(iid, ELIMIT);
+		return;
+	}
+	
+	fibril_mutex_lock(&null_services_mutex);
+	
+	if (null_services[i] == NULL) {
+		fibril_mutex_unlock(&null_services_mutex);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	fibril_mutex_lock(&services_list_mutex);
+	fibril_mutex_lock(&cdir.mutex);
+	loc_service_unregister_core(null_services[i]);
+	fibril_mutex_unlock(&cdir.mutex);
+	fibril_mutex_unlock(&services_list_mutex);
+	
+	null_services[i] = NULL;
+	
+	fibril_mutex_unlock(&null_services_mutex);
+	async_answer_0(iid, EOK);
+}
+
+static void loc_service_add_to_cat(ipc_callid_t iid, ipc_call_t *icall)
+{
+	category_t *cat;
+	loc_service_t *svc;
+	catid_t cat_id;
+	service_id_t svc_id;
+	sysarg_t retval;
+	
+	svc_id = IPC_GET_ARG1(*icall);
+	cat_id = IPC_GET_ARG2(*icall);
+	
+	fibril_mutex_lock(&services_list_mutex);
+	fibril_mutex_lock(&cdir.mutex);
+	
+	cat = category_get(&cdir, cat_id);
+	svc = loc_service_find_id(svc_id);
+	
+	fibril_mutex_lock(&cat->mutex);
+	retval = category_add_service(cat, svc);
+
+	fibril_mutex_unlock(&cat->mutex);
+	fibril_mutex_unlock(&cdir.mutex);
+	fibril_mutex_unlock(&services_list_mutex);
+
+	async_answer_0(iid, retval);
+
+	loc_category_change_event();
+}
+
+
+/** Initialize location service.
+ *
+ *
+ */
+static bool loc_init(void)
+{
+	unsigned int i;
+	category_t *cat;
+
+	for (i = 0; i < NULL_SERVICES; i++)
+		null_services[i] = NULL;
+	
+	categ_dir_init(&cdir);
+
+	cat = category_new("bd");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("keyboard");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("mouse");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("serial");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("usbhc");
+	categ_dir_add_cat(&cdir, cat);
+
+	cat = category_new("virtual");
+	categ_dir_add_cat(&cdir, cat);
+
+	return true;
+}
+
+/** Handle connection on supplier port.
+ *
+ */
+static void loc_connection_supplier(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Accept connection */
+	async_answer_0(iid, EOK);
+	
+	loc_server_t *server = loc_server_register();
+	if (server == NULL)
+		return;
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case LOC_SERVER_UNREGISTER:
+			if (server == NULL)
+				async_answer_0(callid, ENOENT);
+			else
+				async_answer_0(callid, EOK);
+			break;
+		case LOC_SERVICE_ADD_TO_CAT:
+			/* Add service to category */
+			loc_service_add_to_cat(callid, &call);
+			break;
+		case LOC_SERVICE_REGISTER:
+			/* Register one service */
+			loc_service_register(callid, &call, server);
+			break;
+		case LOC_SERVICE_UNREGISTER:
+			/* Remove one service */
+			loc_service_unregister(callid, &call, server);
+			break;
+		case LOC_SERVICE_GET_ID:
+			loc_service_get_id(callid, &call);
+			break;
+		case LOC_NAMESPACE_GET_ID:
+			loc_namespace_get_id(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOENT);
+		}
+	}
+	
+	if (server != NULL) {
+		/*
+		 * Unregister the server and all its services.
+		 */
+		loc_server_unregister(server);
+		server = NULL;
+	}
+}
+
+/** Handle connection on consumer port.
+ *
+ */
+static void loc_connection_consumer(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* Accept connection */
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case LOC_SERVICE_GET_ID:
+			loc_service_get_id(callid, &call);
+			break;
+		case LOC_SERVICE_GET_NAME:
+			loc_service_get_name(callid, &call);
+			break;
+		case LOC_NAMESPACE_GET_ID:
+			loc_namespace_get_id(callid, &call);
+			break;
+		case LOC_CALLBACK_CREATE:
+			loc_callback_create(callid, &call);
+			break;
+		case LOC_CATEGORY_GET_ID:
+			loc_category_get_id(callid, &call);
+			break;
+		case LOC_CATEGORY_GET_NAME:
+			loc_category_get_name(callid, &call);
+			break;
+		case LOC_CATEGORY_GET_SVCS:
+			loc_category_get_svcs(callid, &call);
+			break;
+		case LOC_ID_PROBE:
+			loc_id_probe(callid, &call);
+			break;
+		case LOC_NULL_CREATE:
+			loc_null_create(callid, &call);
+			break;
+		case LOC_NULL_DESTROY:
+			loc_null_destroy(callid, &call);
+			break;
+		case LOC_GET_NAMESPACE_COUNT:
+			loc_get_namespace_count(callid, &call);
+			break;
+		case LOC_GET_SERVICE_COUNT:
+			loc_get_service_count(callid, &call);
+			break;
+		case LOC_GET_CATEGORIES:
+			loc_get_categories(callid, &call);
+			break;
+		case LOC_GET_NAMESPACES:
+			loc_get_namespaces(callid, &call);
+			break;
+		case LOC_GET_SERVICES:
+			loc_get_services(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOENT);
+		}
+	}
+}
+
+/** Function for handling connections to location service
+ *
+ */
+static void loc_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Select interface */
+	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
+	case LOC_PORT_SUPPLIER:
+		loc_connection_supplier(iid, icall);
+		break;
+	case LOC_PORT_CONSUMER:
+		loc_connection_consumer(iid, icall);
+		break;
+	case LOC_CONNECT_TO_SERVICE:
+		/* Connect client to selected service */
+		loc_forward(iid, icall);
+		break;
+	default:
+		/* No such interface */
+		async_answer_0(iid, ENOENT);
+	}
+}
+
+/**
+ *
+ */
+int main(int argc, char *argv[])
+{
+	printf("%s: HelenOS Location Service\n", NAME);
+	
+	if (!loc_init()) {
+		printf("%s: Error while initializing service\n", NAME);
+		return -1;
+	}
+	
+	/* Set a handler of incomming connections */
+	async_set_client_connection(loc_connection);
+	
+	/* Register location service at naming service */
+	if (service_register(SERVICE_LOC) != EOK)
+		return -1;
+	
+	printf("%s: Accepting connections\n", NAME);
+	async_manager();
+	
+	/* Never reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/loc/loc.h
===================================================================
--- uspace/srv/loc/loc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
+++ uspace/srv/loc/loc.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup loc
+ * @{
+ */
+/** @file HelenOS location service.
+ */
+
+#ifndef LOC_H_
+#define LOC_H_
+
+#include <ipc/loc.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <sys/types.h>
+
+/** Representation of server (supplier).
+ *
+ * Each server supplies a set of services.
+ *
+ */
+typedef struct {
+	/** Link to servers_list */
+	link_t servers;
+	
+	/** List of services supplied by this server */
+	list_t services;
+	
+	/** Session asociated with this server */
+	async_sess_t *sess;
+	
+	/** Server name */
+	char *name;
+	
+	/** Fibril mutex for list of services owned by this server */
+	fibril_mutex_t services_mutex;
+} loc_server_t;
+
+/** Info about registered namespaces
+ *
+ */
+typedef struct {
+	/** Link to namespaces_list */
+	link_t namespaces;
+	
+	/** Unique namespace identifier */
+	service_id_t id;
+	
+	/** Namespace name */
+	char *name;
+	
+	/** Reference count */
+	size_t refcnt;
+} loc_namespace_t;
+
+/** Info about registered service
+ *
+ */
+typedef struct {
+	/** Link to global list of services (services_list) */
+	link_t services;
+	/** Link to server list of services (loc_server_t.services) */
+	link_t server_services;
+	/** Link to list of services in category (category_t.services) */
+	link_t cat_services;
+	/** List of category memberships (svc_categ_t) */
+	list_t cat_memb;
+	/** Unique service identifier */
+	service_id_t id;
+	/** Service namespace */
+	loc_namespace_t *namespace;
+	/** Service name */
+	char *name;
+	/** Supplier of this service */
+	loc_server_t *server;
+	/** Use this interface when forwarding to server. */
+	sysarg_t forward_interface;
+} loc_service_t;
+
+extern fibril_mutex_t services_list_mutex;
+
+extern service_id_t loc_create_id(void);
+extern void loc_category_change_event(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/il/arp/arp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -157,12 +157,12 @@
 			
 			arp_clear_addr(&proto->addresses);
-			arp_addr_destroy(&proto->addresses);
-		}
-	}
-	
-	arp_protos_clear(&device->protos);
-}
-
-static int arp_clean_cache_req(int arp_phone)
+			arp_addr_destroy(&proto->addresses, free);
+		}
+	}
+	
+	arp_protos_clear(&device->protos, free);
+}
+
+static int arp_clean_cache_req(void)
 {
 	int count;
@@ -184,5 +184,5 @@
 	}
 	
-	arp_cache_clear(&arp_globals.cache);
+	arp_cache_clear(&arp_globals.cache, free);
 	fibril_mutex_unlock(&arp_globals.lock);
 	
@@ -190,6 +190,6 @@
 }
 
-static int arp_clear_address_req(int arp_phone, device_id_t device_id,
-    services_t protocol, measured_string_t *address)
+static int arp_clear_address_req(device_id_t device_id, services_t protocol,
+    measured_string_t *address)
 {
 	fibril_mutex_lock(&arp_globals.lock);
@@ -212,5 +212,5 @@
 		arp_clear_trans(trans);
 	
-	arp_addr_exclude(&proto->addresses, address->value, address->length);
+	arp_addr_exclude(&proto->addresses, address->value, address->length, free);
 	
 	fibril_mutex_unlock(&arp_globals.lock);
@@ -218,5 +218,5 @@
 }
 
-static int arp_clear_device_req(int arp_phone, device_id_t device_id)
+static int arp_clear_device_req(device_id_t device_id)
 {
 	fibril_mutex_lock(&arp_globals.lock);
@@ -345,5 +345,5 @@
 			    header->protocol_length, trans);
 			if (rc != EOK) {
-				/* The generic char map has already freed trans! */
+				free(trans);
 				return rc;
 			}
@@ -375,5 +375,5 @@
 				return rc;
 			
-			nil_send_msg(device->phone, device_id, packet,
+			nil_send_msg(device->sess, device_id, packet,
 			    SERVICE_ARP);
 			return 1;
@@ -416,7 +416,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -431,5 +432,5 @@
 		
 		case NET_IL_RECEIVED:
-			rc = packet_translate_remote(arp_globals.net_phone, &packet,
+			rc = packet_translate_remote(arp_globals.net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK) {
@@ -439,5 +440,5 @@
 					rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
 					if (rc != 1) {
-						pq_release_remote(arp_globals.net_phone,
+						pq_release_remote(arp_globals.net_sess,
 						    packet_get_id(packet));
 					}
@@ -556,5 +557,5 @@
 		if (index < 0) {
 			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos);
+			arp_protos_destroy(&device->protos, free);
 			free(device);
 			return index;
@@ -564,10 +565,10 @@
 		
 		/* Bind */
-		device->phone = nil_bind_service(device->service,
+		device->sess = nil_bind_service(device->service,
 		    (sysarg_t) device->device_id, SERVICE_ARP,
 		    arp_receiver);
-		if (device->phone < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos);
+		if (device->sess == NULL) {
+			fibril_mutex_unlock(&arp_globals.lock);
+			arp_protos_destroy(&device->protos, free);
 			free(device);
 			return EREFUSED;
@@ -575,9 +576,9 @@
 		
 		/* Get packet dimensions */
-		rc = nil_packet_size_req(device->phone, device_id,
+		rc = nil_packet_size_req(device->sess, device_id,
 		    &device->packet_dimension);
 		if (rc != EOK) {
 			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos);
+			arp_protos_destroy(&device->protos, free);
 			free(device);
 			return rc;
@@ -585,9 +586,9 @@
 		
 		/* Get hardware address */
-		rc = nil_get_addr_req(device->phone, device_id, &device->addr,
+		rc = nil_get_addr_req(device->sess, device_id, &device->addr,
 		    &device->addr_data);
 		if (rc != EOK) {
 			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos);
+			arp_protos_destroy(&device->protos, free);
 			free(device);
 			return rc;
@@ -595,5 +596,5 @@
 		
 		/* Get broadcast address */
-		rc = nil_get_broadcast_addr_req(device->phone, device_id,
+		rc = nil_get_broadcast_addr_req(device->sess, device_id,
 		    &device->broadcast_addr, &device->broadcast_data);
 		if (rc != EOK) {
@@ -601,5 +602,5 @@
 			free(device->addr);
 			free(device->addr_data);
-			arp_protos_destroy(&device->protos);
+			arp_protos_destroy(&device->protos, free);
 			free(device);
 			return rc;
@@ -614,5 +615,5 @@
 			free(device->broadcast_addr);
 			free(device->broadcast_data);
-			arp_protos_destroy(&device->protos);
+			arp_protos_destroy(&device->protos, free);
 			free(device);
 			return rc;
@@ -627,10 +628,10 @@
 }
 
-int il_initialize(int net_phone)
+int il_initialize(async_sess_t *net_sess)
 {
 	fibril_mutex_initialize(&arp_globals.lock);
 	
 	fibril_mutex_lock(&arp_globals.lock);
-	arp_globals.net_phone = net_phone;
+	arp_globals.net_sess = net_sess;
 	int rc = arp_cache_initialize(&arp_globals.cache);
 	fibril_mutex_unlock(&arp_globals.lock);
@@ -647,5 +648,5 @@
 		return ELIMIT;
 	
-	packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
+	packet_t *packet = packet_get_4_remote(arp_globals.net_sess,
 	    device->packet_dimension.addr_len, device->packet_dimension.prefix,
 	    length, device->packet_dimension.suffix);
@@ -655,5 +656,5 @@
 	arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
 	if (!header) {
-		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
 		return ENOMEM;
 	}
@@ -680,9 +681,9 @@
 	    (uint8_t *) device->broadcast_addr->value, device->addr->length);
 	if (rc != EOK) {
-		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
 		return rc;
 	}
 	
-	nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
+	nil_send_msg(device->sess, device_id, packet, SERVICE_ARP);
 	return EOK;
 }
@@ -746,5 +747,5 @@
 			arp_clear_trans(trans);
 			arp_addr_exclude(&proto->addresses, target->value,
-			    target->length);
+			    target->length, free);
 			return EAGAIN;
 		}
@@ -794,5 +795,5 @@
 	    trans);
 	if (rc != EOK) {
-		/* The generic char map has already freed trans! */
+		free(trans);
 		return rc;
 	}
@@ -807,5 +808,5 @@
 		arp_clear_trans(trans);
 		arp_addr_exclude(&proto->addresses, target->value,
-		    target->length);
+		    target->length, free);
 		return ENOENT;
 	}
@@ -845,8 +846,9 @@
 	
 	*count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
 	case NET_ARP_DEVICE:
 		rc = measured_strings_receive(&address, &data, 1);
@@ -889,5 +891,5 @@
 	
 	case NET_ARP_CLEAR_DEVICE:
-		return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
+		return arp_clear_device_req(IPC_GET_DEVICE(*call));
 	
 	case NET_ARP_CLEAR_ADDRESS:
@@ -896,5 +898,5 @@
 			return rc;
 		
-		arp_clear_address_req(0, IPC_GET_DEVICE(*call),
+		arp_clear_address_req(IPC_GET_DEVICE(*call),
 		    IPC_GET_SERVICE(*call), address);
 		free(address);
@@ -903,5 +905,5 @@
 	
 	case NET_ARP_CLEAN_CACHE:
-		return arp_clean_cache_req(0);
+		return arp_clean_cache_req();
 	}
 	
Index: uspace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/il/arp/arp.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #define NET_ARP_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
@@ -104,6 +105,6 @@
 	/** Packet dimension. */
 	packet_dimension_t packet_dimension;
-	/** Device module phone. */
-	int phone;
+	/** Device module session. */
+	async_sess_t *sess;
 	
 	/**
@@ -122,6 +123,7 @@
 	arp_cache_t cache;
 	
-	/** Networking module phone. */
-	int net_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
+	
 	/** Safety lock. */
 	fibril_mutex_t lock;
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/il/ip/ip.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -120,35 +120,36 @@
 GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
 
-static void ip_receiver(ipc_callid_t, ipc_call_t *);
-
-/** Releases the packet and returns the result.
- *
- * @param[in] packet	The packet queue to be released.
- * @param[in] result	The result to be returned.
- * @return		The result parameter.
+static void ip_receiver(ipc_callid_t, ipc_call_t *, void *);
+
+/** Release the packet and returns the result.
+ *
+ * @param[in] packet Packet queue to be released.
+ * @param[in] result Result to be returned.
+ *
+ * @return Result parameter.
+ *
  */
 static int ip_release_and_return(packet_t *packet, int result)
 {
-	pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
 	return result;
 }
 
-/** Returns the ICMP phone.
- *
- * Searches the registered protocols.
- *
- * @return		The found ICMP phone.
- * @return		ENOENT if the ICMP is not registered.
- */
-static int ip_get_icmp_phone(void)
-{
-	ip_proto_t *proto;
-	int phone;
-
+/** Return the ICMP session.
+ *
+ * Search the registered protocols.
+ *
+ * @return Found ICMP session.
+ * @return NULL if the ICMP is not registered.
+ *
+ */
+static async_sess_t *ip_get_icmp_session(void)
+{
 	fibril_rwlock_read_lock(&ip_globals.protos_lock);
-	proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
-	phone = proto ? proto->phone : ENOENT;
+	ip_proto_t *proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
+	async_sess_t *sess = proto ? proto->sess : NULL;
 	fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-	return phone;
+	
+	return sess;
 }
 
@@ -176,8 +177,8 @@
 	socklen_t addrlen;
 
-	// detach the first packet and release the others
+	/* Detach the first packet and release the others */
 	next = pq_detach(packet);
 	if (next)
-		pq_release_remote(ip_globals.net_phone, packet_get_id(next));
+		pq_release_remote(ip_globals.net_sess, packet_get_id(next));
 
 	if (!header) {
@@ -185,5 +186,5 @@
 			return ENOMEM;
 
-		// get header
+		/* Get header */
 		header = (ip_header_t *) packet_get_data(packet);
 		if (!header)
@@ -192,14 +193,14 @@
 	}
 
-	// only for the first fragment
+	/* Only for the first fragment */
 	if (IP_FRAGMENT_OFFSET(header))
 		return EINVAL;
 
-	// not for the ICMP protocol
+	/* Not for the ICMP protocol */
 	if (header->protocol == IPPROTO_ICMP)
 		return EPERM;
 
-	// set the destination address
-	switch (header->version) {
+	/* Set the destination address */
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(dest_in);
@@ -218,30 +219,33 @@
 }
 
-/** Prepares the ICMP notification packet.
- *
- * Releases additional packets and keeps only the first one.
+/** Prepare the ICMP notification packet.
+ *
+ * Release additional packets and keep only the first one.
  * All packets are released on error.
  *
- * @param[in] error	The packet error service.
- * @param[in] packet	The packet or the packet queue to be reported as faulty.
- * @param[in] header	The first packet IP header. May be NULL.
- * @return		The found ICMP phone.
- * @return		EINVAL if the error parameter is set.
- * @return		EINVAL if the ICMP phone is not found.
- * @return		EINVAL if the ip_prepare_icmp() fails.
- */
-static int
-ip_prepare_icmp_and_get_phone(services_t error, packet_t *packet,
-    ip_header_t *header)
-{
-	int phone;
-
-	phone = ip_get_icmp_phone();
-	if (error || (phone < 0) || ip_prepare_icmp(packet, header))
-		return ip_release_and_return(packet, EINVAL);
-	return phone;
-}
-
-int il_initialize(int net_phone)
+ * @param[in] error  Packet error service.
+ * @param[in] packet Packet or the packet queue to be reported as faulty.
+ * @param[in] header First packet IP header. May be NULL.
+ *
+ * @return Found ICMP session.
+ * @return NULL if the error parameter is set.
+ * @return NULL if the ICMP session is not found.
+ * @return NULL if the ip_prepare_icmp() fails.
+ *
+ */
+static async_sess_t *ip_prepare_icmp_and_get_session(services_t error,
+    packet_t *packet, ip_header_t *header)
+{
+	async_sess_t *sess = ip_get_icmp_session();
+	
+	if ((error) || (!sess) || (ip_prepare_icmp(packet, header))) {
+		pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
+		return NULL;
+	}
+	
+	return sess;
+}
+
+int il_initialize(async_sess_t *net_sess)
 {
 	fibril_rwlock_initialize(&ip_globals.lock);
@@ -250,5 +254,5 @@
 	fibril_rwlock_initialize(&ip_globals.netifs_lock);
 	
-	ip_globals.net_phone = net_phone;
+	ip_globals.net_sess = net_sess;
 	ip_globals.packet_counter = 0;
 	ip_globals.gateway.address.s_addr = 0;
@@ -351,6 +355,6 @@
 	configuration = &names[0];
 
-	// get configuration
-	rc = net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id,
+	/* Get configuration */
+	rc = net_get_device_conf_req(ip_globals.net_sess, ip_netif->device_id,
 	    &configuration, count, &data);
 	if (rc != EOK)
@@ -419,15 +423,15 @@
 	}
 
-	// binds the netif service which also initializes the device
-	ip_netif->phone = nil_bind_service(ip_netif->service,
+	/* Bind netif service which also initializes the device */
+	ip_netif->sess = nil_bind_service(ip_netif->service,
 	    (sysarg_t) ip_netif->device_id, SERVICE_IP,
 	    ip_receiver);
-	if (ip_netif->phone < 0) {
+	if (ip_netif->sess == NULL) {
 		printf("Failed to contact the nil service %d\n",
 		    ip_netif->service);
-		return ip_netif->phone;
-	}
-
-	// has to be after the device netif module initialization
+		return ENOENT;
+	}
+
+	/* Has to be after the device netif module initialization */
 	if (ip_netif->arp) {
 		if (route) {
@@ -435,5 +439,5 @@
 			address.length = sizeof(in_addr_t);
 			
-			rc = arp_device_req(ip_netif->arp->phone,
+			rc = arp_device_req(ip_netif->arp->sess,
 			    ip_netif->device_id, SERVICE_IP, ip_netif->service,
 			    &address);
@@ -445,6 +449,6 @@
 	}
 
-	// get packet dimensions
-	rc = nil_packet_size_req(ip_netif->phone, ip_netif->device_id,
+	/* Get packet dimensions */
+	rc = nil_packet_size_req(ip_netif->sess, ip_netif->device_id,
 	    &ip_netif->packet_dimension);
 	if (rc != EOK)
@@ -463,5 +467,5 @@
 	
 	if (gateway.s_addr) {
-		// the default gateway
+		/* The default gateway */
 		ip_globals.gateway.address.s_addr = 0;
 		ip_globals.gateway.netmask.s_addr = 0;
@@ -478,6 +482,5 @@
 }
 
-static int ip_device_req_local(int il_phone, device_id_t device_id,
-    services_t netif)
+static int ip_device_req_local(device_id_t device_id, services_t netif)
 {
 	ip_netif_t *ip_netif;
@@ -505,5 +508,5 @@
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		ip_routes_destroy(&ip_netif->routes);
+		ip_routes_destroy(&ip_netif->routes, free);
 		free(ip_netif);
 		return rc;
@@ -512,7 +515,7 @@
 		ip_netif->arp->usage++;
 
-	// print the settings
-	printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
-	    NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
+	/* Print the settings */
+	printf("%s: Device registered (id: %d, ipv: %d, conf: %s)\n",
+	    NAME, ip_netif->device_id, ip_netif->ipv,
 	    ip_netif->dhcp ? "dhcp" : "static");
 	
@@ -587,5 +590,5 @@
 	ip_netif_t *netif;
 
-	// start with the last netif - the newest one
+	/* Start with the last netif - the newest one */
 	index = ip_netifs_count(&ip_globals.netifs) - 1;
 	while (index >= 0) {
@@ -629,18 +632,18 @@
 	size_t length;
 
-	// copy first itself
+	/* Copy first itself */
 	memcpy(last, first, sizeof(ip_header_t));
 	length = sizeof(ip_header_t);
 	next = sizeof(ip_header_t);
 
-	// process all ip options
-	while (next < first->header_length) {
+	/* Process all IP options */
+	while (next < GET_IP_HEADER_LENGTH(first)) {
 		option = (ip_option_t *) (((uint8_t *) first) + next);
-		// skip end or noop
+		/* Skip end or noop */
 		if ((option->type == IPOPT_END) ||
 		    (option->type == IPOPT_NOOP)) {
 			next++;
 		} else {
-			// copy if told so or skip
+			/* Copy if told so or skip */
 			if (IPOPT_COPIED(option->type)) {
 				memcpy(((uint8_t *) last) + length,
@@ -648,15 +651,15 @@
 				length += option->length;
 			}
-			// next option
+			/* Next option */
 			next += option->length;
 		}
 	}
 
-	// align 4 byte boundary
+	/* Align 4 byte boundary */
 	if (length % 4) {
 		bzero(((uint8_t *) last) + length, 4 - (length % 4));
-		last->header_length = length / 4 + 1;
+		SET_IP_HEADER_LENGTH(last, (length / 4 + 1));
 	} else {
-		last->header_length = length / 4;
+		SET_IP_HEADER_LENGTH(last, (length / 4));
 	}
 
@@ -706,6 +709,6 @@
 		return rc;
 	
-	header->version = IPV4;
-	header->fragment_offset_high = 0;
+	SET_IP_HEADER_VERSION(header, IPV4);
+	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, 0);
 	header->fragment_offset_low = 0;
 	header->header_checksum = 0;
@@ -735,9 +738,10 @@
 			memcpy(middle_header, last_header,
 			    IP_HEADER_LENGTH(last_header));
-			header->flags |= IPFLAG_MORE_FRAGMENTS;
+			SET_IP_HEADER_FLAGS(header,
+			    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
 			middle_header->total_length =
 			    htons(packet_get_data_length(next));
-			middle_header->fragment_offset_high =
-			    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
+			SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
+			    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
 			middle_header->fragment_offset_low =
 			    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
@@ -768,6 +772,6 @@
 		middle_header->total_length =
 		    htons(packet_get_data_length(next));
-		middle_header->fragment_offset_high =
-		    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
+		SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
+		    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
 		middle_header->fragment_offset_low =
 		    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
@@ -785,9 +789,10 @@
 		length += packet_get_data_length(next);
 		free(last_header);
-		header->flags |= IPFLAG_MORE_FRAGMENTS;
+		SET_IP_HEADER_FLAGS(header,
+		    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
 	}
 
 	header->total_length = htons(length);
-	// unnecessary for all protocols
+	/* Unnecessary for all protocols */
 	header->header_checksum = IP_HEADER_CHECKSUM(header);
 
@@ -834,6 +839,6 @@
 	new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
 	offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
-	new_header->fragment_offset_high =
-	    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
+	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(new_header,
+	    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset));
 	new_header->fragment_offset_low =
 	    IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
@@ -865,5 +870,6 @@
 		return NULL;
 	memcpy(middle, last, IP_HEADER_LENGTH(last));
-	middle->flags |= IPFLAG_MORE_FRAGMENTS;
+	SET_IP_HEADER_FLAGS(middle,
+	    (GET_IP_HEADER_FLAGS(middle) | IPFLAG_MORE_FRAGMENTS));
 	return middle;
 }
@@ -916,20 +922,20 @@
 		return ENOMEM;
 
-	// get header
+	/* Get header */
 	header = (ip_header_t *) packet_get_data(packet);
 	if (!header)
 		return EINVAL;
 
-	// fragmentation forbidden?
-	if(header->flags & IPFLAG_DONT_FRAGMENT)
+	/* Fragmentation forbidden? */
+	if(GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT)
 		return EPERM;
 
-	// create the last fragment
-	new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
+	/* Create the last fragment */
+	new_packet = packet_get_4_remote(ip_globals.net_sess, prefix, length,
 	    suffix, ((addrlen > addr_len) ? addrlen : addr_len));
 	if (!new_packet)
 		return ENOMEM;
 
-	// allocate as much as originally
+	/* Allocate as much as originally */
 	last_header = (ip_header_t *) packet_suffix(new_packet,
 	    IP_HEADER_LENGTH(header));
@@ -939,5 +945,5 @@
 	ip_create_last_header(last_header, header);
 
-	// trim the unused space
+	/* Trim the unused space */
 	rc = packet_trim(new_packet, 0,
 	    IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header));
@@ -945,5 +951,5 @@
 		return ip_release_and_return(packet, rc);
 
-	// biggest multiple of 8 lower than content
+	/* Greatest multiple of 8 lower than content */
 	// TODO even fragmentation?
 	length = length & ~0x7;
@@ -957,10 +963,11 @@
 		return ip_release_and_return(packet, rc);
 
-	// mark the first as fragmented
-	header->flags |= IPFLAG_MORE_FRAGMENTS;
-
-	// create middle framgents
+	/* Mark the first as fragmented */
+	SET_IP_HEADER_FLAGS(header,
+	    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
+
+	/* Create middle fragments */
 	while (IP_TOTAL_LENGTH(header) > length) {
-		new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
+		new_packet = packet_get_4_remote(ip_globals.net_sess, prefix,
 		    length, suffix,
 		    ((addrlen >= addr_len) ? addrlen : addr_len));
@@ -981,5 +988,5 @@
 	}
 
-	// finish the first fragment
+	/* Finish the first fragment */
 	header->header_checksum = IP_HEADER_CHECKSUM(header);
 
@@ -987,21 +994,22 @@
 }
 
-/** Checks the packet queue lengths and fragments the packets if needed.
+/** Check the packet queue lengths and fragments the packets if needed.
  *
  * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
  * be fragmented and the fragmentation is not allowed.
  *
- * @param[in,out] packet The packet or the packet queue to be checked.
- * @param[in] prefix	The minimum prefix size.
- * @param[in] content	The maximum content size.
- * @param[in] suffix	The minimum suffix size.
- * @param[in] addr_len	The minimum address length.
- * @param[in] error	The error module service.
- * @return		The packet or the packet queue of the allowed length.
- * @return		NULL if there are no packets left.
- */
-static packet_t *
-ip_split_packet(packet_t *packet, size_t prefix, size_t content, size_t suffix,
-    socklen_t addr_len, services_t error)
+ * @param[in,out] packet   Packet or the packet queue to be checked.
+ * @param[in]     prefix   Minimum prefix size.
+ * @param[in]     content  Maximum content size.
+ * @param[in]     suffix   Minimum suffix size.
+ * @param[in]     addr_len Minimum address length.
+ * @param[in]     error    Error module service.
+ *
+ * @return The packet or the packet queue of the allowed length.
+ * @return NULL if there are no packets left.
+ *
+ */
+static packet_t *ip_split_packet(packet_t *packet, size_t prefix, size_t content,
+    size_t suffix, socklen_t addr_len, services_t error)
 {
 	size_t length;
@@ -1009,8 +1017,8 @@
 	packet_t *new_packet;
 	int result;
-	int phone;
-
+	async_sess_t *sess;
+	
 	next = packet;
-	// check all packets
+	/* Check all packets */
 	while (next) {
 		length = packet_get_data_length(next);
@@ -1021,5 +1029,5 @@
 		}
 
-		// too long
+		/* Too long */
 		result = ip_fragment_packet(next, content, prefix,
 		    suffix, addr_len);
@@ -1027,18 +1035,17 @@
 			new_packet = pq_detach(next);
 			if (next == packet) {
-				// the new first packet of the queue
+				/* The new first packet of the queue */
 				packet = new_packet;
 			}
-			// fragmentation needed?
+			/* Fragmentation needed? */
 			if (result == EPERM) {
-				phone = ip_prepare_icmp_and_get_phone(
-				    error, next, NULL);
-				if (phone >= 0) {
-					// fragmentation necessary ICMP
-					icmp_destination_unreachable_msg(phone,
+				sess = ip_prepare_icmp_and_get_session(error, next, NULL);
+				if (sess) {
+					/* Fragmentation necessary ICMP */
+					icmp_destination_unreachable_msg(sess,
 					    ICMP_FRAG_NEEDED, content, next);
 				}
 			} else {
-				pq_release_remote(ip_globals.net_phone,
+				pq_release_remote(ip_globals.net_sess,
 				    packet_get_id(next));
 			}
@@ -1054,20 +1061,20 @@
 }
 
-/** Sends the packet or the packet queue via the specified route.
+/** Send the packet or the packet queue via the specified route.
  *
  * The ICMP_HOST_UNREACH error notification may be sent if route hardware
  * destination address is found.
  *
- * @param[in,out] packet The packet to be sent.
- * @param[in] netif	The target network interface.
- * @param[in] route	The target route.
- * @param[in] src	The source address.
- * @param[in] dest	The destination address.
- * @param[in] error	The error module service.
- * @return		EOK on success.
- * @return		Other error codes as defined for the arp_translate_req()
- *			function.
- * @return		Other error codes as defined for the ip_prepare_packet()
- *			function.
+ * @param[in,out] packet Packet to be sent.
+ * @param[in]     netif  Target network interface.
+ * @param[in]     route  Target route.
+ * @param[in]     src    Source address.
+ * @param[in]     dest   Destination address.
+ * @param[in]     error  Error module service.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for arp_translate_req().
+ * @return Other error codes as defined for ip_prepare_packet().
+ *
  */
 static int ip_send_route(packet_t *packet, ip_netif_t *netif,
@@ -1077,8 +1084,8 @@
 	measured_string_t *translation;
 	uint8_t *data;
-	int phone;
+	async_sess_t *sess;
 	int rc;
 
-	// get destination hardware address
+	/* Get destination hardware address */
 	if (netif->arp && (route->address.s_addr != dest.s_addr)) {
 		destination.value = route->gateway.s_addr ?
@@ -1086,8 +1093,8 @@
 		destination.length = sizeof(dest.s_addr);
 
-		rc = arp_translate_req(netif->arp->phone, netif->device_id,
+		rc = arp_translate_req(netif->arp->sess, netif->device_id,
 		    SERVICE_IP, &destination, &translation, &data);
 		if (rc != EOK) {
-			pq_release_remote(ip_globals.net_phone,
+			pq_release_remote(ip_globals.net_sess,
 			    packet_get_id(packet));
 			return rc;
@@ -1099,9 +1106,9 @@
 				free(data);
 			}
-			phone = ip_prepare_icmp_and_get_phone(error, packet,
+			sess = ip_prepare_icmp_and_get_session(error, packet,
 			    NULL);
-			if (phone >= 0) {
-				// unreachable ICMP if no routing
-				icmp_destination_unreachable_msg(phone,
+			if (sess) {
+				/* Unreachable ICMP if no routing */
+				icmp_destination_unreachable_msg(sess,
 				    ICMP_HOST_UNREACH, 0, packet);
 			}
@@ -1115,5 +1122,5 @@
 	rc = ip_prepare_packet(src, dest, packet, translation);
 	if (rc != EOK) {
-		pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
 	} else {
 		packet = ip_split_packet(packet, netif->packet_dimension.prefix,
@@ -1122,5 +1129,5 @@
 		    netif->packet_dimension.addr_len, error);
 		if (packet) {
-			nil_send_msg(netif->phone, netif->device_id, packet,
+			nil_send_msg(netif->sess, netif->device_id, packet,
 			    SERVICE_IP);
 		}
@@ -1135,6 +1142,6 @@
 }
 
-static int ip_send_msg_local(int il_phone, device_id_t device_id,
-    packet_t *packet, services_t sender, services_t error)
+static int ip_send_msg_local(device_id_t device_id, packet_t *packet,
+    services_t sender, services_t error)
 {
 	int addrlen;
@@ -1145,9 +1152,11 @@
 	in_addr_t *dest;
 	in_addr_t *src;
-	int phone;
+	async_sess_t *sess;
 	int rc;
 
-	// addresses in the host byte order
-	// should be the next hop address or the target destination address
+	/*
+	 * Addresses in the host byte order
+	 * Should be the next hop address or the target destination address
+	 */
 	addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
 	if (addrlen < 0)
@@ -1174,5 +1183,5 @@
 	fibril_rwlock_read_lock(&ip_globals.netifs_lock);
 
-	// device specified?
+	/* Device specified? */
 	if (device_id > 0) {
 		netif = ip_netifs_find(&ip_globals.netifs, device_id);
@@ -1188,8 +1197,8 @@
 	if (!netif || !route) {
 		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-		phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
-		if (phone >= 0) {
-			// unreachable ICMP if no routing
-			icmp_destination_unreachable_msg(phone,
+		sess = ip_prepare_icmp_and_get_session(error, packet, NULL);
+		if (sess) {
+			/* Unreachable ICMP if no routing */
+			icmp_destination_unreachable_msg(sess,
 			    ICMP_NET_UNREACH, 0, packet);
 		}
@@ -1198,6 +1207,8 @@
 
 	if (error) {
-		// do not send for broadcast, anycast packets or network
-		// broadcast
+		/*
+		 * Do not send for broadcast, anycast packets or network
+		 * broadcast.
+		 */
 		if (!dest->s_addr || !(~dest->s_addr) ||
 		    !(~((dest->s_addr & ~route->netmask.s_addr) |
@@ -1208,8 +1219,8 @@
 	}
 	
-	// if the local host is the destination
+	/* If the local host is the destination */
 	if ((route->address.s_addr == dest->s_addr) &&
 	    (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
-		// find the loopback device to deliver
+		/* Find the loopback device to deliver */
 		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
 		route = ip_find_route(*dest);
@@ -1217,9 +1228,9 @@
 		if (!netif || !route) {
 			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-			phone = ip_prepare_icmp_and_get_phone(error, packet,
+			sess = ip_prepare_icmp_and_get_session(error, packet,
 			    NULL);
-			if (phone >= 0) {
-				// unreachable ICMP if no routing
-				icmp_destination_unreachable_msg(phone,
+			if (sess) {
+				/* Unreachable ICMP if no routing */
+				icmp_destination_unreachable_msg(sess,
 				    ICMP_HOST_UNREACH, 0, packet);
 			}
@@ -1252,5 +1263,5 @@
 
 	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-	// find the device
+	/* Find the device */
 	netif = ip_netifs_find(&ip_globals.netifs, device_id);
 	if (!netif) {
@@ -1305,5 +1316,5 @@
 {
 	ip_proto_t *proto;
-	int phone;
+	async_sess_t *sess;
 	services_t service;
 	tl_received_msg_t received_msg;
@@ -1315,5 +1326,5 @@
 	int rc;
 
-	if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
+	if ((GET_IP_HEADER_FLAGS(header) & IPFLAG_MORE_FRAGMENTS) ||
 	    IP_FRAGMENT_OFFSET(header)) {
 		// TODO fragmented
@@ -1321,5 +1332,5 @@
 	}
 	
-	switch (header->version) {
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(src_in);
@@ -1344,5 +1355,5 @@
 		return ip_release_and_return(packet, rc);
 
-	// trim padding if present
+	/* Trim padding if present */
 	if (!error &&
 	    (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
@@ -1358,8 +1369,8 @@
 	if (!proto) {
 		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-		phone = ip_prepare_icmp_and_get_phone(error, packet, header);
-		if (phone >= 0) {
-			// unreachable ICMP
-			icmp_destination_unreachable_msg(phone,
+		sess = ip_prepare_icmp_and_get_session(error, packet, header);
+		if (sess) {
+			/* Unreachable ICMP */
+			icmp_destination_unreachable_msg(sess,
 			    ICMP_PROT_UNREACH, 0, packet);
 		}
@@ -1373,5 +1384,5 @@
 		rc = received_msg(device_id, packet, service, error);
 	} else {
-		rc = tl_received_msg(proto->phone, device_id, packet,
+		rc = tl_received_msg(proto->sess, device_id, packet,
 		    proto->service, error);
 		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
@@ -1407,5 +1418,5 @@
 	in_addr_t dest;
 	ip_route_t *route;
-	int phone;
+	async_sess_t *sess;
 	struct sockaddr *addr;
 	struct sockaddr_in addr_in;
@@ -1417,11 +1428,11 @@
 		return ip_release_and_return(packet, ENOMEM);
 
-	// checksum
+	/* Checksum */
 	if ((header->header_checksum) &&
 	    (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
-			// checksum error ICMP
-			icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
+		sess = ip_prepare_icmp_and_get_session(0, packet, header);
+		if (sess) {
+			/* Checksum error ICMP */
+			icmp_parameter_problem_msg(sess, ICMP_PARAM_POINTER,
 			    ((size_t) ((void *) &header->header_checksum)) -
 			    ((size_t) ((void *) header)), packet);
@@ -1431,17 +1442,17 @@
 
 	if (header->ttl <= 1) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
-			// ttl exceeded ICMP
-			icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
+		sess = ip_prepare_icmp_and_get_session(0, packet, header);
+		if (sess) {
+			/* TTL exceeded ICMP */
+			icmp_time_exceeded_msg(sess, ICMP_EXC_TTL, packet);
 		}
 		return EINVAL;
 	}
 	
-	// process ipopt and get destination
+	/* Process ipopt and get destination */
 	dest = ip_get_destination(header);
 
-	// set the addrination address
-	switch (header->version) {
+	/* Set the destination address */
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(addr_in);
@@ -1462,8 +1473,8 @@
 	route = ip_find_route(dest);
 	if (!route) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
-			// unreachable ICMP
-			icmp_destination_unreachable_msg(phone,
+		sess = ip_prepare_icmp_and_get_session(0, packet, header);
+		if (sess) {
+			/* Unreachable ICMP */
+			icmp_destination_unreachable_msg(sess,
 			    ICMP_HOST_UNREACH, 0, packet);
 		}
@@ -1472,5 +1483,5 @@
 
 	if (route->address.s_addr == dest.s_addr) {
-		// local delivery
+		/* Local delivery */
 		return ip_deliver_local(device_id, packet, header, 0);
 	}
@@ -1482,8 +1493,8 @@
 	}
 
-	phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-	if (phone >= 0) {
-		// unreachable ICMP if no routing
-		icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
+	sess = ip_prepare_icmp_and_get_session(0, packet, header);
+	if (sess) {
+		/* Unreachable ICMP if no routing */
+		icmp_destination_unreachable_msg(sess, ICMP_HOST_UNREACH, 0,
 		    packet);
 	}
@@ -1492,14 +1503,14 @@
 }
 
-/** Returns the device packet dimensions for sending.
- *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[out] addr_len	The minimum reserved address length.
- * @param[out] prefix	The minimum reserved prefix size.
- * @param[out] content	The maximum content size.
- * @param[out] suffix	The minimum reserved suffix size.
- * @return		EOK on success.
+/** Return the device packet dimensions for sending.
+ *
+ * @param[in]  device_id Device identifier.
+ * @param[out] addr_len  Minimum reserved address length.
+ * @param[out] prefix    Minimum reserved prefix size.
+ * @param[out] content   Maximum content size.
+ * @param[out] suffix    Minimum reserved suffix size.
+ *
+ * @return EOK on success.
+ *
  */
 static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
@@ -1583,7 +1594,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -1599,5 +1611,5 @@
 		
 		case NET_IL_RECEIVED:
-			rc = packet_translate_remote(ip_globals.net_phone, &packet,
+			rc = packet_translate_remote(ip_globals.net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK) {
@@ -1626,22 +1638,23 @@
 }
 
-/** Registers the transport layer protocol.
+/** Register the transport layer protocol.
  *
  * The traffic of this protocol will be supplied using either the receive
  * function or IPC message.
  *
- * @param[in] protocol	The transport layer module protocol.
- * @param[in] service	The transport layer module service.
- * @param[in] phone	The transport layer module phone.
- * @param[in] received_msg The receiving function.
- * @return		EOK on success.
- * @return		EINVAL if the protocol parameter and/or the service
- *			parameter is zero.
- * @return		EINVAL if the phone parameter is not a positive number
- *			and the tl_receive_msg is NULL.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int
-ip_register(int protocol, services_t service, int phone,
+ * @param[in] protocol     Transport layer module protocol.
+ * @param[in] service      Transport layer module service.
+ * @param[in] sess         Transport layer module session.
+ * @param[in] received_msg Receiving function.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the protocol parameter and/or the service
+ *         parameter is zero.
+ * @return EINVAL if the phone parameter is not a positive number
+ *         and the tl_receive_msg is NULL.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+static int ip_register(int protocol, services_t service, async_sess_t *sess,
     tl_received_msg_t received_msg)
 {
@@ -1649,7 +1662,7 @@
 	int index;
 
-	if (!protocol || !service || ((phone < 0) && !received_msg))
+	if ((!protocol) || (!service) || ((!sess) && (!received_msg)))
 		return EINVAL;
-
+	
 	proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
 	if (!proto)
@@ -1658,5 +1671,5 @@
 	proto->protocol = protocol;
 	proto->service = service;
-	proto->phone = phone;
+	proto->sess = sess;
 	proto->received_msg = received_msg;
 
@@ -1670,13 +1683,11 @@
 	fibril_rwlock_write_unlock(&ip_globals.protos_lock);
 
-	printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
-	    NAME, proto->protocol, proto->phone);
+	printf("%s: Protocol registered (protocol: %d)\n",
+	    NAME, proto->protocol);
 
 	return EOK;
 }
 
-
-static int
-ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
+static int ip_add_route_req_local(device_id_t device_id, in_addr_t address,
     in_addr_t netmask, in_addr_t gateway)
 {
@@ -1712,6 +1723,5 @@
 }
 
-static int
-ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
+static int ip_set_gateway_req_local(device_id_t device_id, in_addr_t gateway)
 {
 	ip_netif_t *netif;
@@ -1737,16 +1747,15 @@
 /** Notify the IP module about the received error notification packet.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The received packet or the received packet queue.
- * @param[in] target	The target internetwork module service to be
- *			delivered to.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- *
- */
-static int
-ip_received_error_msg_local(int ip_phone, device_id_t device_id,
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
+ * @param[in] target    Target internetwork module service to be
+ *                      delivered to.
+ * @param[in] error     Packet error reporting service. Prefixes the
+ *                      received packet.
+ *
+ * @return EOK on success.
+ *
+ */
+static int ip_received_error_msg_local(device_id_t device_id,
     packet_t *packet, services_t target, services_t error)
 {
@@ -1770,8 +1779,8 @@
 		header = (ip_header_t *)(data + offset);
 
-		// destination host unreachable?
+		/* Destination host unreachable? */
 		if ((type != ICMP_DEST_UNREACH) ||
 		    (code != ICMP_HOST_UNREACH)) {
-		    	// no, something else
+			/* No, something else */
 			break;
 		}
@@ -1787,11 +1796,11 @@
 		route = ip_routes_get_index(&netif->routes, 0);
 
-		// from the same network?
+		/* From the same network? */
 		if (route && ((route->address.s_addr & route->netmask.s_addr) ==
 		    (header->destination_address & route->netmask.s_addr))) {
-			// clear the ARP mapping if any
+			/* Clear the ARP mapping if any */
 			address.value = (uint8_t *) &header->destination_address;
 			address.length = sizeof(header->destination_address);
-			arp_clear_address_req(netif->arp->phone,
+			arp_clear_address_req(netif->arp->sess,
 			    netif->device_id, SERVICE_IP, &address);
 		}
@@ -1807,6 +1816,5 @@
 }
 
-static int
-ip_get_route_req_local(int ip_phone, ip_protocol_t protocol,
+static int ip_get_route_req_local(ip_protocol_t protocol,
     const struct sockaddr *destination, socklen_t addrlen,
     device_id_t *device_id, void **header, size_t *headerlen)
@@ -1844,8 +1852,8 @@
 	fibril_rwlock_read_lock(&ip_globals.lock);
 	route = ip_find_route(*dest);
-	// if the local host is the destination
+	/* If the local host is the destination */
 	if (route && (route->address.s_addr == dest->s_addr) &&
 	    (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
-		// find the loopback device to deliver
+		/* Find the loopback device to deliver */
 		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
 		route = ip_find_route(*dest);
@@ -1905,31 +1913,34 @@
 	
 	*answer_count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
+		    callback, NULL);
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
-	case IPC_M_CONNECT_TO_ME:
-		return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
-		    IPC_GET_PHONE(*call), NULL);
-	
 	case NET_IP_DEVICE:
-		return ip_device_req_local(0, IPC_GET_DEVICE(*call),
+		return ip_device_req_local(IPC_GET_DEVICE(*call),
 		    IPC_GET_SERVICE(*call));
 	
 	case NET_IP_RECEIVED_ERROR:
-		rc = packet_translate_remote(ip_globals.net_phone, &packet,
+		rc = packet_translate_remote(ip_globals.net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return ip_received_error_msg_local(0, IPC_GET_DEVICE(*call),
+		return ip_received_error_msg_local(IPC_GET_DEVICE(*call),
 		    packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
 	
 	case NET_IP_ADD_ROUTE:
-		return ip_add_route_req_local(0, IPC_GET_DEVICE(*call),
+		return ip_add_route_req_local(IPC_GET_DEVICE(*call),
 		    IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
 		    IP_GET_GATEWAY(*call));
 
 	case NET_IP_SET_GATEWAY:
-		return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call),
+		return ip_set_gateway_req_local(IPC_GET_DEVICE(*call),
 		    IP_GET_GATEWAY(*call));
 
@@ -1940,5 +1951,5 @@
 			return rc;
 		
-		rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(*call), addr,
+		rc = ip_get_route_req_local(IP_GET_PROTOCOL(*call), addr,
 		    (socklen_t) addrlen, &device_id, &header, &headerlen);
 		if (rc != EOK)
@@ -1971,10 +1982,10 @@
 	
 	case NET_IP_SEND:
-		rc = packet_translate_remote(ip_globals.net_phone, &packet,
+		rc = packet_translate_remote(ip_globals.net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
 		
-		return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
+		return ip_send_msg_local(IPC_GET_DEVICE(*call), packet, 0,
 		    IPC_GET_ERROR(*call));
 	}
Index: uspace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/il/ip/ip.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #define NET_IP_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
@@ -98,6 +99,6 @@
 	/** Packet dimension. */
 	packet_dimension_t packet_dimension;
-	/** Netif module phone. */
-	int phone;
+	/** Netif module session. */
+	async_sess_t *sess;
 	/** Routing table. */
 	ip_routes_t routes;
@@ -112,6 +113,6 @@
 /** IP protocol specific data. */
 struct ip_proto {
-	/** Protocol module phone. */
-	int phone;
+	/** Protocol module session. */
+	async_sess_t *sess;
 	/** Protocol number. */
 	int protocol;
@@ -142,6 +143,6 @@
 	/** Known support modules. */
 	modules_t modules;
-	/** Networking module phone. */
-	int net_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
 	/** Registered network interfaces. */
 	ip_netifs_t netifs;
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/net/net.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,4 @@
  */
 
-#include "net.h"
-
 #include <async.h>
 #include <ctype.h>
@@ -46,5 +44,5 @@
 #include <str.h>
 #include <str_error.h>
-
+#include <ns.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -52,18 +50,16 @@
 #include <ipc/il.h>
 #include <ipc/nil.h>
-
 #include <net/modules.h>
 #include <net/packet.h>
 #include <net/device.h>
-
 #include <adt/char_map.h>
 #include <adt/generic_char_map.h>
 #include <adt/measured_strings.h>
 #include <adt/module_map.h>
-
 #include <netif_remote.h>
 #include <nil_remote.h>
 #include <net_interface.h>
 #include <ip_interface.h>
+#include "net.h"
 
 /** Networking module name. */
@@ -289,12 +285,15 @@
 	if (rc != EOK)
 		return rc;
+	
 	rc = add_module(NULL, &net_globals.modules, (uint8_t *) NE2000_NAME,
 	    (uint8_t *) NE2000_FILENAME, SERVICE_NE2000, 0, connect_to_service);
 	if (rc != EOK)
 		return rc;
+	
 	rc = add_module(NULL, &net_globals.modules, (uint8_t *) ETHERNET_NAME,
 	    (uint8_t *) ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service);
 	if (rc != EOK)
 		return rc;
+	
 	rc = add_module(NULL, &net_globals.modules, (uint8_t *) NILDUMMY_NAME,
 	    (uint8_t *) NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service);
@@ -336,5 +335,5 @@
 		goto out;
 	
-	rc = async_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, NULL);
+	rc = service_register(SERVICE_NETWORKING);
 	if (rc != EOK)
 		goto out;
@@ -390,5 +389,5 @@
 }
 
-int net_get_conf_req(int net_phone, measured_string_t **configuration,
+static int net_get_conf_req_local(measured_string_t **configuration,
     size_t count, uint8_t **data)
 {
@@ -399,5 +398,5 @@
 }
 
-int net_get_device_conf_req(int net_phone, device_id_t device_id,
+static int net_get_device_conf_req_local(device_id_t device_id,
     measured_string_t **configuration, size_t count, uint8_t **data)
 {
@@ -475,5 +474,5 @@
 	uintptr_t io = setting ? strtol((char *) setting->value, NULL, 16) : 0;
 	
-	rc = netif_probe_req(netif->driver->phone, netif->id, irq, (void *) io);
+	rc = netif_probe_req(netif->driver->sess, netif->id, irq, (void *) io);
 	if (rc != EOK)
 		return rc;
@@ -488,6 +487,5 @@
 		
 		int mtu = setting ? strtol((char *) setting->value, NULL, 10) : 0;
-		
-		rc = nil_device_req(netif->nil->phone, netif->id, mtu,
+		rc = nil_device_req(netif->nil->sess, netif->id, mtu,
 		    netif->driver->service);
 		if (rc != EOK)
@@ -499,16 +497,9 @@
 	
 	/* Inter-network layer startup */
-	switch (netif->il->service) {
-	case SERVICE_IP:
-		rc = ip_device_req(netif->il->phone, netif->id,
-		    internet_service);
-		if (rc != EOK)
-			return rc;
-		break;
-	default:
-		return ENOENT;
-	}
-	
-	return netif_start_req(netif->driver->phone, netif->id);
+	rc = ip_device_req(netif->il->sess, netif->id, internet_service);
+	if (rc != EOK)
+		return rc;
+	
+	return netif_start_req(netif->driver->sess, netif->id);
 }
 
@@ -552,5 +543,5 @@
 		rc = read_netif_configuration(conf_files[i], netif);
 		if (rc != EOK) {
-			measured_strings_destroy(&netif->configuration);
+			measured_strings_destroy(&netif->configuration, free);
 			free(netif);
 			return rc;
@@ -562,5 +553,5 @@
 		if (!setting) {
 			fprintf(stderr, "%s: Network interface name is missing\n", NAME);
-			measured_strings_destroy(&netif->configuration);
+			measured_strings_destroy(&netif->configuration, free);
 			free(netif);
 			return EINVAL;
@@ -571,5 +562,5 @@
 		int index = netifs_add(&net_globals.netifs, netif->id, netif);
 		if (index < 0) {
-			measured_strings_destroy(&netif->configuration);
+			measured_strings_destroy(&netif->configuration, free);
 			free(netif);
 			return index;
@@ -583,6 +574,6 @@
 		    index);
 		if (rc != EOK) {
-			measured_strings_destroy(&netif->configuration);
-			netifs_exclude_index(&net_globals.netifs, index);
+			measured_strings_destroy(&netif->configuration, free);
+			netifs_exclude_index(&net_globals.netifs, index, free);
 			return rc;
 		}
@@ -590,10 +581,9 @@
 		rc = start_device(netif);
 		if (rc != EOK) {
-			printf("%s: Error starting interface %s (%s)\n", NAME,
+			printf("%s: Ignoring failed interface %s (%s)\n", NAME,
 			    netif->name, str_error(rc));
-			measured_strings_destroy(&netif->configuration);
-			netifs_exclude_index(&net_globals.netifs, index);
-			
-			return rc;
+			measured_strings_destroy(&netif->configuration, free);
+			netifs_exclude_index(&net_globals.netifs, index, free);
+			continue;
 		}
 		
@@ -636,7 +626,9 @@
 	
 	*answer_count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
 	case NET_NET_GET_DEVICE_CONF:
 		rc = measured_strings_receive(&strings, &data,
@@ -644,5 +636,5 @@
 		if (rc != EOK)
 			return rc;
-		net_get_device_conf_req(0, IPC_GET_DEVICE(*call), &strings,
+		net_get_device_conf_req_local(IPC_GET_DEVICE(*call), &strings,
 		    IPC_GET_COUNT(*call), NULL);
 		
@@ -658,5 +650,5 @@
 		if (rc != EOK)
 			return rc;
-		net_get_conf_req(0, &strings, IPC_GET_COUNT(*call), NULL);
+		net_get_conf_req_local(&strings, IPC_GET_COUNT(*call), NULL);
 		
 		/* Strings should not contain received data anymore */
@@ -675,9 +667,11 @@
 /** Default thread for new connections.
  *
- * @param[in] iid The initial message identifier.
+ * @param[in] iid   The initial message identifier.
  * @param[in] icall The initial message call structure.
- *
- */
-static void net_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in] arg   Local argument.
+ *
+ */
+static void net_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	/*
@@ -701,5 +695,5 @@
 		
 		/* End if told to either by the message or the processing result */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
 			return;
 		
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/netif/lo/lo.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,4 +39,5 @@
 #include <stdio.h>
 #include <str.h>
+#include <ns.h>
 #include <ipc/services.h>
 #include <ipc/nil.h>
@@ -147,5 +148,4 @@
 	null_device_stats((device_stats_t *) (*device)->specific);
 	(*device)->device_id = device_id;
-	(*device)->nil_phone = -1;
 	(*device)->state = NETIF_STOPPED;
 	int index = netif_device_map_add(&netif_globals.device_map,
@@ -164,5 +164,5 @@
 int netif_initialize(void)
 {
-	return async_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, NULL);
+	return service_register(SERVICE_LO);
 }
 
@@ -201,8 +201,8 @@
 	} while (next);
 	
-	int phone = device->nil_phone;
+	async_sess_t *nil_sess = netif_globals.nil_sess;
 	fibril_rwlock_write_unlock(&netif_globals.lock);
 	
-	nil_received_msg(phone, device_id, packet, sender);
+	nil_received_msg(nil_sess, device_id, packet, sender);
 	
 	fibril_rwlock_write_lock(&netif_globals.lock);
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/nil/eth/eth.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -59,5 +59,4 @@
 #include <packet_remote.h>
 #include <nil_skel.h>
-
 #include "eth.h"
 
@@ -168,5 +167,5 @@
 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
 
-int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
+int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
 {
 	int index;
@@ -177,6 +176,6 @@
 	    index--) {
 		proto = eth_protos_get_index(&eth_globals.protos, index);
-		if (proto && proto->phone) {
-			il_device_state_msg(proto->phone, device_id, state,
+		if ((proto) && (proto->sess)) {
+			il_device_state_msg(proto->sess, device_id, state,
 			    proto->service);
 		}
@@ -187,5 +186,5 @@
 }
 
-int nil_initialize(int net_phone)
+int nil_initialize(async_sess_t *sess)
 {
 	int rc;
@@ -196,5 +195,5 @@
 	fibril_rwlock_write_lock(&eth_globals.devices_lock);
 	fibril_rwlock_write_lock(&eth_globals.protos_lock);
-	eth_globals.net_phone = net_phone;
+	eth_globals.net_sess = sess;
 
 	eth_globals.broadcast_addr =
@@ -214,5 +213,5 @@
 	if (rc != EOK) {
 		free(eth_globals.broadcast_addr);
-		eth_devices_destroy(&eth_globals.devices);
+		eth_devices_destroy(&eth_globals.devices, free);
 	}
 out:
@@ -223,11 +222,13 @@
 }
 
-/** Processes IPC messages from the registered device driver modules in an
+/** Process IPC messages from the registered device driver modules in an
  * infinite loop.
  *
- * @param[in] iid	The message identifier.
- * @param[in,out] icall	The message parameters.
- */
-static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     iid   Message identifier.
+ * @param[in,out] icall Message parameters.
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -237,14 +238,14 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_NIL_DEVICE_STATE:
-			nil_device_state_msg_local(0, IPC_GET_DEVICE(*icall),
+			nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
 			    IPC_GET_STATE(*icall));
 			async_answer_0(iid, EOK);
 			break;
 		case NET_NIL_RECEIVED:
-			rc = packet_translate_remote(eth_globals.net_phone,
+			rc = packet_translate_remote(eth_globals.net_sess,
 			    &packet, IPC_GET_PACKET(*icall));
 			if (rc == EOK)
-				rc = nil_received_msg_local(0,
-				    IPC_GET_DEVICE(*icall), packet, 0);
+				rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
+				    packet, 0);
 			
 			async_answer_0(iid, (sysarg_t) rc);
@@ -322,6 +323,6 @@
 			proto = eth_protos_get_index(&eth_globals.protos,
 			    index);
-			if (proto->phone) {
-				il_mtu_changed_msg(proto->phone,
+			if (proto->sess) {
+				il_mtu_changed_msg(proto->sess,
 				    device->device_id, device->mtu,
 				    proto->service);
@@ -347,5 +348,5 @@
 
 	configuration = &names[0];
-	rc = net_get_device_conf_req(eth_globals.net_phone, device->device_id,
+	rc = net_get_device_conf_req(eth_globals.net_sess, device->device_id,
 	    &configuration, count, &data);
 	if (rc != EOK) {
@@ -376,14 +377,14 @@
 	
 	/* Bind the device driver */
-	device->phone = netif_bind_service(device->service, device->device_id,
+	device->sess = netif_bind_service(device->service, device->device_id,
 	    SERVICE_ETHERNET, eth_receiver);
-	if (device->phone < 0) {
+	if (device->sess == NULL) {
 		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
 		free(device);
-		return device->phone;
+		return ENOENT;
 	}
 	
 	/* Get hardware address */
-	rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,
+	rc = netif_get_addr_req(device->sess, device->device_id, &device->addr,
 	    &device->addr_data);
 	if (rc != EOK) {
@@ -505,6 +506,6 @@
 }
 
-int nil_received_msg_local(int nil_phone, device_id_t device_id,
-    packet_t *packet, services_t target)
+int nil_received_msg_local(device_id_t device_id, packet_t *packet,
+    services_t target)
 {
 	eth_proto_t *proto;
@@ -528,9 +529,9 @@
 		proto = eth_process_packet(flags, packet);
 		if (proto) {
-			il_received_msg(proto->phone, device_id, packet,
+			il_received_msg(proto->sess, device_id, packet,
 			    proto->service);
 		} else {
-			// drop invalid/unknown
-			pq_release_remote(eth_globals.net_phone,
+			/* Drop invalid/unknown */
+			pq_release_remote(eth_globals.net_sess,
 			    packet_get_id(packet));
 		}
@@ -611,15 +612,17 @@
 }
 
-/** Registers receiving module service.
- *
- * Passes received packets for this service.
- *
- * @param[in] service	The module service.
- * @param[in] phone	The service phone.
- * @return		EOK on success.
- * @return		ENOENT if the service is not known.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int eth_register_message(services_t service, int phone)
+/** Register receiving module service.
+ *
+ * Pass received packets for this service.
+ *
+ * @param[in] service Module service.
+ * @param[in] sess    Service session.
+ *
+ * @return EOK on success.
+ * @return ENOENT if the service is not known.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+static int eth_register_message(services_t service, async_sess_t *sess)
 {
 	eth_proto_t *proto;
@@ -634,5 +637,5 @@
 	proto = eth_protos_find(&eth_globals.protos, protocol);
 	if (proto) {
-		proto->phone = phone;
+		proto->sess = sess;
 		fibril_rwlock_write_unlock(&eth_globals.protos_lock);
 		return EOK;
@@ -646,5 +649,5 @@
 		proto->service = service;
 		proto->protocol = protocol;
-		proto->phone = phone;
+		proto->sess = sess;
 
 		index = eth_protos_add(&eth_globals.protos, protocol, proto);
@@ -656,6 +659,6 @@
 	}
 	
-	printf("%s: Protocol registered (protocol: %d, service: %d, phone: "
-	    "%d)\n", NAME, proto->protocol, proto->service, proto->phone);
+	printf("%s: Protocol registered (protocol: %d, service: %d)\n",
+	    NAME, proto->protocol, proto->service);
 	
 	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
@@ -795,5 +798,5 @@
 	ethertype = htons(protocol_map(SERVICE_ETHERNET, sender));
 	if (!ethertype) {
-		pq_release_remote(eth_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
 		return EINVAL;
 	}
@@ -816,5 +819,5 @@
 			if (next == packet)
 				packet = tmp;
-			pq_release_remote(eth_globals.net_phone,
+			pq_release_remote(eth_globals.net_sess,
 			    packet_get_id(next));
 			next = tmp;
@@ -826,5 +829,5 @@
 	/* Send packet queue */
 	if (packet) {
-		netif_send_msg(device->phone, device_id, packet,
+		netif_send_msg(device->sess, device_id, packet,
 		    SERVICE_ETHERNET);
 	}
@@ -846,13 +849,19 @@
 	
 	*answer_count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return eth_register_message(NIL_GET_PROTO(*call), callback);
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
 	case NET_NIL_DEVICE:
 		return eth_device_message(IPC_GET_DEVICE(*call),
 		    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
 	case NET_NIL_SEND:
-		rc = packet_translate_remote(eth_globals.net_phone, &packet,
+		rc = packet_translate_remote(eth_globals.net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -883,7 +892,4 @@
 			return EOK;
 		return measured_strings_reply(address, 1);
-	case IPC_M_CONNECT_TO_ME:
-		return eth_register_message(NIL_GET_PROTO(*call),
-		    IPC_GET_PHONE(*call));
 	}
 	
Index: uspace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/nil/eth/eth.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,7 +38,7 @@
 #define NET_ETH_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <adt/measured_strings.h>
@@ -223,6 +223,6 @@
 	/** Device driver service. */
 	services_t service;
-	/** Driver phone. */
-	int phone;
+	/** Driver session. */
+	async_sess_t *sess;
 	/** Maximal transmission unit. */
 	size_t mtu;
@@ -248,12 +248,12 @@
 	/** Protocol identifier. */
 	int protocol;
-	/** Protocol module phone. */
-	int phone;
+	/** Protocol module session. */
+	async_sess_t *sess;
 };
 
 /** Ethernet global data. */
 struct eth_globals {
-	/** Networking module phone. */
-	int net_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
 	/** Safety lock for devices. */
 	fibril_rwlock_t devices_lock;
@@ -265,5 +265,5 @@
 	/**
 	 * Protocol map.
-	 * Service phone map for each protocol.
+	 * Service map for each protocol.
 	 */
 	eth_protos_t protos;
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -44,5 +44,4 @@
 #include <ipc/net.h>
 #include <ipc/services.h>
-
 #include <net/modules.h>
 #include <net/device.h>
@@ -53,5 +52,4 @@
 #include <netif_remote.h>
 #include <nil_skel.h>
-
 #include "nildummy.h"
 
@@ -67,9 +65,9 @@
 DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
 
-int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
+int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
 {
 	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-	if (nildummy_globals.proto.phone)
-		il_device_state_msg(nildummy_globals.proto.phone, device_id,
+	if (nildummy_globals.proto.sess)
+		il_device_state_msg(nildummy_globals.proto.sess, device_id,
 		    state, nildummy_globals.proto.service);
 	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
@@ -78,5 +76,5 @@
 }
 
-int nil_initialize(int net_phone)
+int nil_initialize(async_sess_t *sess)
 {
 	fibril_rwlock_initialize(&nildummy_globals.devices_lock);
@@ -85,6 +83,6 @@
 	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
 	
-	nildummy_globals.net_phone = net_phone;
-	nildummy_globals.proto.phone = 0;
+	nildummy_globals.net_sess = sess;
+	nildummy_globals.proto.sess = NULL;
 	int rc = nildummy_devices_initialize(&nildummy_globals.devices);
 	
@@ -99,7 +97,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     arg    Local argument.
+ *
+ */
+static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -109,15 +108,15 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_NIL_DEVICE_STATE:
-			rc = nil_device_state_msg_local(0,
-			    IPC_GET_DEVICE(*icall), IPC_GET_STATE(*icall));
+			rc = nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
+			    IPC_GET_STATE(*icall));
 			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
 		case NET_NIL_RECEIVED:
-			rc = packet_translate_remote(nildummy_globals.net_phone,
+			rc = packet_translate_remote(nildummy_globals.net_sess,
 			    &packet, IPC_GET_PACKET(*icall));
 			if (rc == EOK)
-				rc = nil_received_msg_local(0,
-				    IPC_GET_DEVICE(*icall), packet, 0);
+				rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
+				    packet, 0);
 			
 			async_answer_0(iid, (sysarg_t) rc);
@@ -177,6 +176,6 @@
 		/* Notify the upper layer module */
 		fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-		if (nildummy_globals.proto.phone) {
-			il_mtu_changed_msg(nildummy_globals.proto.phone,
+		if (nildummy_globals.proto.sess) {
+			il_mtu_changed_msg(nildummy_globals.proto.sess,
 			    device->device_id, device->mtu,
 			    nildummy_globals.proto.service);
@@ -200,14 +199,14 @@
 
 	/* Bind the device driver */
-	device->phone = netif_bind_service(device->service, device->device_id,
+	device->sess = netif_bind_service(device->service, device->device_id,
 	    SERVICE_ETHERNET, nildummy_receiver);
-	if (device->phone < 0) {
+	if (device->sess == NULL) {
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
 		free(device);
-		return device->phone;
+		return ENOENT;
 	}
 	
 	/* Get hardware address */
-	int rc = netif_get_addr_req(device->phone, device->device_id,
+	int rc = netif_get_addr_req(device->sess, device->device_id,
 	    &device->addr, &device->addr_data);
 	if (rc != EOK) {
@@ -304,13 +303,13 @@
 }
 
-int nil_received_msg_local(int nil_phone, device_id_t device_id,
-    packet_t *packet, services_t target)
+int nil_received_msg_local(device_id_t device_id, packet_t *packet,
+    services_t target)
 {
 	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
 	
-	if (nildummy_globals.proto.phone) {
+	if (nildummy_globals.proto.sess) {
 		do {
 			packet_t *next = pq_detach(packet);
-			il_received_msg(nildummy_globals.proto.phone, device_id,
+			il_received_msg(nildummy_globals.proto.sess, device_id,
 			    packet, nildummy_globals.proto.service);
 			packet = next;
@@ -328,5 +327,5 @@
  *
  * @param[in] service Module service.
- * @param[in] phone   Service phone.
+ * @param[in] sess    Service session.
  *
  * @return EOK on success.
@@ -335,12 +334,12 @@
  *
  */
-static int nildummy_register_message(services_t service, int phone)
+static int nildummy_register_message(services_t service, async_sess_t *sess)
 {
 	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
 	nildummy_globals.proto.service = service;
-	nildummy_globals.proto.phone = phone;
-	
-	printf("%s: Protocol registered (service: %d, phone: %d)\n",
-	    NAME, nildummy_globals.proto.service, nildummy_globals.proto.phone);
+	nildummy_globals.proto.sess = sess;
+	
+	printf("%s: Protocol registered (service: %d)\n",
+	    NAME, nildummy_globals.proto.service);
 	
 	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
@@ -373,5 +372,5 @@
 	/* Send packet queue */
 	if (packet)
-		netif_send_msg(device->phone, device_id, packet,
+		netif_send_msg(device->sess, device_id, packet,
 		    SERVICE_NILDUMMY);
 	
@@ -393,8 +392,14 @@
 	
 	*answer_count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return nildummy_register_message(NIL_GET_PROTO(*call), callback);
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
 	case NET_NIL_DEVICE:
 		return nildummy_device_message(IPC_GET_DEVICE(*call),
@@ -402,5 +407,5 @@
 	
 	case NET_NIL_SEND:
-		rc = packet_translate_remote(nildummy_globals.net_phone,
+		rc = packet_translate_remote(nildummy_globals.net_sess,
 		    &packet, IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -432,8 +437,4 @@
 			return rc;
 		return measured_strings_reply(address, 1);
-	
-	case IPC_M_CONNECT_TO_ME:
-		return nildummy_register_message(NIL_GET_PROTO(*call),
-		    IPC_GET_PHONE(*call));
 	}
 	
Index: uspace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,7 +38,7 @@
 #define NET_NILDUMMY_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <adt/measured_strings.h>
@@ -81,6 +81,6 @@
 	services_t service;
 	
-	/** Driver phone. */
-	int phone;
+	/** Driver session. */
+	async_sess_t *sess;
 	
 	/** Maximal transmission unit. */
@@ -99,12 +99,12 @@
 	services_t service;
 	
-	/** Protocol module phone. */
-	int phone;
+	/** Protocol module session. */
+	async_sess_t *sess;
 };
 
 /** Dummy nil global data. */
 struct nildummy_globals {
-	/** Networking module phone. */
-	int net_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
 	
 	/** Lock for devices. */
Index: uspace/srv/net/tl/icmp/Makefile
===================================================================
--- uspace/srv/net/tl/icmp/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/tl/icmp/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -32,4 +32,5 @@
 EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
 BINARY = icmp
+STATIC_ONLY = y
 
 SOURCES = \
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -118,6 +118,6 @@
 
 /** Global data */
-static int phone_net = -1;
-static int phone_ip = -1;
+static async_sess_t *net_sess = NULL;
+static async_sess_t *ip_sess = NULL;
 static bool error_reporting = true;
 static bool echo_replying = true;
@@ -173,5 +173,5 @@
 static void icmp_release(packet_t *packet)
 {
-	pq_release_remote(phone_net, packet_get_id(packet));
+	pq_release_remote(net_sess, packet_get_id(packet));
 }
 
@@ -225,5 +225,5 @@
 	}
 	
-	return ip_send_msg(phone_ip, -1, packet, SERVICE_ICMP, error);
+	return ip_send_msg(ip_sess, -1, packet, SERVICE_ICMP, error);
 }
 
@@ -297,5 +297,5 @@
 	size_t length = (size_t) addrlen;
 	
-	packet_t *packet = packet_get_4_remote(phone_net, size,
+	packet_t *packet = packet_get_4_remote(net_sess, size,
 	    icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
 	    icmp_dimension.suffix);
@@ -595,5 +595,5 @@
 	case ICMP_SKIP:
 	case ICMP_PHOTURIS:
-		ip_received_error_msg(phone_ip, -1, packet,
+		ip_received_error_msg(ip_sess, -1, packet,
 		    SERVICE_IP, SERVICE_ICMP);
 		return EOK;
@@ -608,16 +608,19 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
-{
-	bool loop = true;
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
 	packet_t *packet;
 	int rc;
 	
-	while (loop) {
+	while (true) {
+		if (!IPC_GET_IMETHOD(*icall))
+			break;
+		
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(phone_net, &packet,
+			rc = packet_translate_remote(net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK) {
@@ -629,7 +632,4 @@
 			async_answer_0(iid, (sysarg_t) rc);
 			break;
-		case IPC_M_PHONE_HUNGUP:
-			loop = false;
-			continue;
 		default:
 			async_answer_0(iid, (sysarg_t) ENOTSUP);
@@ -642,5 +642,5 @@
 /** Initialize the ICMP module.
  *
- * @param[in] net_phone Network module phone.
+ * @param[in] sess Network module session.
  *
  * @return EOK on success.
@@ -648,5 +648,5 @@
  *
  */
-int tl_initialize(int net_phone)
+int tl_initialize(async_sess_t *sess)
 {
 	measured_string_t names[] = {
@@ -670,11 +670,11 @@
 	atomic_set(&icmp_client, 0);
 	
-	phone_net = net_phone;
-	phone_ip = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
+	net_sess = sess;
+	ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
 	    icmp_receiver);
-	if (phone_ip < 0)
-		return phone_ip;
-	
-	int rc = ip_packet_size_req(phone_ip, -1, &icmp_dimension);
+	if (ip_sess == NULL)
+		return ENOENT;
+	
+	int rc = ip_packet_size_req(ip_sess, -1, &icmp_dimension);
 	if (rc != EOK)
 		return rc;
@@ -685,5 +685,5 @@
 	/* Get configuration */
 	configuration = &names[0];
-	rc = net_get_conf_req(phone_net, &configuration, count, &data);
+	rc = net_get_conf_req(net_sess, &configuration, count, &data);
 	if (rc != EOK)
 		return rc;
@@ -763,5 +763,5 @@
 	
 	case NET_ICMP_DEST_UNREACH:
-		rc = packet_translate_remote(phone_net, &packet,
+		rc = packet_translate_remote(net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -772,5 +772,5 @@
 	
 	case NET_ICMP_SOURCE_QUENCH:
-		rc = packet_translate_remote(phone_net, &packet,
+		rc = packet_translate_remote(net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -780,5 +780,5 @@
 	
 	case NET_ICMP_TIME_EXCEEDED:
-		rc = packet_translate_remote(phone_net, &packet,
+		rc = packet_translate_remote(net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -788,5 +788,5 @@
 	
 	case NET_ICMP_PARAMETERPROB:
-		rc = packet_translate_remote(phone_net, &packet,
+		rc = packet_translate_remote(net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -206,5 +206,6 @@
 
 static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t);
-static int tcp_process_client_messages(ipc_callid_t, ipc_call_t);
+static int tcp_process_client_messages(async_sess_t *, ipc_callid_t,
+    ipc_call_t);
 
 static int tcp_listen_message(socket_cores_t *, int, int);
@@ -299,7 +300,8 @@
 		return tcp_release_and_return(packet, NO_DATA);
 
-//      printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header),
-//	    ntohs(header->destination_port));
-
+#if 0
+	printf("header len %d, port %d \n", TCP_HEADER_LENGTH(header),
+	    ntohs(header->destination_port));
+#endif
 	result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
 	if (result <= 0)
@@ -323,7 +325,7 @@
 
 	if (!socket) {
-		if (tl_prepare_icmp_packet(tcp_globals.net_phone,
-		    tcp_globals.icmp_phone, packet, error) == EOK) {
-			icmp_destination_unreachable_msg(tcp_globals.icmp_phone,
+		if (tl_prepare_icmp_packet(tcp_globals.net_sess,
+		    tcp_globals.icmp_sess, packet, error) == EOK) {
+			icmp_destination_unreachable_msg(tcp_globals.icmp_sess,
 			    ICMP_PORT_UNREACH, 0, packet);
 		}
@@ -396,9 +398,9 @@
 		fibril_rwlock_write_unlock(socket_data->local_lock);
 
-		rc = tl_prepare_icmp_packet(tcp_globals.net_phone,
-		    tcp_globals.icmp_phone, packet, error);
+		rc = tl_prepare_icmp_packet(tcp_globals.net_sess,
+		    tcp_globals.icmp_sess, packet, error);
 		if (rc == EOK) {
 			/* Checksum error ICMP */
-			icmp_parameter_problem_msg(tcp_globals.icmp_phone,
+			icmp_parameter_problem_msg(tcp_globals.icmp_sess,
 			    ICMP_PARAM_POINTER,
 			    ((size_t) ((void *) &header->checksum)) -
@@ -438,5 +440,5 @@
 		break;
 	default:
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 	}
 
@@ -475,5 +477,5 @@
 	old_incoming = socket_data->next_incoming;
 
-	if (header->finalize) {
+	if (GET_TCP_HEADER_FINALIZE(header)) {
 		socket_data->fin_incoming = new_sequence_number +
 		    total_length - TCP_HEADER_LENGTH(header);
@@ -501,5 +503,5 @@
 			/* Release the acknowledged packets */
 			next_packet = pq_next(packet);
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(packet));
 			packet = next_packet;
@@ -560,5 +562,5 @@
 			next_packet = pq_next(next_packet);
 			pq_insert_after(tmp_packet, next_packet);
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(tmp_packet));
 		}
@@ -597,5 +599,5 @@
 				if (packet == socket_data->incoming)
 					socket_data->incoming = next_packet;
-				pq_release_remote(tcp_globals.net_phone,
+				pq_release_remote(tcp_globals.net_sess,
 				    packet_get_id(packet));
 				packet = next_packet;
@@ -620,5 +622,5 @@
 				if (length <= 0) {
 					/* Remove the empty packet */
-					pq_release_remote(tcp_globals.net_phone,
+					pq_release_remote(tcp_globals.net_sess,
 					    packet_get_id(packet));
 					packet = next_packet;
@@ -667,5 +669,5 @@
 				}
 				/* Remove the duplicit or corrupted packet */
-				pq_release_remote(tcp_globals.net_phone,
+				pq_release_remote(tcp_globals.net_sess,
 				    packet_get_id(packet));
 				packet = next_packet;
@@ -694,7 +696,7 @@
 		if (rc != EOK) {
 			/* Remove the corrupted packets */
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(packet));
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(next_packet));
 		} else {
@@ -707,10 +709,10 @@
 				    new_sequence_number, length);
 				if (rc != EOK) {
-					pq_release_remote(tcp_globals.net_phone,
+					pq_release_remote(tcp_globals.net_sess,
 					    packet_get_id(next_packet));
 				}
 				rc = pq_insert_after(packet, next_packet);
 				if (rc != EOK) {
-					pq_release_remote(tcp_globals.net_phone,
+					pq_release_remote(tcp_globals.net_sess,
 					    packet_get_id(next_packet));
 				}
@@ -721,5 +723,5 @@
 		printf("unexpected\n");
 		/* Release duplicite or restricted */
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		forced_ack = true;
 	}
@@ -789,5 +791,5 @@
 	if (rc != EOK)
 		return tcp_release_and_return(packet, rc);
-	rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+	rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 	    &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
 	if (rc != EOK)
@@ -798,9 +800,10 @@
 
 	/* Notify the destination socket */
-	async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
-	    (sysarg_t) socket->socket_id,
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
 	    ((packet_dimension->content < socket_data->data_fragment_size) ?
 	    packet_dimension->content : socket_data->data_fragment_size), 0, 0,
 	    (sysarg_t) fragments);
+	async_exchange_end(exch);
 
 	return EOK;
@@ -819,8 +822,8 @@
 
 	/* Notify the destination socket */
-	async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
-	    (sysarg_t) socket->socket_id,
-	    0, 0, 0,
-	    (sysarg_t) 0 /* 0 fragments == no more data */);
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
+	    0, 0, 0, (sysarg_t) 0 /* 0 fragments == no more data */);
+	async_exchange_end(exch);
 }
 
@@ -837,5 +840,5 @@
 	assert(packet);
 
-	if (!header->synchronize)
+	if (!GET_TCP_HEADER_SYNCHRONIZE(header))
 		return tcp_release_and_return(packet, EINVAL);
 	
@@ -848,5 +851,5 @@
 	next_packet = pq_detach(packet);
 	if (next_packet) {
-		pq_release_remote(tcp_globals.net_phone,
+		pq_release_remote(tcp_globals.net_sess,
 		    packet_get_id(next_packet));
 	}
@@ -902,5 +905,5 @@
 	assert(packet);
 
-	if (!header->synchronize)
+	if (!GET_TCP_HEADER_SYNCHRONIZE(header))
 		return tcp_release_and_return(packet, EINVAL);
 
@@ -935,5 +938,5 @@
 	/* Create a socket */
 	socket_id = -1;
-	rc = socket_create(socket_data->local_sockets, listening_socket->phone,
+	rc = socket_create(socket_data->local_sockets, listening_socket->sess,
 	    socket_data, &socket_id);
 	if (rc != EOK) {
@@ -988,5 +991,5 @@
 	fibril_rwlock_write_unlock(&tcp_globals.lock);
 	if (rc != EOK) {
-		socket_destroy(tcp_globals.net_phone, socket->socket_id,
+		socket_destroy(tcp_globals.net_sess, socket->socket_id,
 		    socket_data->local_sockets, &tcp_globals.sockets,
 		    tcp_free_socket_data);
@@ -1000,5 +1003,5 @@
 	next_packet = pq_detach(packet);
 	if (next_packet) {
-		pq_release_remote(tcp_globals.net_phone,
+		pq_release_remote(tcp_globals.net_sess,
 		    packet_get_id(next_packet));
 	}
@@ -1009,5 +1012,5 @@
 		    packet_get_data_length(packet) - sizeof(*header));
 		if (rc != EOK) {
-			socket_destroy(tcp_globals.net_phone, socket->socket_id,
+			socket_destroy(tcp_globals.net_sess, socket->socket_id,
 			    socket_data->local_sockets, &tcp_globals.sockets,
 			    tcp_free_socket_data);
@@ -1020,5 +1023,5 @@
 	rc = tcp_queue_packet(socket, socket_data, packet, 1);
 	if (rc != EOK) {
-		socket_destroy(tcp_globals.net_phone, socket->socket_id,
+		socket_destroy(tcp_globals.net_sess, socket->socket_id,
 		    socket_data->local_sockets, &tcp_globals.sockets,
 		    tcp_free_socket_data);
@@ -1028,5 +1031,5 @@
 	packet = tcp_get_packets_to_send(socket, socket_data);
 	if (!packet) {
-		socket_destroy(tcp_globals.net_phone, socket->socket_id,
+		socket_destroy(tcp_globals.net_sess, socket->socket_id,
 		    socket_data->local_sockets, &tcp_globals.sockets,
 		    tcp_free_socket_data);
@@ -1056,5 +1059,5 @@
 	assert(packet);
 
-	if (!header->acknowledge)
+	if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
 		return tcp_release_and_return(packet, EINVAL);
 
@@ -1062,6 +1065,6 @@
 	tcp_process_acknowledgement(socket, socket_data, header);
 
-	socket_data->next_incoming = ntohl(header->sequence_number);	// + 1;
-	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	socket_data->next_incoming = ntohl(header->sequence_number); /* + 1; */
+	pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 	socket_data->state = TCP_SOCKET_ESTABLISHED;
 	listening_socket = socket_cores_find(socket_data->local_sockets,
@@ -1077,8 +1080,10 @@
 		if (rc == EOK) {
 			/* Notify the destination socket */
-			async_msg_5(socket->phone, NET_SOCKET_ACCEPTED,
+			async_exch_t *exch = async_exchange_begin(socket->sess);
+			async_msg_5(exch, NET_SOCKET_ACCEPTED,
 			    (sysarg_t) listening_socket->socket_id,
 			    socket_data->data_fragment_size, TCP_HEADER_SIZE,
 			    0, (sysarg_t) socket->socket_id);
+			async_exchange_end(exch);
 
 			fibril_rwlock_write_unlock(socket_data->local_lock);
@@ -1125,5 +1130,5 @@
 	assert(header);
 
-	if (!header->acknowledge)
+	if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
 		return;
 
@@ -1176,5 +1181,5 @@
 				/* Add to acknowledged or release */
 				if (pq_add(&acknowledged, packet, 0, 0) != EOK)
-					pq_release_remote(tcp_globals.net_phone,
+					pq_release_remote(tcp_globals.net_sess,
 					    packet_get_id(packet));
 				packet = next;
@@ -1185,5 +1190,5 @@
 		/* Release acknowledged */
 		if (acknowledged) {
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(acknowledged));
 		}
@@ -1229,11 +1234,12 @@
 	assert(answer);
 	assert(answer_count);
-
+	
 	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_CONNECT_TO_ME:
-		return tcp_process_client_messages(callid, *call);
-	}
-
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return tcp_process_client_messages(callback, callid, *call);
+	
 	return ENOTSUP;
 }
@@ -1265,10 +1271,9 @@
 }
 
-int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
+int tcp_process_client_messages(async_sess_t *sess, ipc_callid_t callid,
+    ipc_call_t call)
 {
 	int res;
-	bool keep_on_going = true;
 	socket_cores_t local_sockets;
-	int app_phone = IPC_GET_PHONE(call);
 	struct sockaddr *addr;
 	int socket_id;
@@ -1292,5 +1297,5 @@
 	fibril_rwlock_initialize(&lock);
 
-	while (keep_on_going) {
+	while (true) {
 
 		/* Answer the call */
@@ -1300,12 +1305,12 @@
 		/* Get the next call */
 		callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			res = EHANGUP;
+			break;
+		}
 
 		/* Process the call */
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			keep_on_going = false;
-			res = EHANGUP;
-			break;
-
 		case NET_SOCKET:
 			socket_data =
@@ -1321,5 +1326,5 @@
 			fibril_rwlock_write_lock(&lock);
 			socket_id = SOCKET_GET_SOCKET_ID(call);
-			res = socket_create(&local_sockets, app_phone,
+			res = socket_create(&local_sockets, sess,
 			    socket_data, &socket_id);
 			SOCKET_SET_SOCKET_ID(answer, socket_id);
@@ -1329,5 +1334,5 @@
 				break;
 			}
-			if (tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+			if (tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 			    &tcp_globals.dimensions, DEVICE_INVALID_ID,
 			    &packet_dimension) == EOK) {
@@ -1504,10 +1509,10 @@
 	}
 
-	/* Release the application phone */
-	async_hangup(app_phone);
+	/* Release the application session */
+	async_hangup(sess);
 
 	printf("release\n");
 	/* Release all local sockets */
-	socket_cores_release(tcp_globals.net_phone, &local_sockets,
+	socket_cores_release(tcp_globals.net_sess, &local_sockets,
 	    &tcp_globals.sockets, tcp_free_socket_data);
 
@@ -1617,5 +1622,5 @@
 			local_lock = socket_data->local_lock;
 			fibril_rwlock_write_lock(local_lock);
-			socket_destroy(tcp_globals.net_phone,
+			socket_destroy(tcp_globals.net_sess,
 			    timeout->socket_id, timeout->local_sockets,
 			    &tcp_globals.sockets, tcp_free_socket_data);
@@ -1707,5 +1712,5 @@
 		if (socket->port > 0) {
 			socket_ports_exclude(&tcp_globals.sockets,
-			    socket->port);
+			    socket->port, free);
 			socket->port = 0;
 		}
@@ -1750,5 +1755,5 @@
 	}
 
-	rc = ip_get_route_req(tcp_globals.ip_phone, IPPROTO_TCP,
+	rc = ip_get_route_req(tcp_globals.ip_sess, IPPROTO_TCP,
 	    addr, addrlen, &socket_data->device_id,
 	    &socket_data->pseudo_header, &socket_data->headerlen);
@@ -1832,5 +1837,5 @@
 
 	/* Remember the outgoing FIN */
-	if (header->finalize) 
+	if (GET_TCP_HEADER_FINALIZE(header))
 		socket_data->fin_outgoing = socket_data->next_outgoing;
 	
@@ -1898,5 +1903,5 @@
 			rc = pq_insert_after(previous, copy);
 			if (rc != EOK) {
-				pq_release_remote(tcp_globals.net_phone,
+				pq_release_remote(tcp_globals.net_sess,
 				    packet_get_id(copy));
 				return sending;
@@ -1935,5 +1940,5 @@
 	    socket_data->headerlen, packet_get_data_length(packet));
 	if (rc != EOK) {
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		return NULL;
 	}
@@ -1942,5 +1947,5 @@
 	header = (tcp_header_t *) packet_get_data(packet);
 	if (!header) {
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		return NULL;
 	}
@@ -1951,5 +1956,5 @@
 		header->acknowledgement_number =
 		    htonl(socket_data->next_incoming);
-		header->acknowledge = 1;
+		SET_TCP_HEADER_ACKNOWLEDGE(header, 1);
 	}
 	header->window = htons(socket_data->window);
@@ -1967,5 +1972,5 @@
 	rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
 	if (rc != EOK) {
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		return NULL;
 	}
@@ -1974,5 +1979,5 @@
 	    sequence_number, socket_data->state, socket_data->timeout, true);
 	if (rc != EOK) {
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		return NULL;
 	}
@@ -1991,5 +1996,5 @@
 
 	/* Make a copy of the packet */
-	copy = packet_get_copy(tcp_globals.net_phone, packet);
+	copy = packet_get_copy(tcp_globals.net_sess, packet);
 	if (!copy)
 		return NULL;
@@ -2005,5 +2010,5 @@
 	while (packet) {
 		next = pq_detach(packet);
-		ip_send_msg(tcp_globals.ip_phone, device_id, packet,
+		ip_send_msg(tcp_globals.ip_sess, device_id, packet,
 		    SERVICE_TCP, 0);
 		packet = next;
@@ -2023,7 +2028,8 @@
 	header->source_port = htons(socket->port);
 	header->source_port = htons(socket_data->dest_port);
-	header->header_length = TCP_COMPUTE_HEADER_LENGTH(sizeof(*header));
-	header->synchronize = synchronize;
-	header->finalize = finalize;
+	SET_TCP_HEADER_LENGTH(header,
+	    TCP_COMPUTE_HEADER_LENGTH(sizeof(*header)));
+	SET_TCP_HEADER_SYNCHRONIZE(header, synchronize);
+	SET_TCP_HEADER_FINALIZE(header, finalize);
 }
 
@@ -2117,5 +2123,5 @@
 		return NO_DATA;
 
-	rc = packet_translate_remote(tcp_globals.net_phone, &packet, packet_id);
+	rc = packet_translate_remote(tcp_globals.net_sess, &packet, packet_id);
 	if (rc != EOK)
 		return rc;
@@ -2128,5 +2134,5 @@
 	/* Release the packet */
 	dyn_fifo_pop(&socket->received);
-	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 
 	/* Return the total length */
@@ -2166,5 +2172,5 @@
 		return ENOTCONN;
 
-	rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+	rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 	    &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
 	if (rc != EOK)
@@ -2177,5 +2183,5 @@
 	for (index = 0; index < fragments; index++) {
 		/* Read the data fragment */
-		result = tl_socket_read_packet_data(tcp_globals.net_phone,
+		result = tl_socket_read_packet_data(tcp_globals.net_sess,
 		    &packet, TCP_HEADER_SIZE, packet_dimension,
 		    socket_data->addr, socket_data->addrlen);
@@ -2240,5 +2246,5 @@
 	default:
 		/* Just destroy */
-		rc = socket_destroy(tcp_globals.net_phone, socket_id,
+		rc = socket_destroy(tcp_globals.net_sess, socket_id,
 		    local_sockets, &tcp_globals.sockets,
 		    tcp_free_socket_data);
@@ -2288,5 +2294,5 @@
 
 	/* Get the device packet dimension */
-	rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+	rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 	    &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
 	if (rc != EOK)
@@ -2294,5 +2300,5 @@
 
 	/* Get a new packet */
-	*packet = packet_get_4_remote(tcp_globals.net_phone, TCP_HEADER_SIZE,
+	*packet = packet_get_4_remote(tcp_globals.net_sess, TCP_HEADER_SIZE,
 	    packet_dimension->addr_len, packet_dimension->prefix,
 	    packet_dimension->suffix);
@@ -2357,5 +2363,5 @@
 			if (rc != EOK)
 				return rc;
-			rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+			rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 			    &tcp_globals.dimensions, socket_data->device_id,
 			    &packet_dimension);
@@ -2429,5 +2435,5 @@
 int tcp_release_and_return(packet_t *packet, int result)
 {
-	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 	return result;
 }
@@ -2437,7 +2443,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
+ * @param[in]     arg   Local argument.
  *
  */
-static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -2447,5 +2454,5 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(tcp_globals.net_phone, &packet,
+			rc = packet_translate_remote(tcp_globals.net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK)
@@ -2465,5 +2472,5 @@
 /** Initialize the TCP module.
  *
- * @param[in] net_phone Network module phone.
+ * @param[in] sess Network module session.
  *
  * @return EOK on success.
@@ -2471,17 +2478,17 @@
  *
  */
-int tl_initialize(int net_phone)
+int tl_initialize(async_sess_t *sess)
 {
 	fibril_rwlock_initialize(&tcp_globals.lock);
 	fibril_rwlock_write_lock(&tcp_globals.lock);
 	
-	tcp_globals.net_phone = net_phone;
+	tcp_globals.net_sess = sess;
 	
-	tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
-	tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
+	tcp_globals.icmp_sess = icmp_connect_module();
+	tcp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
 	    SERVICE_TCP, tcp_receiver);
-	if (tcp_globals.ip_phone < 0) {
+	if (tcp_globals.ip_sess == NULL) {
 		fibril_rwlock_write_unlock(&tcp_globals.lock);
-		return tcp_globals.ip_phone;
+		return ENOENT;
 	}
 	
@@ -2492,5 +2499,5 @@
 	rc = packet_dimensions_initialize(&tcp_globals.dimensions);
 	if (rc != EOK) {
-		socket_ports_destroy(&tcp_globals.sockets);
+		socket_ports_destroy(&tcp_globals.sockets, free);
 		goto out;
 	}
Index: uspace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/tl/tcp/tcp.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,6 +38,6 @@
 #define NET_TCP_H_
 
+#include <async.h>
 #include <fibril_synch.h>
-
 #include <net/packet.h>
 #include <net/device.h>
@@ -190,7 +190,4 @@
 	int backlog;
 	
-//	/** Segment size. */
-//	size_t segment_size;
-
 	/**
 	 * Parent listening socket identifier.
@@ -287,10 +284,10 @@
 /** TCP global data. */
 struct tcp_globals {
-	/** Networking module phone. */
-	int net_phone;
-	/** IP module phone. */
-	int ip_phone;
-	/** ICMP module phone. */
-	int icmp_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
+	/** IP module session. */
+	async_sess_t *ip_sess;
+	/** ICMP module session. */
+	async_sess_t *icmp_sess;
 	/** Last used free port. */
 	int last_used_port;
Index: uspace/srv/net/tl/tcp/tcp_header.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_header.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/tl/tcp/tcp_header.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -47,5 +47,5 @@
  * @param[in] header The TCP packet header.
  */
-#define TCP_HEADER_LENGTH(header)		((header)->header_length * 4U)
+#define TCP_HEADER_LENGTH(header)		(GET_TCP_HEADER_LENGTH(header) * 4U)
 
 /** Returns the TCP header length.
@@ -73,30 +73,63 @@
 	uint32_t sequence_number;
 	uint32_t acknowledgement_number;
-	
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t header_length:4;
-	uint8_t reserved1:4;
-#else
-	uint8_t reserved1:4;
-	uint8_t header_length:4;
-#endif
 
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t reserved2:2;
-	uint8_t urgent:1;
-	uint8_t acknowledge:1;
-	uint8_t push:1;
-	uint8_t reset:1;
-	uint8_t synchronize:1;
-	uint8_t finalize:1;
-#else
-	uint8_t finalize:1;
-	uint8_t synchronize:1;
-	uint8_t reset:1;
-	uint8_t push:1;
-	uint8_t acknowledge:1;
-	uint8_t urgent:1;
-	uint8_t reserved2:2;
-#endif
+	uint8_t hlr; /* header length, reserved1 */
+
+#define GET_TCP_HEADER_LENGTH(header) \
+	(((header)->hlr & 0xf0) >> 4)
+#define SET_TCP_HEADER_LENGTH(header, length) \
+	((header)->hlr = \
+	 ((length & 0x0f) << 4) | ((header)->hlr & 0x0f))
+
+#define GET_TCP_HEADER_RESERVED1(header) \
+	((header)->hlr & 0x0f)
+#define SET_TCP_HEADER_RESERVED1(header, reserved1) \
+	((header)->hlr = \
+	 (reserved1 & 0x0f) | ((header)->hlr & 0xf0))
+
+	/* reserved2, urgent, acknowledge, push, reset, synchronize, finalize */
+	uint8_t ruaprsf;  
+
+#define GET_TCP_HEADER_RESERVED2(header) \
+	(((header)->ruaprsf & 0xc0) >> 6)
+#define SET_TCP_HEADER_RESERVED2(header, reserved2) \
+	((header)->ruaprsf = \
+	 ((reserved2 & 0x03) << 6) | ((header)->ruaprsf & 0x3f))
+
+#define GET_TCP_HEADER_URGENT(header) \
+	(((header)->ruaprsf & 0x20) >> 5)
+#define SET_TCP_HEADER_URGENT(header, urgent) \
+	((header)->ruaprsf = \
+	 ((urgent & 0x01) << 5) | ((header)->ruaprsf & 0xdf))
+
+#define GET_TCP_HEADER_ACKNOWLEDGE(header) \
+	(((header)->ruaprsf & 0x10) >> 4)
+#define SET_TCP_HEADER_ACKNOWLEDGE(header, acknowledge) \
+	((header)->ruaprsf = \
+	 ((acknowledge & 0x01) << 4) | ((header)->ruaprsf & 0xef))
+
+#define GET_TCP_HEADER_PUSH(header) \
+	(((header)->ruaprsf & 0x08) >> 3)
+#define SET_TCP_HEADER_PUSH(header, push) \
+	((header)->ruaprsf = \
+	 ((push & 0x01) << 3) | ((header)->ruaprsf & 0xf7))
+
+#define GET_TCP_HEADER_RESET(header) \
+	(((header)->ruaprsf & 0x04) >> 2)
+#define SET_TCP_HEADER_RESET(header, reset) \
+	((header)->ruaprsf = \
+	 ((reset & 0x01) << 2) | ((header)->ruaprsf & 0xfb))
+
+#define GET_TCP_HEADER_SYNCHRONIZE(header) \
+	(((header)->ruaprsf & 0x02) >> 1)
+#define SET_TCP_HEADER_SYNCHRONIZE(header, synchronize) \
+	((header)->ruaprsf = \
+	 ((synchronize & 0x01) << 1) | ((header)->ruaprsf & 0xfd))
+
+#define GET_TCP_HEADER_FINALIZE(header) \
+	((header)->ruaprsf & 0x01)
+#define SET_TCP_HEADER_FINALIZE(header, finalize) \
+	((header)->ruaprsf = \
+	 (finalize & 0x01) | ((header)->ruaprsf & 0xfe))
 
 	uint16_t window;
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/tl/udp/udp.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -99,5 +99,5 @@
 static int udp_release_and_return(packet_t *packet, int result)
 {
-	pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(udp_globals.net_sess, packet_get_id(packet));
 	return result;
 }
@@ -192,7 +192,7 @@
 	    ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
 	if (!socket) {
-		if (tl_prepare_icmp_packet(udp_globals.net_phone,
-		    udp_globals.icmp_phone, packet, error) == EOK) {
-			icmp_destination_unreachable_msg(udp_globals.icmp_phone,
+		if (tl_prepare_icmp_packet(udp_globals.net_sess,
+		    udp_globals.icmp_sess, packet, error) == EOK) {
+			icmp_destination_unreachable_msg(udp_globals.icmp_sess,
 			    ICMP_PORT_UNREACH, 0, packet);
 		}
@@ -251,5 +251,5 @@
 			while (tmp_packet) {
 				next_packet = pq_detach(tmp_packet);
-				pq_release_remote(udp_globals.net_phone,
+				pq_release_remote(udp_globals.net_sess,
 				    packet_get_id(tmp_packet));
 				tmp_packet = next_packet;
@@ -274,9 +274,9 @@
 		if (flip_checksum(compact_checksum(checksum)) !=
 		    IP_CHECKSUM_ZERO) {
-			if (tl_prepare_icmp_packet(udp_globals.net_phone,
-			    udp_globals.icmp_phone, packet, error) == EOK) {
+			if (tl_prepare_icmp_packet(udp_globals.net_sess,
+			    udp_globals.icmp_sess, packet, error) == EOK) {
 				/* Checksum error ICMP */
 				icmp_parameter_problem_msg(
-				    udp_globals.icmp_phone, ICMP_PARAM_POINTER,
+				    udp_globals.icmp_sess, ICMP_PARAM_POINTER,
 				    ((size_t) ((void *) &header->checksum)) -
 				    ((size_t) ((void *) header)), packet);
@@ -292,5 +292,5 @@
 		return udp_release_and_return(packet, rc);
 		
-	rc = tl_get_ip_packet_dimension(udp_globals.ip_phone,
+	rc = tl_get_ip_packet_dimension(udp_globals.ip_sess,
 	    &udp_globals.dimensions, device_id, &packet_dimension);
 	if (rc != EOK)
@@ -299,7 +299,9 @@
 	/* Notify the destination socket */
 	fibril_rwlock_write_unlock(&udp_globals.lock);
-	async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
-	    (sysarg_t) socket->socket_id, packet_dimension->content, 0, 0,
-	    (sysarg_t) fragments);
+	
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
+	    packet_dimension->content, 0, 0, (sysarg_t) fragments);
+	async_exchange_end(exch);
 
 	return EOK;
@@ -337,7 +339,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -347,5 +350,5 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(udp_globals.net_phone, &packet,
+			rc = packet_translate_remote(udp_globals.net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK)
@@ -365,5 +368,5 @@
 /** Initialize the UDP module.
  *
- * @param[in] net_phone Network module phone.
+ * @param[in] sess Network module session.
  *
  * @return EOK on success.
@@ -371,5 +374,5 @@
  *
  */
-int tl_initialize(int net_phone)
+int tl_initialize(async_sess_t *sess)
 {
 	measured_string_t names[] = {
@@ -390,17 +393,16 @@
 	fibril_rwlock_write_lock(&udp_globals.lock);
 	
-	udp_globals.net_phone = net_phone;
-	
-	udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
-	
-	udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
-	    SERVICE_UDP, udp_receiver);
-	if (udp_globals.ip_phone < 0) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return udp_globals.ip_phone;
+	udp_globals.net_sess = sess;
+	udp_globals.icmp_sess = icmp_connect_module();
+	
+	udp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
+	     SERVICE_UDP, udp_receiver);
+	if (udp_globals.ip_sess == NULL) {
+	    fibril_rwlock_write_unlock(&udp_globals.lock);
+	    return ENOENT;
 	}
 	
 	/* Read default packet dimensions */
-	int rc = ip_packet_size_req(udp_globals.ip_phone, -1,
+	int rc = ip_packet_size_req(udp_globals.ip_sess, -1,
 	    &udp_globals.packet_dimension);
 	if (rc != EOK) {
@@ -417,5 +419,5 @@
 	rc = packet_dimensions_initialize(&udp_globals.dimensions);
 	if (rc != EOK) {
-		socket_ports_destroy(&udp_globals.sockets);
+		socket_ports_destroy(&udp_globals.sockets, free);
 		fibril_rwlock_write_unlock(&udp_globals.lock);
 		return rc;
@@ -431,8 +433,8 @@
 	/* Get configuration */
 	configuration = &names[0];
-	rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,
+	rc = net_get_conf_req(udp_globals.net_sess, &configuration, count,
 	    &data);
 	if (rc != EOK) {
-		socket_ports_destroy(&udp_globals.sockets);
+		socket_ports_destroy(&udp_globals.sockets, free);
 		fibril_rwlock_write_unlock(&udp_globals.lock);
 		return rc;
@@ -499,5 +501,9 @@
 	device_id_t device_id;
 	packet_dimension_t *packet_dimension;
+	size_t size;
 	int rc;
+
+	/* In case of error, do not update the data fragment size. */
+	*data_fragment_size = 0;
 	
 	rc = tl_get_address_port(addr, addrlen, &dest_port);
@@ -521,10 +527,10 @@
 
 	if (udp_globals.checksum_computing) {
-		rc = ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr,
+		rc = ip_get_route_req(udp_globals.ip_sess, IPPROTO_UDP, addr,
 		    addrlen, &device_id, &ip_header, &headerlen);
 		if (rc != EOK)
 			return rc;
 		/* Get the device packet dimension */
-//		rc = tl_get_ip_packet_dimension(udp_globals.ip_phone,
+//		rc = tl_get_ip_packet_dimension(udp_globals.ip_sess,
 //		    &udp_globals.dimensions, device_id, &packet_dimension);
 //		if (rc != EOK)
@@ -533,5 +539,5 @@
 //	} else {
 		/* Do not ask all the time */
-		rc = ip_packet_size_req(udp_globals.ip_phone, -1,
+		rc = ip_packet_size_req(udp_globals.ip_sess, -1,
 		    &udp_globals.packet_dimension);
 		if (rc != EOK)
@@ -540,6 +546,16 @@
 //	}
 
+	/*
+	 * Update the data fragment size based on what the lower layers can
+	 * handle without fragmentation, but not more than the maximum allowed
+	 * for UDP.
+	 */
+	size = MAX_UDP_FRAGMENT_SIZE;
+	if (packet_dimension->content < size)
+	    size = packet_dimension->content;
+	*data_fragment_size = size;
+
 	/* Read the first packet fragment */
-	result = tl_socket_read_packet_data(udp_globals.net_phone, &packet,
+	result = tl_socket_read_packet_data(udp_globals.net_sess, &packet,
 	    UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
 	if (result < 0)
@@ -562,5 +578,5 @@
 	/* Read the rest of the packet fragments */
 	for (index = 1; index < fragments; index++) {
-		result = tl_socket_read_packet_data(udp_globals.net_phone,
+		result = tl_socket_read_packet_data(udp_globals.net_sess,
 		    &next_packet, 0, packet_dimension, addr, addrlen);
 		if (result < 0)
@@ -614,5 +630,5 @@
 
 	/* Send the packet */
-	ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
+	ip_send_msg(udp_globals.ip_sess, device_id, packet, SERVICE_UDP, 0);
 
 	return EOK;
@@ -661,5 +677,5 @@
 		return NO_DATA;
 	
-	rc = packet_translate_remote(udp_globals.net_phone, &packet, packet_id);
+	rc = packet_translate_remote(udp_globals.net_sess, &packet, packet_id);
 	if (rc != EOK) {
 		(void) dyn_fifo_pop(&socket->received);
@@ -721,24 +737,26 @@
 }
 
-/** Processes the socket client messages.
- *
- * Runs until the client module disconnects.
- *
- * @param[in] callid 	The message identifier.
- * @param[in] call	The message parameters.
- * @return		EOK on success.
- *
- * @see	socket.h
- */
-static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
+/** Process the socket client messages.
+ *
+ * Run until the client module disconnects.
+ *
+ * @see socket.h
+ *
+ * @param[in] sess   Callback session.
+ * @param[in] callid Message identifier.
+ * @param[in] call   Message parameters.
+ *
+ * @return EOK on success.
+ *
+ */
+static int udp_process_client_messages(async_sess_t *sess, ipc_callid_t callid,
+    ipc_call_t call)
 {
 	int res;
-	bool keep_on_going = true;
 	socket_cores_t local_sockets;
-	int app_phone = IPC_GET_PHONE(call);
 	struct sockaddr *addr;
 	int socket_id;
 	size_t addrlen;
-	size_t size = 0;
+	size_t size;
 	ipc_call_t answer;
 	size_t answer_count;
@@ -759,5 +777,5 @@
 	socket_cores_initialize(&local_sockets);
 
-	while (keep_on_going) {
+	while (true) {
 
 		/* Answer the call */
@@ -771,13 +789,13 @@
 
 		/* Process the call */
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			keep_on_going = false;
+		if (!IPC_GET_IMETHOD(call)) {
 			res = EHANGUP;
 			break;
-
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case NET_SOCKET:
 			socket_id = SOCKET_GET_SOCKET_ID(call);
-			res = socket_create(&local_sockets, app_phone, NULL,
+			res = socket_create(&local_sockets, sess, NULL,
 			    &socket_id);
 			SOCKET_SET_SOCKET_ID(answer, socket_id);
@@ -786,13 +804,12 @@
 				break;
 			
-			if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
+			size = MAX_UDP_FRAGMENT_SIZE;
+			if (tl_get_ip_packet_dimension(udp_globals.ip_sess,
 			    &udp_globals.dimensions, DEVICE_INVALID_ID,
 			    &packet_dimension) == EOK) {
-				SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
-				    packet_dimension->content);
+				if (packet_dimension->content < size)
+					size = packet_dimension->content;
 			}
-
-//			SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
-//			    MAX_UDP_FRAGMENT_SIZE);
+			SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
 			SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
 			answer_count = 3;
@@ -852,5 +869,5 @@
 		case NET_SOCKET_CLOSE:
 			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = socket_destroy(udp_globals.net_phone,
+			res = socket_destroy(udp_globals.net_sess,
 			    SOCKET_GET_SOCKET_ID(call), &local_sockets,
 			    &udp_globals.sockets, NULL);
@@ -866,9 +883,9 @@
 	}
 
-	/* Release the application phone */
-	async_hangup(app_phone);
+	/* Release the application session */
+	async_hangup(sess);
 
 	/* Release all local sockets */
-	socket_cores_release(udp_globals.net_phone, &local_sockets,
+	socket_cores_release(udp_globals.net_sess, &local_sockets,
 	    &udp_globals.sockets, NULL);
 
@@ -900,10 +917,10 @@
 {
 	*answer_count = 0;
-
-	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_CONNECT_TO_ME:
-		return udp_process_client_messages(callid, *call);
-	}
-
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return udp_process_client_messages(callback, callid, *call);
+	
 	return ENOTSUP;
 }
Index: uspace/srv/net/tl/udp/udp.h
===================================================================
--- uspace/srv/net/tl/udp/udp.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/net/tl/udp/udp.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,4 +38,5 @@
 #define NET_UDP_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <socket_core.h>
@@ -49,10 +50,10 @@
 /** UDP global data. */
 struct udp_globals {
-	/** Networking module phone. */
-	int net_phone;
-	/** IP module phone. */
-	int ip_phone;
-	/** ICMP module phone. */
-	int icmp_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
+	/** IP module session. */
+	async_sess_t *ip_sess;
+	/** ICMP module session. */
+	async_sess_t *icmp_sess;
 	/** Packet dimension. */
 	packet_dimension_t packet_dimension;
Index: uspace/srv/ns/Makefile
===================================================================
--- uspace/srv/ns/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/ns/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../..
 BINARY = ns
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/ns/clonable.c
===================================================================
--- uspace/srv/ns/clonable.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/ns/clonable.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,5 +52,5 @@
 
 /** List of clonable-service connection requests. */
-static link_t cs_req;
+static list_t cs_req;
 
 int clonable_init(void)
@@ -76,13 +76,16 @@
     ipc_callid_t callid)
 {
-	if (list_empty(&cs_req)) {
+	link_t *req_link;
+
+	req_link = list_first(&cs_req);
+	if (req_link == NULL) {
 		/* There was no pending connection request. */
-		printf(NAME ": Unexpected clonable server.\n");
+		printf("%s: Unexpected clonable server.\n", NAME);
 		ipc_answer_0(callid, EBUSY);
 		return;
 	}
 	
-	cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);
-	list_remove(&csr->link);
+	cs_req_t *csr = list_get_instance(req_link, cs_req_t, link);
+	list_remove(req_link);
 	
 	/* Currently we can only handle a single type of clonable service. */
Index: uspace/srv/ns/service.c
===================================================================
--- uspace/srv/ns/service.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/ns/service.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -35,4 +35,6 @@
 #include <assert.h>
 #include <errno.h>
+#include <stdio.h>
+#include <malloc.h>
 #include "service.h"
 #include "ns.h"
@@ -121,5 +123,5 @@
 } pending_conn_t;
 
-static link_t pending_conn;
+static list_t pending_conn;
 
 int service_init(void)
@@ -139,8 +141,6 @@
 void process_pending_conn(void)
 {
-	link_t *cur;
-	
 loop:
-	for (cur = pending_conn.next; cur != &pending_conn; cur = cur->next) {
+	list_foreach(pending_conn, cur) {
 		pending_conn_t *pr = list_get_instance(cur, pending_conn_t, link);
 		
Index: uspace/srv/ns/task.c
===================================================================
--- uspace/srv/ns/task.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/ns/task.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -39,4 +39,5 @@
 #include <stdio.h>
 #include <macros.h>
+#include <malloc.h>
 #include "task.h"
 #include "ns.h"
@@ -188,5 +189,5 @@
 } pending_wait_t;
 
-static link_t pending_wait;
+static list_t pending_wait;
 
 int task_init(void)
@@ -211,9 +212,8 @@
 void process_pending_wait(void)
 {
-	link_t *cur;
 	task_exit_t texit;
 	
 loop:
-	for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) {
+	list_foreach(pending_wait, cur) {
 		pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
 		
Index: uspace/srv/taskmon/taskmon.c
===================================================================
--- uspace/srv/taskmon/taskmon.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/taskmon/taskmon.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -92,14 +92,15 @@
 int main(int argc, char *argv[])
 {
-	printf(NAME ": Task Monitoring Service\n");
-
+	printf("%s: Task Monitoring Service\n", NAME);
+	
 	if (event_subscribe(EVENT_FAULT, 0) != EOK) {
-		printf(NAME ": Error registering fault notifications.\n");
+		printf("%s: Error registering fault notifications.\n", NAME);
 		return -1;
 	}
-
+	
 	async_set_interrupt_received(fault_event);
+	task_retval(0);
 	async_manager();
-
+	
 	return 0;
 }
Index: uspace/srv/vfs/Makefile
===================================================================
--- uspace/srv/vfs/Makefile	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/vfs/Makefile	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../..
 BINARY = vfs
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/vfs/vfs.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -36,6 +36,9 @@
  */
 
+#include <vfs/vfs.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <abi/ipc/event.h>
+#include <event.h>
+#include <ns.h>
 #include <async.h>
 #include <errno.h>
@@ -45,12 +48,17 @@
 #include <as.h>
 #include <atomic.h>
+#include <macros.h>
 #include "vfs.h"
 
 #define NAME  "vfs"
 
-static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
+enum {
+	VFS_TASK_STATE_CHANGE
+};
+
+static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	bool keep_on_going = true;
-
+	bool cont = true;
+	
 	/*
 	 * The connection was opened via the IPC_CONNECT_ME_TO call.
@@ -59,15 +67,15 @@
 	async_answer_0(iid, EOK);
 	
-	while (keep_on_going) {
+	while (cont) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			keep_on_going = false;
-			break;
 		case VFS_IN_REGISTER:
 			vfs_register(callid, &call);
-			keep_on_going = false;
+			cont = false;
 			break;
 		case VFS_IN_MOUNT:
@@ -80,7 +88,4 @@
 			vfs_open(callid, &call);
 			break;
-		case VFS_IN_OPEN_NODE:
-			vfs_open_node(callid, &call);
-			break;
 		case VFS_IN_CLOSE:
 			vfs_close(callid, &call);
@@ -118,4 +123,8 @@
 		case VFS_IN_DUP:
 			vfs_dup(callid, &call);
+			break;
+		case VFS_IN_WAIT_HANDLE:
+			vfs_wait_handle(callid, &call);
+			break;
 		default:
 			async_answer_0(callid, ENOTSUP);
@@ -123,9 +132,24 @@
 		}
 	}
-
+	
 	/*
 	 * Open files for this client will be cleaned up when its last
 	 * connection fibril terminates.
 	 */
+}
+
+static void notification_received(ipc_callid_t callid, ipc_call_t *call)
+{
+	switch (IPC_GET_IMETHOD(*call)) {
+	case VFS_TASK_STATE_CHANGE:
+		if (IPC_GET_ARG1(*call) == VFS_PASS_HANDLE)
+			vfs_pass_handle(
+			    (task_id_t) MERGE_LOUP32(IPC_GET_ARG4(*call),
+			    IPC_GET_ARG5(*call)), call->in_task_id,
+			    (int) IPC_GET_ARG2(*call));
+		break;
+	default:
+		break;
+	}
 }
 
@@ -170,4 +194,10 @@
 
 	/*
+	 * Set notification handler and subscribe to notifications.
+	 */
+	async_set_interrupt_received(notification_received);
+	event_task_subscribe(EVENT_TASK_STATE_CHANGE, VFS_TASK_STATE_CHANGE);
+
+	/*
 	 * Register at the naming service.
 	 */
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/vfs/vfs.h	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -38,7 +38,8 @@
 #include <fibril_synch.h>
 #include <sys/types.h>
-#include <devmap.h>
+#include <loc.h>
 #include <bool.h>
 #include <ipc/vfs.h>
+#include <task.h>
 
 #ifndef dprintf
@@ -53,5 +54,5 @@
 	vfs_info_t vfs_info;
 	fs_handle_t fs_handle;
-	async_sess_t session;
+	async_sess_t *sess;
 } fs_info_t;
 
@@ -61,5 +62,5 @@
 #define VFS_PAIR \
 	fs_handle_t fs_handle; \
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 
 /**
@@ -67,5 +68,5 @@
  * doesn't contain any state. For a stateful structure, see vfs_node_t.
  *
- * @note	fs_handle, devmap_handle and index are meant to be returned in one
+ * @note	fs_handle, service_id and index are meant to be returned in one
  *		IPC reply.
  */
@@ -145,7 +146,7 @@
 extern fibril_mutex_t nodes_mutex;
 
-extern fibril_condvar_t fs_head_cv;
-extern fibril_mutex_t fs_head_lock;
-extern link_t fs_head;		/**< List of registered file systems. */
+extern fibril_condvar_t fs_list_cv;
+extern fibril_mutex_t fs_list_lock;
+extern list_t fs_list;		/**< List of registered file systems. */
 
 extern vfs_pair_t rootfs;	/**< Root file system. */
@@ -158,7 +159,7 @@
 } plb_entry_t;
 
-extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_head. */
+extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_entries. */
 extern uint8_t *plb;		/**< Path Lookup Buffer */
-extern link_t plb_head;		/**< List of active PLB entries. */
+extern list_t plb_entries;	/**< List of active PLB entries. */
 
 #define MAX_MNTOPTS_LEN		256
@@ -167,6 +168,6 @@
 extern fibril_rwlock_t namespace_rwlock;
 
-extern int vfs_grab_phone(fs_handle_t);
-extern void vfs_release_phone(fs_handle_t, int);
+extern async_exch_t *vfs_exchange_grab(fs_handle_t);
+extern void vfs_exchange_release(async_exch_t *);
 
 extern fs_handle_t fs_name_to_handle(char *, bool);
@@ -175,6 +176,4 @@
 extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *,
     vfs_pair_t *, ...);
-extern int vfs_open_node_internal(vfs_lookup_res_t *);
-extern int vfs_close_internal(vfs_file_t *);
 
 extern bool vfs_nodes_init(void);
@@ -182,5 +181,5 @@
 extern void vfs_node_put(vfs_node_t *);
 extern void vfs_node_forget(vfs_node_t *);
-extern unsigned vfs_nodes_refcount_sum_get(fs_handle_t, devmap_handle_t);
+extern unsigned vfs_nodes_refcount_sum_get(fs_handle_t, service_id_t);
 
 
@@ -189,4 +188,7 @@
 extern void *vfs_client_data_create(void);
 extern void vfs_client_data_destroy(void *);
+
+extern void vfs_pass_handle(task_id_t, task_id_t, int);
+extern int vfs_wait_handle_internal(void);
 
 extern vfs_file_t *vfs_file_get(int);
@@ -198,4 +200,5 @@
 extern void vfs_node_addref(vfs_node_t *);
 extern void vfs_node_delref(vfs_node_t *);
+extern int vfs_open_node_remote(vfs_node_t *);
 
 extern void vfs_register(ipc_callid_t, ipc_call_t *);
@@ -203,5 +206,4 @@
 extern void vfs_unmount(ipc_callid_t, ipc_call_t *);
 extern void vfs_open(ipc_callid_t, ipc_call_t *);
-extern void vfs_open_node(ipc_callid_t, ipc_call_t *);
 extern void vfs_sync(ipc_callid_t, ipc_call_t *);
 extern void vfs_dup(ipc_callid_t, ipc_call_t *);
@@ -216,4 +218,5 @@
 extern void vfs_unlink(ipc_callid_t, ipc_call_t *);
 extern void vfs_rename(ipc_callid_t, ipc_call_t *);
+extern void vfs_wait_handle(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/vfs/vfs_file.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -43,46 +43,66 @@
 #include <fibril.h>
 #include <fibril_synch.h>
+#include <adt/list.h>
+#include <task.h>
 #include "vfs.h"
 
-#define VFS_DATA	((vfs_client_data_t *) async_client_data_get())
+#define VFS_DATA	((vfs_client_data_t *) async_get_client_data())
 #define FILES		(VFS_DATA->files)
 
 typedef struct {
 	fibril_mutex_t lock;
+	fibril_condvar_t cv;
+	list_t passed_handles;
 	vfs_file_t **files;
 } vfs_client_data_t;
 
+typedef struct {
+	link_t link;
+	int handle;
+} vfs_boxed_handle_t;
+
+static int _vfs_fd_free(vfs_client_data_t *, int);
+
 /** Initialize the table of open files. */
-static bool vfs_files_init(void)
-{
-	fibril_mutex_lock(&VFS_DATA->lock);
-	if (!FILES) {
-		FILES = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
-		if (!FILES) {
-			fibril_mutex_unlock(&VFS_DATA->lock);
+static bool vfs_files_init(vfs_client_data_t *vfs_data)
+{
+	fibril_mutex_lock(&vfs_data->lock);
+	if (!vfs_data->files) {
+		vfs_data->files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
+		if (!vfs_data->files) {
+			fibril_mutex_unlock(&vfs_data->lock);
 			return false;
 		}
-		memset(FILES, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
-	}
-	fibril_mutex_unlock(&VFS_DATA->lock);
+		memset(vfs_data->files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
+	}
+	fibril_mutex_unlock(&vfs_data->lock);
 	return true;
 }
 
 /** Cleanup the table of open files. */
-static void vfs_files_done(void)
+static void vfs_files_done(vfs_client_data_t *vfs_data)
 {
 	int i;
 
-	if (!FILES)
+	if (!vfs_data->files)
 		return;
 
 	for (i = 0; i < MAX_OPEN_FILES; i++) {
-		if (FILES[i]) {
-			(void) vfs_close_internal(FILES[i]);
-			(void) vfs_fd_free(i);
-		}
-	}
-	
-	free(FILES);
+		if (vfs_data->files[i])
+			(void) _vfs_fd_free(vfs_data, i);
+	}
+	
+	free(vfs_data->files);
+
+	while (!list_empty(&vfs_data->passed_handles)) {
+		link_t *lnk;
+		vfs_boxed_handle_t *bh;
+		
+		lnk = list_first(&vfs_data->passed_handles);
+		list_remove(lnk);
+
+		bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
+		free(bh);
+	}
 }
 
@@ -94,4 +114,6 @@
 	if (vfs_data) {
 		fibril_mutex_initialize(&vfs_data->lock);
+		fibril_condvar_initialize(&vfs_data->cv);
+		list_initialize(&vfs_data->passed_handles);
 		vfs_data->files = NULL;
 	}
@@ -104,6 +126,25 @@
 	vfs_client_data_t *vfs_data = (vfs_client_data_t *) data;
 
-	vfs_files_done();
+	vfs_files_done(vfs_data);
 	free(vfs_data);
+}
+
+/** Close the file in the endpoint FS server. */
+static int vfs_file_close_remote(vfs_file_t *file)
+{
+	assert(!file->refcnt);
+	
+	async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle);
+	
+	ipc_call_t answer;
+	aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->service_id,
+	    file->node->index, &answer);
+	
+	vfs_exchange_release(exch);
+	
+	sysarg_t rc;
+	async_wait_for(msg, &rc);
+	
+	return IPC_GET_ARG1(answer);
 }
 
@@ -113,7 +154,7 @@
  *			incremented.
  */
-static void vfs_file_addref(vfs_file_t *file)
-{
-	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
+static void vfs_file_addref(vfs_client_data_t *vfs_data, vfs_file_t *file)
+{
+	assert(fibril_mutex_is_locked(&vfs_data->lock));
 
 	file->refcnt++;
@@ -125,30 +166,26 @@
  *			decremented.
  */
-static void vfs_file_delref(vfs_file_t *file)
-{
-	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
+static int vfs_file_delref(vfs_client_data_t *vfs_data, vfs_file_t *file)
+{
+	int rc = EOK;
+
+	assert(fibril_mutex_is_locked(&vfs_data->lock));
 
 	if (file->refcnt-- == 1) {
 		/*
-		 * Lost the last reference to a file, need to drop our reference
-		 * to the underlying VFS node.
+		 * Lost the last reference to a file, need to close it in the
+		 * endpoint FS and drop our reference to the underlying VFS node.
 		 */
+		rc = vfs_file_close_remote(file);
 		vfs_node_delref(file->node);
 		free(file);
 	}
-}
-
-
-/** Allocate a file descriptor.
- *
- * @param desc If true, look for an available file descriptor
- *             in a descending order.
- *
- * @return First available file descriptor or a negative error
- *         code.
- */
-int vfs_fd_alloc(bool desc)
-{
-	if (!vfs_files_init())
+
+	return rc;
+}
+
+static int _vfs_fd_alloc(vfs_client_data_t *vfs_data, bool desc)
+{
+	if (!vfs_files_init(vfs_data))
 		return ENOMEM;
 	
@@ -159,17 +196,17 @@
 		i = 0;
 	
-	fibril_mutex_lock(&VFS_DATA->lock);
+	fibril_mutex_lock(&vfs_data->lock);
 	while (true) {
-		if (!FILES[i]) {
-			FILES[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
-			if (!FILES[i]) {
-				fibril_mutex_unlock(&VFS_DATA->lock);
+		if (!vfs_data->files[i]) {
+			vfs_data->files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
+			if (!vfs_data->files[i]) {
+				fibril_mutex_unlock(&vfs_data->lock);
 				return ENOMEM;
 			}
 			
-			memset(FILES[i], 0, sizeof(vfs_file_t));
-			fibril_mutex_initialize(&FILES[i]->lock);
-			vfs_file_addref(FILES[i]);
-			fibril_mutex_unlock(&VFS_DATA->lock);
+			memset(vfs_data->files[i], 0, sizeof(vfs_file_t));
+			fibril_mutex_initialize(&vfs_data->files[i]->lock);
+			vfs_file_addref(vfs_data, vfs_data->files[i]);
+			fibril_mutex_unlock(&vfs_data->lock);
 			return (int) i;
 		}
@@ -187,7 +224,40 @@
 		}
 	}
-	fibril_mutex_unlock(&VFS_DATA->lock);
+	fibril_mutex_unlock(&vfs_data->lock);
 	
 	return EMFILE;
+}
+
+/** Allocate a file descriptor.
+ *
+ * @param desc If true, look for an available file descriptor
+ *             in a descending order.
+ *
+ * @return First available file descriptor or a negative error
+ *         code.
+ */
+int vfs_fd_alloc(bool desc)
+{
+	return _vfs_fd_alloc(VFS_DATA, desc);
+}
+
+static int _vfs_fd_free(vfs_client_data_t *vfs_data, int fd)
+{
+	int rc;
+
+	if (!vfs_files_init(vfs_data))
+		return ENOMEM;
+
+	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;
+	fibril_mutex_unlock(&vfs_data->lock);
+	
+	return rc;
 }
 
@@ -201,18 +271,5 @@
 int vfs_fd_free(int fd)
 {
-	if (!vfs_files_init())
-		return ENOMEM;
-
-	fibril_mutex_lock(&VFS_DATA->lock);	
-	if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (FILES[fd] == NULL)) {
-		fibril_mutex_unlock(&VFS_DATA->lock);
-		return EBADF;
-	}
-	
-	vfs_file_delref(FILES[fd]);
-	FILES[fd] = NULL;
-	fibril_mutex_unlock(&VFS_DATA->lock);
-	
-	return EOK;
+	return _vfs_fd_free(VFS_DATA, fd);
 }
 
@@ -228,5 +285,5 @@
 int vfs_fd_assign(vfs_file_t *file, int fd)
 {
-	if (!vfs_files_init())
+	if (!vfs_files_init(VFS_DATA))
 		return ENOMEM;
 
@@ -238,5 +295,5 @@
 	
 	FILES[fd] = file;
-	vfs_file_addref(FILES[fd]);
+	vfs_file_addref(VFS_DATA, FILES[fd]);
 	fibril_mutex_unlock(&VFS_DATA->lock);
 	
@@ -244,4 +301,23 @@
 }
 
+static vfs_file_t *_vfs_file_get(vfs_client_data_t *vfs_data, int fd)
+{
+	if (!vfs_files_init(vfs_data))
+		return NULL;
+	
+	fibril_mutex_lock(&vfs_data->lock);
+	if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
+		vfs_file_t *file = vfs_data->files[fd];
+		if (file != NULL) {
+			vfs_file_addref(vfs_data, file);
+			fibril_mutex_unlock(&vfs_data->lock);
+			return file;
+		}
+	}
+	fibril_mutex_unlock(&vfs_data->lock);
+	
+	return NULL;
+}
+
 /** Find VFS file structure for a given file descriptor.
  *
@@ -252,17 +328,12 @@
 vfs_file_t *vfs_file_get(int fd)
 {
-	if (!vfs_files_init())
-		return NULL;
-	
-	fibril_mutex_lock(&VFS_DATA->lock);
-	if ((fd >= 0) && (fd < MAX_OPEN_FILES)) {
-		vfs_file_t *file = FILES[fd];
-		vfs_file_addref(file);
-		fibril_mutex_unlock(&VFS_DATA->lock);
-		return file;
-	}
-	fibril_mutex_unlock(&VFS_DATA->lock);
-	
-	return NULL;
+	return _vfs_file_get(VFS_DATA, fd);
+}
+
+static void _vfs_file_put(vfs_client_data_t *vfs_data, vfs_file_t *file)
+{
+	fibril_mutex_lock(&vfs_data->lock);
+	vfs_file_delref(vfs_data, file);
+	fibril_mutex_unlock(&vfs_data->lock);
 }
 
@@ -273,7 +344,90 @@
 void vfs_file_put(vfs_file_t *file)
 {
-	fibril_mutex_lock(&VFS_DATA->lock);
-	vfs_file_delref(file);
-	fibril_mutex_unlock(&VFS_DATA->lock);
+	_vfs_file_put(VFS_DATA, file);
+}
+
+void vfs_pass_handle(task_id_t donor_id, task_id_t acceptor_id, int donor_fd)
+{
+	vfs_client_data_t *donor_data = NULL;
+	vfs_client_data_t *acceptor_data = NULL;
+	vfs_file_t *donor_file = NULL;
+	vfs_file_t *acceptor_file = NULL;
+	vfs_boxed_handle_t *bh;
+	int acceptor_fd;
+
+	acceptor_data = async_get_client_data_by_id(acceptor_id);
+	if (!acceptor_data)
+		return;
+
+	bh = malloc(sizeof(vfs_boxed_handle_t));
+	assert(bh);
+
+	link_initialize(&bh->link);
+	bh->handle = -1;
+
+	donor_data = async_get_client_data_by_id(donor_id);
+	if (!donor_data)
+		goto out;
+
+	donor_file = _vfs_file_get(donor_data, donor_fd);
+	if (!donor_file)
+		goto out;
+
+	acceptor_fd = _vfs_fd_alloc(acceptor_data, false);
+	if (acceptor_fd < 0)
+		goto out;
+
+	bh->handle = acceptor_fd;
+
+	/*
+	 * Add a new reference to the underlying VFS node.
+	 */
+	vfs_node_addref(donor_file->node);
+	(void) vfs_open_node_remote(donor_file->node);
+
+	acceptor_file = _vfs_file_get(acceptor_data, acceptor_fd);
+	assert(acceptor_file);
+
+	/*
+	 * Inherit attributes from the donor.
+	 */
+	acceptor_file->node = donor_file->node;
+	acceptor_file->append = donor_file->append;
+	acceptor_file->pos = donor_file->pos;
+
+out:
+	fibril_mutex_lock(&acceptor_data->lock);
+	list_append(&bh->link, &acceptor_data->passed_handles);
+	fibril_condvar_broadcast(&acceptor_data->cv);
+	fibril_mutex_unlock(&acceptor_data->lock);
+
+	if (donor_data)
+		async_put_client_data_by_id(donor_id);
+	if (acceptor_data)
+		async_put_client_data_by_id(acceptor_id);
+	if (donor_file)
+		_vfs_file_put(donor_data, donor_file);
+	if (acceptor_file)
+		_vfs_file_put(acceptor_data, acceptor_file);
+
+}
+
+int vfs_wait_handle_internal(void)
+{
+	vfs_client_data_t *vfs_data = VFS_DATA;	
+	int fd;
+	
+	fibril_mutex_lock(&vfs_data->lock);
+	while (list_empty(&vfs_data->passed_handles))
+		fibril_condvar_wait(&vfs_data->cv, &vfs_data->lock);
+	link_t *lnk = list_first(&vfs_data->passed_handles);
+	list_remove(lnk);
+	fibril_mutex_unlock(&vfs_data->lock);
+
+	vfs_boxed_handle_t *bh = list_get_instance(lnk, vfs_boxed_handle_t, link);
+	fd = bh->handle;
+	free(bh);
+
+	return fd;
 }
 
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/vfs/vfs_lookup.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -50,5 +50,5 @@
 
 FIBRIL_MUTEX_INITIALIZE(plb_mutex);
-LIST_INITIALIZE(plb_head);	/**< PLB entry ring buffer. */
+LIST_INITIALIZE(plb_entries);	/**< PLB entry ring buffer. */
 uint8_t *plb = NULL;
 
@@ -102,12 +102,12 @@
 	size_t last;	/* the last free index */
 
-	if (list_empty(&plb_head)) {
+	if (list_empty(&plb_entries)) {
 		first = 0;
 		last = PLB_SIZE - 1;
 	} else {
-		plb_entry_t *oldest = list_get_instance(plb_head.next,
-		    plb_entry_t, plb_link);
-		plb_entry_t *newest = list_get_instance(plb_head.prev,
-		    plb_entry_t, plb_link);
+		plb_entry_t *oldest = list_get_instance(
+		    list_first(&plb_entries), plb_entry_t, plb_link);
+		plb_entry_t *newest = list_get_instance(
+		    list_last(&plb_entries), plb_entry_t, plb_link);
 
 		first = (newest->index + newest->len) % PLB_SIZE;
@@ -145,5 +145,5 @@
 	 * buffer.
 	 */
-	list_append(&entry.plb_link, &plb_head);
+	list_append(&entry.plb_link, &plb_entries);
 	
 	fibril_mutex_unlock(&plb_mutex);
@@ -159,13 +159,13 @@
 
 	ipc_call_t answer;
-	int phone = vfs_grab_phone(root->fs_handle);
-	aid_t req = async_send_5(phone, VFS_OUT_LOOKUP, (sysarg_t) first,
+	async_exch_t *exch = vfs_exchange_grab(root->fs_handle);
+	aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first,
 	    (sysarg_t) (first + len - 1) % PLB_SIZE,
-	    (sysarg_t) root->devmap_handle, (sysarg_t) lflag, (sysarg_t) index,
+	    (sysarg_t) root->service_id, (sysarg_t) lflag, (sysarg_t) index,
 	    &answer);
 	
 	sysarg_t rc;
 	async_wait_for(req, &rc);
-	vfs_release_phone(root->fs_handle, phone);
+	vfs_exchange_release(exch);
 	
 	fibril_mutex_lock(&plb_mutex);
@@ -185,5 +185,5 @@
 	
 	result->triplet.fs_handle = (fs_handle_t) rc;
-	result->triplet.devmap_handle = (devmap_handle_t) IPC_GET_ARG1(answer);
+	result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer);
 	result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
 	result->size =
@@ -201,37 +201,4 @@
 }
 
-/** Perform a node open operation.
- *
- * @return EOK on success or an error code from errno.h.
- *
- */
-int vfs_open_node_internal(vfs_lookup_res_t *result)
-{
-	int phone = vfs_grab_phone(result->triplet.fs_handle);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE,
-	    (sysarg_t) result->triplet.devmap_handle,
-	    (sysarg_t) result->triplet.index, &answer);
-	
-	sysarg_t rc;
-	async_wait_for(req, &rc);
-	vfs_release_phone(result->triplet.fs_handle, phone);
-	
-	if (rc == EOK) {
-		result->size =
-		    MERGE_LOUP32(IPC_GET_ARG1(answer), IPC_GET_ARG2(answer));
-		result->lnkcnt = (unsigned int) IPC_GET_ARG3(answer);
-		if (IPC_GET_ARG4(answer) & L_FILE)
-			result->type = VFS_NODE_FILE;
-		else if (IPC_GET_ARG4(answer) & L_DIRECTORY)
-			result->type = VFS_NODE_DIRECTORY;
-		else
-			result->type = VFS_NODE_UNKNOWN;
-	}
-	
-	return rc;
-}
-
 /**
  * @}
Index: uspace/srv/vfs/vfs_node.c
===================================================================
--- uspace/srv/vfs/vfs_node.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/vfs/vfs_node.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -104,35 +104,44 @@
 	bool free_vfs_node = false;
 	bool free_fs_node = false;
-
-	fibril_mutex_lock(&nodes_mutex);
+	
+	fibril_mutex_lock(&nodes_mutex);
+	
 	if (node->refcnt-- == 1) {
+		
 		/*
 		 * We are dropping the last reference to this node.
 		 * Remove it from the VFS node hash table.
 		 */
+		
 		unsigned long key[] = {
 			[KEY_FS_HANDLE] = node->fs_handle,
-			[KEY_DEV_HANDLE] = node->devmap_handle,
+			[KEY_DEV_HANDLE] = node->service_id,
 			[KEY_INDEX] = node->index
 		};
+		
 		hash_table_remove(&nodes, key, 3);
 		free_vfs_node = true;
+		
 		if (!node->lnkcnt)
 			free_fs_node = true;
 	}
-	fibril_mutex_unlock(&nodes_mutex);
-
+	
+	fibril_mutex_unlock(&nodes_mutex);
+	
 	if (free_fs_node) {
-		/* 
+		
+		/*
 		 * The node is not visible in the file system namespace.
 		 * Free up its resources.
 		 */
-		int phone = vfs_grab_phone(node->fs_handle);
-		sysarg_t rc;
-		rc = async_req_2_0(phone, VFS_OUT_DESTROY,
-		    (sysarg_t)node->devmap_handle, (sysarg_t)node->index);
+		
+		async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
+		sysarg_t rc = async_req_2_0(exch, VFS_OUT_DESTROY,
+		    (sysarg_t) node->service_id, (sysarg_t)node->index);
+		
 		assert(rc == EOK);
-		vfs_release_phone(node->fs_handle, phone);
+		vfs_exchange_release(exch);
 	}
+	
 	if (free_vfs_node)
 		free(node);
@@ -151,5 +160,5 @@
 	unsigned long key[] = {
 		[KEY_FS_HANDLE] = node->fs_handle,
-		[KEY_DEV_HANDLE] = node->devmap_handle,
+		[KEY_DEV_HANDLE] = node->service_id,
 		[KEY_INDEX] = node->index
 	};
@@ -175,5 +184,5 @@
 	unsigned long key[] = {
 		[KEY_FS_HANDLE] = result->triplet.fs_handle,
-		[KEY_DEV_HANDLE] = result->triplet.devmap_handle,
+		[KEY_DEV_HANDLE] = result->triplet.service_id,
 		[KEY_INDEX] = result->triplet.index
 	};
@@ -191,5 +200,5 @@
 		memset(node, 0, sizeof(vfs_node_t));
 		node->fs_handle = result->triplet.fs_handle;
-		node->devmap_handle = result->triplet.devmap_handle;
+		node->service_id = result->triplet.service_id;
 		node->index = result->triplet.index;
 		node->size = result->size;
@@ -243,5 +252,5 @@
 	vfs_node_t *node = hash_table_get_instance(item, vfs_node_t, nh_link);
 	return (node->fs_handle == (fs_handle_t) key[KEY_FS_HANDLE]) &&
-	    (node->devmap_handle == key[KEY_DEV_HANDLE]) &&
+	    (node->service_id == key[KEY_DEV_HANDLE]) &&
 	    (node->index == key[KEY_INDEX]);
 }
@@ -255,5 +264,5 @@
 	unsigned refcnt;
 	fs_handle_t fs_handle;
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 };
 
@@ -264,15 +273,15 @@
 
 	if ((node->fs_handle == rd->fs_handle) &&
-	    (node->devmap_handle == rd->devmap_handle))
+	    (node->service_id == rd->service_id))
 		rd->refcnt += node->refcnt;
 }
 
 unsigned
-vfs_nodes_refcount_sum_get(fs_handle_t fs_handle, devmap_handle_t devmap_handle)
+vfs_nodes_refcount_sum_get(fs_handle_t fs_handle, service_id_t service_id)
 {
 	struct refcnt_data rd = {
 		.refcnt = 0,
 		.fs_handle = fs_handle,
-		.devmap_handle = devmap_handle
+		.service_id = service_id
 	};
 
@@ -282,4 +291,26 @@
 
 	return rd.refcnt;
+}
+
+
+/** Perform a remote node open operation.
+ *
+ * @return EOK on success or an error code from errno.h.
+ *
+ */
+int vfs_open_node_remote(vfs_node_t *node)
+{
+	async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, VFS_OUT_OPEN_NODE,
+	    (sysarg_t) node->service_id, (sysarg_t) node->index, &answer);
+	
+	vfs_exchange_release(exch);
+
+	sysarg_t rc;
+	async_wait_for(req, &rc);
+	
+	return rc;
 }
 
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/vfs/vfs_ops.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -54,5 +54,5 @@
 
 /* Forward declarations of static functions. */
-static int vfs_truncate_internal(fs_handle_t, devmap_handle_t, fs_index_t,
+static int vfs_truncate_internal(fs_handle_t, service_id_t, fs_index_t,
     aoff64_t);
 
@@ -65,8 +65,8 @@
 vfs_pair_t rootfs = {
 	.fs_handle = 0,
-	.devmap_handle = 0
+	.service_id = 0
 };
 
-static void vfs_mount_internal(ipc_callid_t rid, devmap_handle_t devmap_handle,
+static void vfs_mount_internal(ipc_callid_t rid, service_id_t service_id,
     fs_handle_t fs_handle, char *mp, char *opts)
 {
@@ -76,8 +76,8 @@
 	vfs_node_t *mr_node;
 	fs_index_t rindex;
-	size_t rsize;
+	aoff64_t rsize;
 	unsigned rlnkcnt;
+	async_exch_t *exch;
 	sysarg_t rc;
-	int phone;
 	aid_t msg;
 	ipc_call_t answer;
@@ -123,13 +123,14 @@
 			
 			/* Tell the mountee that it is being mounted. */
-			phone = vfs_grab_phone(fs_handle);
-			msg = async_send_1(phone, VFS_OUT_MOUNTED,
-			    (sysarg_t) devmap_handle, &answer);
-			/* send the mount options */
-			rc = async_data_write_start(phone, (void *)opts,
+			exch = vfs_exchange_grab(fs_handle);
+			msg = async_send_1(exch, VFS_OUT_MOUNTED,
+			    (sysarg_t) service_id, &answer);
+			/* Send the mount options */
+			rc = async_data_write_start(exch, (void *)opts,
 			    str_size(opts));
+			vfs_exchange_release(exch);
+			
 			if (rc != EOK) {
 				async_wait_for(msg, NULL);
-				vfs_release_phone(fs_handle, phone);
 				fibril_rwlock_write_unlock(&namespace_rwlock);
 				async_answer_0(rid, rc);
@@ -137,5 +138,4 @@
 			}
 			async_wait_for(msg, &rc);
-			vfs_release_phone(fs_handle, phone);
 			
 			if (rc != EOK) {
@@ -146,9 +146,9 @@
 
 			rindex = (fs_index_t) IPC_GET_ARG1(answer);
-			rsize = (size_t) IPC_GET_ARG2(answer);
-			rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
+			rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer), IPC_GET_ARG3(answer));
+			rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
 			
 			mr_res.triplet.fs_handle = fs_handle;
-			mr_res.triplet.devmap_handle = devmap_handle;
+			mr_res.triplet.service_id = service_id;
 			mr_res.triplet.index = rindex;
 			mr_res.size = rsize;
@@ -157,5 +157,5 @@
 			
 			rootfs.fs_handle = fs_handle;
-			rootfs.devmap_handle = devmap_handle;
+			rootfs.service_id = service_id;
 			
 			/* Add reference to the mounted root. */
@@ -178,61 +178,66 @@
 	
 	/*
-	 * At this point, we have all necessary pieces: file system and device
-	 * handles, and we know the mount point VFS node.
-	 */
-	
-	int mountee_phone = vfs_grab_phone(fs_handle);
-	assert(mountee_phone >= 0);
-
-	phone = vfs_grab_phone(mp_res.triplet.fs_handle);
-	msg = async_send_4(phone, VFS_OUT_MOUNT,
-	    (sysarg_t) mp_res.triplet.devmap_handle,
+	 * At this point, we have all necessary pieces: file system handle
+	 * and service ID, and we know the mount point VFS node.
+	 */
+	
+	async_exch_t *mountee_exch = vfs_exchange_grab(fs_handle);
+	assert(mountee_exch);
+	
+	exch = vfs_exchange_grab(mp_res.triplet.fs_handle);
+	msg = async_send_4(exch, VFS_OUT_MOUNT,
+	    (sysarg_t) mp_res.triplet.service_id,
 	    (sysarg_t) mp_res.triplet.index,
 	    (sysarg_t) fs_handle,
-	    (sysarg_t) devmap_handle, &answer);
-	
-	/* send connection */
-	rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
-	if (rc != EOK) {
+	    (sysarg_t) service_id, &answer);
+	
+	/* Send connection */
+	rc = async_exchange_clone(exch, mountee_exch);
+	vfs_exchange_release(mountee_exch);
+	
+	if (rc != EOK) {
+		vfs_exchange_release(exch);
 		async_wait_for(msg, NULL);
-		vfs_release_phone(fs_handle, mountee_phone);
-		vfs_release_phone(mp_res.triplet.fs_handle, phone);
+		
 		/* Mount failed, drop reference to mp_node. */
 		if (mp_node)
 			vfs_node_put(mp_node);
-		async_answer_0(rid, rc);
-		fibril_rwlock_write_unlock(&namespace_rwlock);
-		return;
-	}
-
-	vfs_release_phone(fs_handle, mountee_phone);
+		
+		async_answer_0(rid, rc);
+		fibril_rwlock_write_unlock(&namespace_rwlock);
+		return;
+	}
 	
 	/* send the mount options */
-	rc = async_data_write_start(phone, (void *)opts, str_size(opts));
-	if (rc != EOK) {
+	rc = async_data_write_start(exch, (void *) opts, str_size(opts));
+	if (rc != EOK) {
+		vfs_exchange_release(exch);
 		async_wait_for(msg, NULL);
-		vfs_release_phone(mp_res.triplet.fs_handle, phone);
+		
 		/* Mount failed, drop reference to mp_node. */
 		if (mp_node)
 			vfs_node_put(mp_node);
-		fibril_rwlock_write_unlock(&namespace_rwlock);
-		async_answer_0(rid, rc);
-		return;
-	}
+		
+		fibril_rwlock_write_unlock(&namespace_rwlock);
+		async_answer_0(rid, rc);
+		return;
+	}
+	
+	vfs_exchange_release(exch);
 	async_wait_for(msg, &rc);
-	vfs_release_phone(mp_res.triplet.fs_handle, phone);
 	
 	if (rc == EOK) {
 		rindex = (fs_index_t) IPC_GET_ARG1(answer);
-		rsize = (size_t) IPC_GET_ARG2(answer);
-		rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
-	
+		rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer),
+		    IPC_GET_ARG3(answer));
+		rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
+		
 		mr_res.triplet.fs_handle = fs_handle;
-		mr_res.triplet.devmap_handle = devmap_handle;
+		mr_res.triplet.service_id = service_id;
 		mr_res.triplet.index = rindex;
 		mr_res.size = rsize;
 		mr_res.lnkcnt = rlnkcnt;
 		mr_res.type = VFS_NODE_DIRECTORY;
-	
+		
 		/* Add reference to the mounted root. */
 		mr_node = vfs_node_get(&mr_res); 
@@ -243,5 +248,5 @@
 			vfs_node_put(mp_node);
 	}
-
+	
 	async_answer_0(rid, rc);
 	fibril_rwlock_write_unlock(&namespace_rwlock);
@@ -250,5 +255,5 @@
 void vfs_mount(ipc_callid_t rid, ipc_call_t *request)
 {
-	devmap_handle_t devmap_handle;
+	service_id_t service_id;
 
 	/*
@@ -257,5 +262,5 @@
 	 * in the request.
 	 */
-	devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	service_id = (service_id_t) IPC_GET_ARG1(*request);
 	
 	/*
@@ -303,10 +308,10 @@
 	
 	/*
-	 * Wait for IPC_M_PING so that we can return an error if we don't know
+	 * Wait for VFS_IN_PING so that we can return an error if we don't know
 	 * fs_name.
 	 */
 	ipc_call_t data;
 	ipc_callid_t callid = async_get_call(&data);
-	if (IPC_GET_IMETHOD(data) != IPC_M_PING) {
+	if (IPC_GET_IMETHOD(data) != VFS_IN_PING) {
 		async_answer_0(callid, ENOTSUP);
 		async_answer_0(rid, ENOTSUP);
@@ -321,5 +326,5 @@
 	 * This will also give us its file system handle.
 	 */
-	fibril_mutex_lock(&fs_head_lock);
+	fibril_mutex_lock(&fs_list_lock);
 	fs_handle_t fs_handle;
 recheck:
@@ -327,9 +332,9 @@
 	if (!fs_handle) {
 		if (flags & IPC_FLAG_BLOCKING) {
-			fibril_condvar_wait(&fs_head_cv, &fs_head_lock);
+			fibril_condvar_wait(&fs_list_cv, &fs_list_lock);
 			goto recheck;
 		}
 		
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		async_answer_0(callid, ENOENT);
 		async_answer_0(rid, ENOENT);
@@ -339,5 +344,5 @@
 		return;
 	}
-	fibril_mutex_unlock(&fs_head_lock);
+	fibril_mutex_unlock(&fs_list_lock);
 	
 	/* Acknowledge that we know fs_name. */
@@ -345,5 +350,5 @@
 	
 	/* Do the mount */
-	vfs_mount_internal(rid, devmap_handle, fs_handle, mp, opts);
+	vfs_mount_internal(rid, service_id, fs_handle, mp, opts);
 	free(mp);
 	free(fs_name);
@@ -358,6 +363,6 @@
 	vfs_lookup_res_t mr_res;
 	vfs_node_t *mr_node;
-	int phone;
-
+	async_exch_t *exch;
+	
 	/*
 	 * Receive the mount point path.
@@ -367,5 +372,5 @@
 	if (rc != EOK)
 		async_answer_0(rid, rc);
-
+	
 	/*
 	 * Taking the namespace lock will do two things for us. First, it will
@@ -395,5 +400,5 @@
 		return;
 	}
-
+	
 	/*
 	 * Count the total number of references for the mounted file system. We
@@ -404,5 +409,5 @@
 	 */
 	if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
-	    mr_node->devmap_handle) != 2) {
+	    mr_node->service_id) != 2) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
 		vfs_node_put(mr_node);
@@ -411,7 +416,7 @@
 		return;
 	}
-
+	
 	if (str_cmp(mp, "/") == 0) {
-
+		
 		/*
 		 * Unmounting the root file system.
@@ -420,10 +425,12 @@
 		 * VFS_OUT_UNMOUNTED directly to the mounted file system.
 		 */
-
+		
 		free(mp);
-		phone = vfs_grab_phone(mr_node->fs_handle);
-		rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
-		    mr_node->devmap_handle);
-		vfs_release_phone(mr_node->fs_handle, phone);
+		
+		exch = vfs_exchange_grab(mr_node->fs_handle);
+		rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED,
+		    mr_node->service_id);
+		vfs_exchange_release(exch);
+		
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
@@ -432,8 +439,9 @@
 			return;
 		}
+		
 		rootfs.fs_handle = 0;
-		rootfs.devmap_handle = 0;
+		rootfs.service_id = 0;
 	} else {
-
+		
 		/*
 		 * Unmounting a non-root file system.
@@ -442,5 +450,5 @@
 		 * file system, so we delegate the operation to it.
 		 */
-
+		
 		rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
 		free(mp);
@@ -451,4 +459,5 @@
 			return;
 		}
+		
 		vfs_node_t *mp_node = vfs_node_get(&mp_res);
 		if (!mp_node) {
@@ -458,9 +467,10 @@
 			return;
 		}
-
-		phone = vfs_grab_phone(mp_node->fs_handle);
-		rc = async_req_2_0(phone, VFS_OUT_UNMOUNT,
-		    mp_node->devmap_handle, mp_node->index);
-		vfs_release_phone(mp_node->fs_handle, phone);
+		
+		exch = vfs_exchange_grab(mp_node->fs_handle);
+		rc = async_req_2_0(exch, VFS_OUT_UNMOUNT,
+		    mp_node->service_id, mp_node->index);
+		vfs_exchange_release(exch);
+		
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
@@ -470,5 +480,5 @@
 			return;
 		}
-
+		
 		/* Drop the reference we got above. */
 		vfs_node_put(mp_node);
@@ -476,6 +486,5 @@
 		vfs_node_put(mp_node);
 	}
-
-
+	
 	/*
 	 * All went well, the mounted file system was successfully unmounted.
@@ -483,5 +492,5 @@
 	 */
 	vfs_node_forget(mr_node);
-
+	
 	fibril_rwlock_write_unlock(&namespace_rwlock);
 	async_answer_0(rid, EOK);
@@ -566,5 +575,5 @@
 		if (node->size) {
 			rc = vfs_truncate_internal(node->fs_handle,
-			    node->devmap_handle, node->index, 0);
+			    node->service_id, node->index, 0);
 			if (rc) {
 				fibril_rwlock_write_unlock(&node->contents_rwlock);
@@ -609,77 +618,4 @@
 }
 
-void vfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	// FIXME: check for sanity of the supplied fs, dev and index
-	
-	/*
-	 * The interface is open_node(fs, dev, index, oflag).
-	 */
-	vfs_lookup_res_t lr;
-	
-	lr.triplet.fs_handle = IPC_GET_ARG1(*request);
-	lr.triplet.devmap_handle = IPC_GET_ARG2(*request);
-	lr.triplet.index = IPC_GET_ARG3(*request);
-	int oflag = IPC_GET_ARG4(*request);
-	
-	fibril_rwlock_read_lock(&namespace_rwlock);
-	
-	int rc = vfs_open_node_internal(&lr);
-	if (rc != EOK) {
-		fibril_rwlock_read_unlock(&namespace_rwlock);
-		async_answer_0(rid, rc);
-		return;
-	}
-	
-	vfs_node_t *node = vfs_node_get(&lr);
-	fibril_rwlock_read_unlock(&namespace_rwlock);
-	
-	/* Truncate the file if requested and if necessary. */
-	if (oflag & O_TRUNC) {
-		fibril_rwlock_write_lock(&node->contents_rwlock);
-		if (node->size) {
-			rc = vfs_truncate_internal(node->fs_handle,
-			    node->devmap_handle, node->index, 0);
-			if (rc) {
-				fibril_rwlock_write_unlock(&node->contents_rwlock);
-				vfs_node_put(node);
-				async_answer_0(rid, rc);
-				return;
-			}
-			node->size = 0;
-		}
-		fibril_rwlock_write_unlock(&node->contents_rwlock);
-	}
-	
-	/*
-	 * Get ourselves a file descriptor and the corresponding vfs_file_t
-	 * structure.
-	 */
-	int fd = vfs_fd_alloc((oflag & O_DESC) != 0);
-	if (fd < 0) {
-		vfs_node_put(node);
-		async_answer_0(rid, fd);
-		return;
-	}
-	vfs_file_t *file = vfs_file_get(fd);
-	file->node = node;
-	if (oflag & O_APPEND)
-		file->append = true;
-	
-	/*
-	 * The following increase in reference count is for the fact that the
-	 * file is being opened and that a file structure is pointing to it.
-	 * It is necessary so that the file will not disappear when
-	 * vfs_node_put() is called. The reference will be dropped by the
-	 * respective VFS_IN_CLOSE.
-	 */
-	vfs_node_addref(node);
-	vfs_node_put(node);
-	vfs_file_put(file);
-	
-	/* Success! Return the new file descriptor to the client. */
-	async_answer_1(rid, EOK, fd);
-}
-
 void vfs_sync(ipc_callid_t rid, ipc_call_t *request)
 {
@@ -698,75 +634,28 @@
 	 */
 	fibril_mutex_lock(&file->lock);
-	int fs_phone = vfs_grab_phone(file->node->fs_handle);
+	async_exch_t *fs_exch = vfs_exchange_grab(file->node->fs_handle);
 	
 	/* Make a VFS_OUT_SYMC request at the destination FS server. */
 	aid_t msg;
 	ipc_call_t answer;
-	msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->devmap_handle,
+	msg = async_send_2(fs_exch, VFS_OUT_SYNC, file->node->service_id,
 	    file->node->index, &answer);
-
+	
+	vfs_exchange_release(fs_exch);
+	
 	/* Wait for reply from the FS server. */
 	sysarg_t rc;
 	async_wait_for(msg, &rc);
 	
-	vfs_release_phone(file->node->fs_handle, fs_phone);
 	fibril_mutex_unlock(&file->lock);
-
+	
 	vfs_file_put(file);
 	async_answer_0(rid, rc);
 }
 
-int vfs_close_internal(vfs_file_t *file)
-{
-	/*
-	 * Lock the open file structure so that no other thread can manipulate
-	 * the same open file at a time.
-	 */
-	fibril_mutex_lock(&file->lock);
-	
-	if (file->refcnt <= 1) {
-		/* Only close the file on the destination FS server
-		   if there are no more file descriptors (except the
-		   present one) pointing to this file. */
-		
-		int fs_phone = vfs_grab_phone(file->node->fs_handle);
-		
-		/* Make a VFS_OUT_CLOSE request at the destination FS server. */
-		aid_t msg;
-		ipc_call_t answer;
-		msg = async_send_2(fs_phone, VFS_OUT_CLOSE,
-		    file->node->devmap_handle, file->node->index, &answer);
-		
-		/* Wait for reply from the FS server. */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		
-		vfs_release_phone(file->node->fs_handle, fs_phone);
-		fibril_mutex_unlock(&file->lock);
-		
-		return IPC_GET_ARG1(answer);
-	}
-	
-	fibril_mutex_unlock(&file->lock);
-	return EOK;
-}
-
 void vfs_close(ipc_callid_t rid, ipc_call_t *request)
 {
 	int fd = IPC_GET_ARG1(*request);
-	
-	/* Lookup the file structure corresponding to the file descriptor. */
-	vfs_file_t *file = vfs_file_get(fd);
-	if (!file) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
-	
-	int ret = vfs_close_internal(file);
-	if (ret != EOK)
-		async_answer_0(rid, ret);
-	
-	vfs_file_put(file);
-	ret = vfs_fd_free(fd);
+	int ret = vfs_fd_free(fd);
 	async_answer_0(rid, ret);
 }
@@ -774,6 +663,4 @@
 static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
 {
-	vfs_info_t *vi;
-
 	/*
 	 * The following code strongly depends on the fact that the files data
@@ -785,5 +672,5 @@
 	 * open files supports parallel access!
 	 */
-
+	
 	int fd = IPC_GET_ARG1(*request);
 	
@@ -800,8 +687,8 @@
 	 */
 	fibril_mutex_lock(&file->lock);
-
-	vi = fs_handle_to_info(file->node->fs_handle);
-	assert(vi);
-
+	
+	vfs_info_t *fs_info = fs_handle_to_info(file->node->fs_handle);
+	assert(fs_info);
+	
 	/*
 	 * Lock the file's node so that no other client can read/write to it at
@@ -809,9 +696,10 @@
 	 * write implementation does not modify the file size.
 	 */
-	if (read || (vi->concurrent_read_write && vi->write_retains_size))
+	if ((read) ||
+	    ((fs_info->concurrent_read_write) && (fs_info->write_retains_size)))
 		fibril_rwlock_read_lock(&file->node->contents_rwlock);
 	else
 		fibril_rwlock_write_lock(&file->node->contents_rwlock);
-
+	
 	if (file->node->type == VFS_NODE_DIRECTORY) {
 		/*
@@ -823,5 +711,5 @@
 	}
 	
-	int fs_phone = vfs_grab_phone(file->node->fs_handle);
+	async_exch_t *fs_exch = vfs_exchange_grab(file->node->fs_handle);
 	
 	/*
@@ -835,17 +723,17 @@
 	ipc_call_t answer;
 	if (read) {
-		rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ,
-		    file->node->devmap_handle, file->node->index, file->pos,
-		    &answer);
+		rc = async_data_read_forward_4_1(fs_exch, VFS_OUT_READ,
+		    file->node->service_id, file->node->index,
+		    LOWER32(file->pos), UPPER32(file->pos), &answer);
 	} else {
 		if (file->append)
 			file->pos = file->node->size;
 		
-		rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE,
-		    file->node->devmap_handle, file->node->index, file->pos,
-		    &answer);
-	}
-	
-	vfs_release_phone(file->node->fs_handle, fs_phone);
+		rc = async_data_write_forward_4_1(fs_exch, VFS_OUT_WRITE,
+		    file->node->service_id, file->node->index,
+		    LOWER32(file->pos), UPPER32(file->pos), &answer);
+	}
+	
+	vfs_exchange_release(fs_exch);
 	
 	size_t bytes = IPC_GET_ARG1(answer);
@@ -855,10 +743,12 @@
 	
 	/* Unlock the VFS node. */
-	if (read || (vi->concurrent_read_write && vi->write_retains_size))
+	if ((read) ||
+	    ((fs_info->concurrent_read_write) && (fs_info->write_retains_size)))
 		fibril_rwlock_read_unlock(&file->node->contents_rwlock);
 	else {
 		/* Update the cached version of node's size. */
 		if (rc == EOK)
-			file->node->size = IPC_GET_ARG2(answer); 
+			file->node->size = MERGE_LOUP32(IPC_GET_ARG2(answer),
+			    IPC_GET_ARG3(answer));
 		fibril_rwlock_write_unlock(&file->node->contents_rwlock);
 	}
@@ -972,15 +862,14 @@
 }
 
-int vfs_truncate_internal(fs_handle_t fs_handle, devmap_handle_t devmap_handle,
+int vfs_truncate_internal(fs_handle_t fs_handle, service_id_t service_id,
     fs_index_t index, aoff64_t size)
 {
-	sysarg_t rc;
-	int fs_phone;
-	
-	fs_phone = vfs_grab_phone(fs_handle);
-	rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (sysarg_t) devmap_handle,
-	    (sysarg_t) index, LOWER32(size), UPPER32(size));
-	vfs_release_phone(fs_handle, fs_phone);
-	return (int)rc;
+	async_exch_t *exch = vfs_exchange_grab(fs_handle);
+	sysarg_t rc = async_req_4_0(exch, VFS_OUT_TRUNCATE,
+	    (sysarg_t) service_id, (sysarg_t) index, LOWER32(size),
+	    UPPER32(size));
+	vfs_exchange_release(exch);
+	
+	return (int) rc;
 }
 
@@ -1001,5 +890,5 @@
 	fibril_rwlock_write_lock(&file->node->contents_rwlock);
 	rc = vfs_truncate_internal(file->node->fs_handle,
-	    file->node->devmap_handle, file->node->index, size);
+	    file->node->service_id, file->node->index, size);
 	if (rc == EOK)
 		file->node->size = size;
@@ -1032,13 +921,15 @@
 	fibril_mutex_lock(&file->lock);
 
-	int fs_phone = vfs_grab_phone(file->node->fs_handle);
+	async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle);
 	
 	aid_t msg;
-	msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->devmap_handle,
+	msg = async_send_3(exch, VFS_OUT_STAT, file->node->service_id,
 	    file->node->index, true, NULL);
-	async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	
+	vfs_exchange_release(exch);
+	
 	async_wait_for(msg, &rc);
-	vfs_release_phone(file->node->fs_handle, fs_phone);
-
+	
 	fibril_mutex_unlock(&file->lock);
 	vfs_file_put(file);
@@ -1083,13 +974,15 @@
 	fibril_rwlock_read_unlock(&namespace_rwlock);
 
-	int fs_phone = vfs_grab_phone(node->fs_handle);
+	async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
+	
 	aid_t msg;
-	msg = async_send_3(fs_phone, VFS_OUT_STAT, node->devmap_handle,
+	msg = async_send_3(exch, VFS_OUT_STAT, node->service_id,
 	    node->index, false, NULL);
-	async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	
+	vfs_exchange_release(exch);
 	
 	sysarg_t rv;
 	async_wait_for(msg, &rv);
-	vfs_release_phone(node->fs_handle, fs_phone);
 
 	async_answer_0(rid, rv);
@@ -1234,4 +1127,5 @@
 	if (!parentc) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
+		vfs_node_put(old_node);
 		async_answer_0(rid, rc);
 		free(old);
@@ -1251,4 +1145,5 @@
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
+		vfs_node_put(old_node);
 		async_answer_0(rid, rc);
 		free(old);
@@ -1259,6 +1154,7 @@
 	/* Check whether linking to the same file system instance. */
 	if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
-	    (old_node->devmap_handle != new_par_lr.triplet.devmap_handle)) {
-		fibril_rwlock_write_unlock(&namespace_rwlock);
+	    (old_node->service_id != new_par_lr.triplet.service_id)) {
+		fibril_rwlock_write_unlock(&namespace_rwlock);
+		vfs_node_put(old_node);
 		async_answer_0(rid, EXDEV);	/* different file systems */
 		free(old);
@@ -1279,4 +1175,5 @@
 		if (!new_node) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
+			vfs_node_put(old_node);
 			async_answer_0(rid, ENOMEM);
 			free(old);
@@ -1290,4 +1187,5 @@
 	default:
 		fibril_rwlock_write_unlock(&namespace_rwlock);
+		vfs_node_put(old_node);
 		async_answer_0(rid, ENOTEMPTY);
 		free(old);
@@ -1300,4 +1198,5 @@
 	if (rc != EOK) {
 		fibril_rwlock_write_unlock(&namespace_rwlock);
+		vfs_node_put(old_node);
 		if (new_node)
 			vfs_node_put(new_node);
@@ -1363,27 +1262,6 @@
 	fibril_mutex_lock(&oldfile->lock);
 	
-	/* Lookup an open file structure possibly corresponding to newfd. */
-	vfs_file_t *newfile = vfs_file_get(newfd);
-	if (newfile) {
-		/* Close the originally opened file. */
-		int ret = vfs_close_internal(newfile);
-		if (ret != EOK) {
-			fibril_mutex_unlock(&oldfile->lock);
-			vfs_file_put(oldfile);
-			vfs_file_put(newfile);
-			async_answer_0(rid, ret);
-			return;
-		}
-		
-		ret = vfs_fd_free(newfd);
-		if (ret != EOK) {
-			fibril_mutex_unlock(&oldfile->lock);
-			vfs_file_put(oldfile);
-			vfs_file_put(newfile);
-			async_answer_0(rid, ret);
-			return;
-		}
-		vfs_file_put(newfile);
-	}
+	/* Make sure newfd is closed. */
+	(void) vfs_fd_free(newfd);
 	
 	/* Assign the old file to newfd. */
@@ -1398,4 +1276,10 @@
 }
 
+void vfs_wait_handle(ipc_callid_t rid, ipc_call_t *request)
+{
+	int fd = vfs_wait_handle_internal();
+	async_answer_1(rid, EOK, fd);
+}
+
 /**
  * @}
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ uspace/srv/vfs/vfs_register.c	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -52,7 +52,7 @@
 #include "vfs.h"
 
-FIBRIL_CONDVAR_INITIALIZE(fs_head_cv);
-FIBRIL_MUTEX_INITIALIZE(fs_head_lock);
-LIST_INITIALIZE(fs_head);
+FIBRIL_CONDVAR_INITIALIZE(fs_list_cv);
+FIBRIL_MUTEX_INITIALIZE(fs_list_lock);
+LIST_INITIALIZE(fs_list);
 
 atomic_t fs_handle_next = {
@@ -62,12 +62,13 @@
 /** Verify the VFS info structure.
  *
- * @param info		Info structure to be verified.
- *
- * @return		Non-zero if the info structure is sane, zero otherwise.
+ * @param info Info structure to be verified.
+ *
+ * @return Non-zero if the info structure is sane, zero otherwise.
+ *
  */
 static bool vfs_info_sane(vfs_info_t *info)
 {
 	int i;
-
+	
 	/*
 	 * Check if the name is non-empty and is composed solely of ASCII
@@ -78,4 +79,5 @@
 		return false;
 	}
+	
 	for (i = 1; i < FS_NAME_MAXLEN; i++) {
 		if (!(islower(info->name[i]) || isdigit(info->name[i])) &&
@@ -90,4 +92,5 @@
 		}
 	}
+	
 	/*
 	 * This check is not redundant. It ensures that the name is
@@ -104,11 +107,10 @@
 /** VFS_REGISTER protocol function.
  *
- * @param rid		Hash of the call with the request.
- * @param request	Call structure with the request.
+ * @param rid     Hash of the call with the request.
+ * @param request Call structure with the request.
+ *
  */
 void vfs_register(ipc_callid_t rid, ipc_call_t *request)
 {
-	int phone;
-	
 	dprintf("Processing VFS_REGISTER request received from %p.\n",
 	    request->in_phone_hash);
@@ -147,5 +149,5 @@
 	}
 	
-	fibril_mutex_lock(&fs_head_lock);
+	fibril_mutex_lock(&fs_list_lock);
 	
 	/*
@@ -157,5 +159,5 @@
 		 */
 		dprintf("FS is already registered.\n");
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		free(fs_info);
 		async_answer_0(rid, EEXISTS);
@@ -167,5 +169,5 @@
 	 */
 	dprintf("Inserting FS into the list of registered file systems.\n");
-	list_append(&fs_info->fs_link, &fs_head);
+	list_append(&fs_info->fs_link, &fs_list);
 	
 	/*
@@ -174,20 +176,14 @@
 	 * which to forward VFS requests to it.
 	 */
-	ipc_call_t call;
-	ipc_callid_t callid = async_get_call(&call);
-	if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
-		dprintf("Unexpected call, method = %d\n", IPC_GET_IMETHOD(call));
+	fs_info->sess = async_callback_receive(EXCHANGE_PARALLEL);
+	if (!fs_info->sess) {
+		dprintf("Callback connection expected\n");
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
-		free(fs_info);
-		async_answer_0(callid, EINVAL);
+		fibril_mutex_unlock(&fs_list_lock);
+		free(fs_info);
 		async_answer_0(rid, EINVAL);
 		return;
 	}
 	
-	phone = IPC_GET_ARG5(call);
-	async_session_create(&fs_info->session, phone, 0);
-	async_answer_0(callid, EOK);
-	
 	dprintf("Callback connection to FS created.\n");
 	
@@ -197,10 +193,10 @@
 	
 	size_t size;
+	ipc_callid_t callid;
 	if (!async_share_in_receive(&callid, &size)) {
 		dprintf("Unexpected call, method = %d\n", IPC_GET_IMETHOD(call));
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
-		async_session_destroy(&fs_info->session);
-		async_hangup(phone);
+		fibril_mutex_unlock(&fs_list_lock);
+		async_hangup(fs_info->sess);
 		free(fs_info);
 		async_answer_0(callid, EINVAL);
@@ -215,7 +211,6 @@
 		dprintf("Client suggests wrong size of PFB, size = %d\n", size);
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
-		async_session_destroy(&fs_info->session);
-		async_hangup(phone);
+		fibril_mutex_unlock(&fs_list_lock);
+		async_hangup(fs_info->sess);
 		free(fs_info);
 		async_answer_0(callid, EINVAL);
@@ -240,6 +235,6 @@
 	async_answer_1(rid, EOK, (sysarg_t) fs_info->fs_handle);
 	
-	fibril_condvar_broadcast(&fs_head_cv);
-	fibril_mutex_unlock(&fs_head_lock);
+	fibril_condvar_broadcast(&fs_list_cv);
+	fibril_mutex_unlock(&fs_list_lock);
 	
 	dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
@@ -247,69 +242,58 @@
 }
 
-/** For a given file system handle, implement policy for allocating a phone.
- *
- * @param handle	File system handle.
- *
- * @return		Phone over which a multi-call request can be safely
- *			sent. Return 0 if no phone was found.
- */
-int vfs_grab_phone(fs_handle_t handle)
-{
-	link_t *cur;
-	fs_info_t *fs;
-	int phone;
-
-	/*
-	 * For now, we don't try to be very clever and very fast.  We simply
-	 * lookup the phone in the fs_head list and duplicate it.  The duplicate
-	 * phone will be returned to the client and the client will use it for
-	 * communication.  In the future, we should cache the connections so
-	 * that they do not have to be reestablished over and over again.
-	 */
-	fibril_mutex_lock(&fs_head_lock);
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
-		fs = list_get_instance(cur, fs_info_t, fs_link);
+/** Begin an exchange for a given file system handle
+ *
+ * @param handle File system handle.
+ *
+ * @return Exchange for a multi-call request.
+ * @return NULL if no such file exists.
+ *
+ */
+async_exch_t *vfs_exchange_grab(fs_handle_t handle)
+{
+	/*
+	 * For now, we don't try to be very clever and very fast.
+	 * We simply lookup the session in fs_list and
+	 * begin an exchange.
+	 */
+	fibril_mutex_lock(&fs_list_lock);
+	
+	list_foreach(fs_list, cur) {
+		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
+		
 		if (fs->fs_handle == handle) {
-			fibril_mutex_unlock(&fs_head_lock);
-			phone = async_exchange_begin(&fs->session);
-
-			assert(phone > 0);
-			return phone;
+			fibril_mutex_unlock(&fs_list_lock);
+			
+			assert(fs->sess);
+			async_exch_t *exch = async_exchange_begin(fs->sess);
+			
+			assert(exch);
+			return exch;
 		}
 	}
-	fibril_mutex_unlock(&fs_head_lock);
-	return 0;
-}
-
-/** Tell VFS that the phone is not needed anymore.
- *
- * @param phone		Phone to FS task.
- */
-void vfs_release_phone(fs_handle_t handle, int phone)
-{
-	link_t *cur;
-	fs_info_t *fs;
-
-	fibril_mutex_lock(&fs_head_lock);
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
-		fs = list_get_instance(cur, fs_info_t, fs_link);
-		if (fs->fs_handle == handle) {
-			fibril_mutex_unlock(&fs_head_lock);
-			async_exchange_end(&fs->session, phone);
-			return;
-		}
-	}
-	/* should not really get here */
-	abort();
-	fibril_mutex_unlock(&fs_head_lock);
+	
+	fibril_mutex_unlock(&fs_list_lock);
+	
+	return NULL;
+}
+
+/** End VFS server exchange.
+ *
+ * @param exch   VFS server exchange.
+ *
+ */
+void vfs_exchange_release(async_exch_t *exch)
+{
+	async_exchange_end(exch);
 }
 
 /** Convert file system name to its handle.
  *
- * @param name		File system name.
- * @param lock		If true, the function will lock and unlock the
- * 			fs_head_lock.
- *
- * @return		File system handle or zero if file system not found.
+ * @param name File system name.
+ * @param lock If true, the function will lock and unlock the
+ *             fs_list_lock.
+ *
+ * @return File system handle or zero if file system not found.
+ *
  */
 fs_handle_t fs_name_to_handle(char *name, bool lock)
@@ -318,15 +302,17 @@
 	
 	if (lock)
-		fibril_mutex_lock(&fs_head_lock);
-	link_t *cur;
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+		fibril_mutex_lock(&fs_list_lock);
+	
+	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
-		if (str_cmp(fs->vfs_info.name, name) == 0) { 
+		if (str_cmp(fs->vfs_info.name, name) == 0) {
 			handle = fs->fs_handle;
 			break;
 		}
 	}
+	
 	if (lock)
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
+	
 	return handle;
 }
@@ -334,14 +320,15 @@
 /** Find the VFS info structure.
  *
- * @param handle	FS handle for which the VFS info structure is sought.
- * @return		VFS info structure on success or NULL otherwise.
+ * @param handle FS handle for which the VFS info structure is sought.
+ *
+ * @return VFS info structure on success or NULL otherwise.
+ *
  */
 vfs_info_t *fs_handle_to_info(fs_handle_t handle)
 {
 	vfs_info_t *info = NULL;
-	link_t *cur;
-
-	fibril_mutex_lock(&fs_head_lock);
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+	
+	fibril_mutex_lock(&fs_list_lock);
+	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
 		if (fs->fs_handle == handle) { 
@@ -350,6 +337,6 @@
 		}
 	}
-	fibril_mutex_unlock(&fs_head_lock);
-
+	fibril_mutex_unlock(&fs_list_lock);
+	
 	return info;
 }
@@ -357,3 +344,3 @@
 /**
  * @}
- */ 
+ */
Index: version
===================================================================
--- version	(revision 667a4f84d6f4121641eb400329f6775769df3b1b)
+++ version	(revision abf04a54e4c7aacff4953360924ae064a6a0fc91)
@@ -37,5 +37,5 @@
 VERSION = 0
 PATCHLEVEL = 4
-SUBLEVEL = 2
+SUBLEVEL = 3
 
 ifdef EXTRAVERSION
@@ -45,3 +45,3 @@
 endif
 
-NAME = Skewer
+NAME = Sashimi
