Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ HelenOS.config	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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)
 
@@ -81,11 +85,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 +123,8 @@
 
 % Kernel architecture
+@ "mips64"
+! [PLATFORM=mips64] KARCH (choice)
+
+% Kernel architecture
 @ "ppc32"
 ! [PLATFORM=ppc32] KARCH (choice)
@@ -165,4 +170,8 @@
 
 % User space architecture
+@ "mips64"
+! [PLATFORM=mips64] UARCH (choice)
+
+% User space architecture
 @ "ppc32"
 ! [PLATFORM=ppc32] UARCH (choice)
@@ -206,4 +215,8 @@
 @ "mips32"
 ! [PLATFORM=mips32] BARCH (choice)
+
+% Boot architecture
+@ "mips64"
+! [PLATFORM=mips64] BARCH (choice)
 
 % Boot architecture
@@ -229,4 +242,8 @@
 @ "ecoff"
 ! [PLATFORM=mips32&(MACHINE=bgxemul|MACHINE=lgxemul)] IMAGE (choice)
+
+% Image format
+@ "binary"
+! [PLATFORM=mips64] IMAGE (choice)
 
 
@@ -256,5 +273,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 +309,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 +339,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 +396,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 +412,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
@@ -421,8 +438,8 @@
 
 % 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
@@ -447,13 +464,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)
@@ -463,5 +471,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
@@ -475,5 +483,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
@@ -522,7 +530,4 @@
 ! [PLATFORM=sparc64&CONFIG_SMP=y] CONFIG_AP (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)
@@ -569,5 +574,7 @@
 ! CONFIG_RUN_VIRTUAL_USB_HC (n/y)
 
-% Polling UHCI & OHCI (no interrupts)
-! [PLATFORM=ia32|PLATFORM=amd64] CONFIG_USBHC_NO_INTERRUPTS (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: boot/Makefile
===================================================================
--- boot/Makefile	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -50,4 +50,7 @@
 	$(MKFAT) 1048576 $(DIST_PATH) $@
 endif
+ifeq ($(RDFMT),ext2fs)
+	$(MKEXT2) 1048576 $(DIST_PATH) $@
+endif
 
 build_dist: clean_dist
@@ -76,5 +79,5 @@
 		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)
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/Makefile.common	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -56,4 +56,5 @@
 MKTMPFS = $(TOOLS_PATH)/mktmpfs.py
 MKFAT = $(TOOLS_PATH)/mkfat.py
+MKEXT2 = $(TOOLS_PATH)/mkext2.py
 MKUIMAGE = $(TOOLS_PATH)/mkuimage.py
 
@@ -82,4 +83,8 @@
 ifeq ($(RDFMT),fat)
 	INIT_TASKS += $(USPACE_PATH)/srv/fs/fat/fat
+endif
+
+ifeq ($(RDFMT),ext2fs)
+	INIT_TASKS += $(USPACE_PATH)/srv/fs/ext2fs/ext2fs
 endif
 
Index: boot/Makefile.silo
===================================================================
--- boot/Makefile.silo	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/Makefile.silo	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/Makefile.uboot	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/ia64/include/types.h
===================================================================
--- boot/arch/ia64/include/types.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/arch/ia64/include/types.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/arch/ia64/src/boot.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -37,4 +37,11 @@
 
 	#
+	# Save the boot parameter structure address passed from the
+	# ELILO-compatible EFI loader.
+	#
+	movl r8 = bootpar ;;
+	st8 [r8] = r28
+
+	#
 	# Initialize the register stack to some sane value.
 	#
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/arch/ia64/src/main.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -30,7 +30,9 @@
 
 #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 <halt.h>
 #include <printf.h>
@@ -51,9 +53,80 @@
 #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_sal_configuration(void)
+{
+	if (!bootpar) {
+		/* Configure default values for simulators. */
+		bootinfo.freq_scale = DEFAULT_FREQ_SCALE;
+		bootinfo.sys_freq = DEFAULT_SYS_FREQ;
+	} else {
+		/* TODO: read the real values from SAL */
+		bootinfo.freq_scale = DEFAULT_FREQ_SCALE;
+		bootinfo.sys_freq = DEFAULT_SYS_FREQ;
+	}
+}
 
 void bootstrap(void)
@@ -113,31 +186,7 @@
 	
 	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();
 	
 	printf("Booting the kernel ...\n");
Index: boot/arch/mips32/Makefile.inc
===================================================================
--- boot/arch/mips32/Makefile.inc	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/arch/mips32/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/arch/mips32/src/asm.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/_link.ld.in	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/include/arch.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/include/asm.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/include/asm.h
Index: boot/arch/mips64/include/main.h
===================================================================
--- boot/arch/mips64/include/main.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/include/main.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/include/main.h
Index: boot/arch/mips64/include/regname.h
===================================================================
--- boot/arch/mips64/include/regname.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/include/regname.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/include/regname.h
Index: boot/arch/mips64/include/types.h
===================================================================
--- boot/arch/mips64/include/types.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/include/types.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/src/asm.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/src/main.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/arch/mips64/src/putchar.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/sparc64/Makefile.inc
===================================================================
--- boot/arch/sparc64/Makefile.inc	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/arch/sparc64/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ boot/arch/sparc64/src/main.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ boot/genarch/include/efi.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,59 @@
+/*
+ * 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_
+
+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
+
+#endif
Index: ntrib/tools/serengeti_silo.sh
===================================================================
--- contrib/tools/serengeti_silo.sh	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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: defaults/amd64/Makefile.config
===================================================================
--- defaults/amd64/Makefile.config	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ defaults/amd64/Makefile.config	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -65,2 +65,4 @@
 CONFIG_MOUNT_DATA = n
 
+# OHCI root hub power switch, ganged is enough
+OHCI_POWER_SWITCH = ganged
Index: defaults/ia32/Makefile.config
===================================================================
--- defaults/ia32/Makefile.config	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ defaults/ia32/Makefile.config	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ defaults/mips64/Makefile.config	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ defaults/mips64/msim/Makefile.config	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,2 @@
+# Machine type
+MACHINE = msim
Index: defaults/mips64/output
===================================================================
--- defaults/mips64/output	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ defaults/mips64/output	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+image.boot
Index: defaults/sparc64/Makefile.config
===================================================================
--- defaults/sparc64/Makefile.config	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ defaults/sparc64/Makefile.config	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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/arch/amd64/Makefile.inc
===================================================================
--- kernel/arch/amd64/Makefile.inc	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/amd64/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -41,5 +41,5 @@
 # is fixed.
 #
-# If GCC generates a code for tail call, instead of generating ..
+# When GCC generates a code for tail call, instead of generating ..
 #
 #   jmp *fnc
@@ -48,4 +48,6 @@
 #
 #   jmp *$fnc
+#
+# See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48385 for reference.
 #
 
Index: kernel/arch/arm32/src/mach/gta02/gta02.c
===================================================================
--- kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/arm32/src/mach/gta02/gta02.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/arm32/src/mach/integratorcp/integratorcp.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -53,5 +53,4 @@
 
 #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;
@@ -296,11 +295,6 @@
 	
 	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/ia32/src/boot/vesa_real.inc
===================================================================
--- kernel/arch/ia32/src/boot/vesa_real.inc	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/ia32/src/boot/vesa_real.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/ia64/include/bootinfo.h
===================================================================
--- kernel/arch/ia64/include/bootinfo.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/ia64/include/bootinfo.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/src/drivers/ski.c
===================================================================
--- kernel/arch/ia64/src/drivers/ski.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/ia64/src/drivers/ski.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/ia64/src/ia64.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -151,5 +151,5 @@
 	/* Set platform name. */
 #ifdef MACHINE_ski
-	platform = "pc";
+	platform = "ski";
 #endif
 #ifdef MACHINE_i460GX
Index: kernel/arch/ia64/src/mm/frame.c
===================================================================
--- kernel/arch/ia64/src/mm/frame.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/ia64/src/mm/frame.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/mips32/Makefile.inc
===================================================================
--- kernel/arch/mips32/Makefile.inc	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/cycle.h
===================================================================
--- kernel/arch/mips32/include/cycle.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/include/cycle.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup mips2
+/** @addtogroup mips32
  * @{
  */
Index: kernel/arch/mips32/include/debug.h
===================================================================
--- kernel/arch/mips32/include/debug.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/include/debug.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/mm/frame.h
===================================================================
--- kernel/arch/mips32/include/mm/frame.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/include/mm/frame.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -42,6 +42,4 @@
 #ifndef __ASM__
 
-#include <typedefs.h>
-
 extern void frame_arch_init(void);
 extern void physmem_print(void);
Index: kernel/arch/mips32/include/stack.h
===================================================================
--- kernel/arch/mips32/include/stack.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/include/stack.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/src/cache.c
===================================================================
--- kernel/arch/mips32/src/cache.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/src/cache.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup mips32	
+/** @addtogroup mips32
  * @{
  */
Index: kernel/arch/mips32/src/cpu/cpu.c
===================================================================
--- kernel/arch/mips32/src/cpu/cpu.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/src/cpu/cpu.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/fpu_context.c
===================================================================
--- kernel/arch/mips32/src/fpu_context.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/src/fpu_context.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/mm/as.c
===================================================================
--- kernel/arch/mips32/src/mm/as.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/src/mm/as.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/tlb.c
===================================================================
--- kernel/arch/mips32/src/mm/tlb.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/src/mm/tlb.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -73,5 +73,5 @@
 		tlbwi();
 	}
-		
+	
 	/*
 	 * The kernel is going to make use of some wired
@@ -386,13 +386,10 @@
 			ASSERT(pte->w || access != PF_ACCESS_WRITE);
 			return pte;
-			break;
 		case AS_PF_DEFER:
 			*pfrc = AS_PF_DEFER;
 			return NULL;
-			break;
 		case AS_PF_FAULT:
 			*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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/mips32/src/start.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/_link.ld.in	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/arch.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/asm.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/asm/boot.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/asm/regname.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/atomic.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/barrier.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/cache.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/context.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/context_offset.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,181 @@
+/*
+ * 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__
+
+#include <arch/asm/regname.h>
+
+# 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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/cp0.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,143 @@
+/*
+ * 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_
+
+#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)
+#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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/cpu.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/cycle.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/debug.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/debugger.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/drivers/msim.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/elf.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/exception.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/faddr.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/fpu_context.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/interrupt.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/istate.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,121 @@
+/*
+ * 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 <arch/cp0.h>
+
+#ifdef KERNEL
+
+#include <typedefs.h>
+#include <trace.h>
+
+#else
+
+#include <sys/types.h>
+#define NO_TRACE
+
+#endif
+
+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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/mm/as.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/mm/asid.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/mm/frame.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,53 @@
+/*
+ * 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)
+
+#ifdef KERNEL
+#ifndef __ASM__
+
+extern void frame_arch_init(void);
+extern void physmem_print(void);
+
+#endif /* __ASM__ */
+#endif /* KERNEL */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/mm/page.h
===================================================================
--- kernel/arch/mips64/include/mm/page.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/mm/page.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,63 @@
+/*
+ * 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
+
+#ifdef KERNEL
+#ifndef __ASM__
+
+extern void page_arch_init(void);
+
+#endif /* __ASM__ */
+#endif /* KERNEL */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/mips64/include/mm/tlb.h
===================================================================
--- kernel/arch/mips64/include/mm/tlb.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/mm/tlb.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/proc/task.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/proc/thread.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/smp/dorder.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/stack.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/include/types.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/asm.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/cache.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/src/cache.c
Index: kernel/arch/mips64/src/context.S
===================================================================
--- kernel/arch/mips64/src/context.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/context.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/src/context.S
Index: kernel/arch/mips64/src/cpu
===================================================================
--- kernel/arch/mips64/src/cpu	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/cpu	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/src/cpu
Index: kernel/arch/mips64/src/ddi
===================================================================
--- kernel/arch/mips64/src/ddi	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/ddi	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/src/ddi
Index: kernel/arch/mips64/src/debug
===================================================================
--- kernel/arch/mips64/src/debug	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/debug	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/src/debug
Index: kernel/arch/mips64/src/debugger.c
===================================================================
--- kernel/arch/mips64/src/debugger.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/debugger.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/src/debugger.c
Index: kernel/arch/mips64/src/exception.c
===================================================================
--- kernel/arch/mips64/src/exception.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/exception.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/fpu_context.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/src/fpu_context.c
Index: kernel/arch/mips64/src/interrupt.c
===================================================================
--- kernel/arch/mips64/src/interrupt.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/interrupt.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/mips64.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 <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 <genarch/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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/mm/as.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/mm/frame.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/mm/page.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/mm/tlb.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/smp/dorder.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/smp/smp.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/arch/mips64/src/start.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/sparc64/Makefile.inc
===================================================================
--- kernel/arch/sparc64/Makefile.inc	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/sparc64/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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: rnel/arch/sparc64/include/drivers/fhc.h
===================================================================
--- kernel/arch/sparc64/include/drivers/fhc.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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/src/console.c
===================================================================
--- kernel/arch/sparc64/src/console.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/sparc64/src/console.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/arch/sparc64/src/drivers/niagara.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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: rnel/arch/sparc64/src/drivers/sgcn.c
===================================================================
--- kernel/arch/sparc64/src/drivers/sgcn.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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/genarch/Makefile.inc
===================================================================
--- kernel/genarch/Makefile.inc	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/genarch/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 += \
@@ -141,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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/genarch/include/drivers/s3c24xx_uart/s3c24xx_uart.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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: rnel/genarch/include/ofw/fhc.h
===================================================================
--- kernel/genarch/include/ofw/fhc.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/genarch/src/drivers/dsrln/dsrlnout.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/genarch/src/drivers/ega/ega.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -64,4 +64,6 @@
 	IRQ_SPINLOCK_DECLARE(lock);
 	
+	parea_t parea;
+	
 	uint32_t cursor;
 	uint8_t *addr;
@@ -70,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 *);
 
@@ -437,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)
@@ -448,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),
@@ -459,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);
@@ -469,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,
@@ -481,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);
@@ -503,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);
@@ -529,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;
@@ -535,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;
@@ -555,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);
@@ -572,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);
@@ -612,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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/genarch/src/drivers/s3c24xx_uart/s3c24xx_uart.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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: rnel/genarch/src/drivers/z8530/z8530.c
===================================================================
--- kernel/genarch/src/drivers/z8530/z8530.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/genarch/src/fb/fb.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -82,4 +82,6 @@
 	SPINLOCK_DECLARE(lock);
 	
+	parea_t parea;
+	
 	uint8_t *addr;
 	uint16_t *backbuf;
@@ -109,5 +111,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 +217,5 @@
  *
  */
-static void logo_hide(fb_instance_t *instance, bool silent)
+static void logo_hide(fb_instance_t *instance)
 {
 	instance->ylogo = 0;
@@ -221,5 +223,5 @@
 	instance->rowtrim = instance->rows;
 	
-	if (!silent)
+	if ((!instance->parea.mapped) || (console_override))
 		fb_redraw_internal(instance);
 }
@@ -229,5 +231,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 +238,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 +255,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 +300,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 +314,5 @@
 	
 	glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
-	    col, row, silent, true);
+	    col, row, true);
 }
 
@@ -362,5 +364,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 +371,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 +397,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 +403,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 +557,5 @@
 	
 	spinlock_initialize(&instance->lock, "*fb.instance.lock");
+	
 	instance->rgb_conv = rgb_conv;
 	instance->pixelbytes = pixelbytes;
@@ -623,8 +626,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/ofw/fhc.c
===================================================================
--- kernel/genarch/src/ofw/fhc.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,137 +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 <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/generic/include/console/chardev.h
===================================================================
--- kernel/generic/include/console/chardev.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/include/console/chardev.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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. */
Index: kernel/generic/include/console/console.h
===================================================================
--- kernel/generic/include/console/console.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/include/console/console.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/ddi/ddi.h
===================================================================
--- kernel/generic/include/ddi/ddi.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/include/ddi/ddi.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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: kernel/generic/include/lib/elf.h
===================================================================
--- kernel/generic/include/lib/elf.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/include/lib/elf.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -106,15 +106,4 @@
 #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
 
 /**
@@ -149,4 +138,9 @@
 #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
@@ -195,5 +189,4 @@
  * ELF object file specifications. They are the only types used
  * in ELF header.
- *
  */
 typedef uint64_t elf_xword;
@@ -207,5 +200,4 @@
  *
  * These types are specific for 32-bit format.
- *
  */
 typedef uint32_t elf32_addr;
@@ -216,5 +208,4 @@
  *
  * These types are specific for 64-bit format.
- *
  */
 typedef uint64_t elf64_addr;
@@ -332,4 +323,26 @@
 };
 
+/*
+ * 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;
@@ -337,4 +350,5 @@
 typedef struct elf32_section_header elf_section_header_t;
 typedef struct elf32_symbol elf_symbol_t;
+typedef struct elf32_note elf_note_t;
 #endif
 
@@ -344,7 +358,6 @@
 typedef struct elf64_section_header elf_section_header_t;
 typedef struct elf64_symbol elf_symbol_t;
+typedef struct elf64_note elf_note_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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ kernel/generic/include/lib/elf_load.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/include/mm/as.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -65,4 +65,5 @@
 #include <arch/mm/as.h>
 #include <arch/mm/asid.h>
+#include <arch/istate.h>
 #include <typedefs.h>
 #include <synch/spinlock.h>
@@ -306,14 +307,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);
Index: kernel/generic/include/panic.h
===================================================================
--- kernel/generic/include/panic.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/include/panic.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/include/syscall/syscall.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -94,6 +94,5 @@
 	SYS_SYSINFO_GET_DATA,
 	
-	SYS_DEBUG_ENABLE_CONSOLE,
-	SYS_DEBUG_DISABLE_CONSOLE,
+	SYS_DEBUG_ACTIVATE_CONSOLE,
 	
 	SYSCALL_END
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/console/console.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -87,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 *);
 
@@ -95,6 +95,6 @@
 };
 
-/** Silence output */
-bool silent = false;
+/** Override kernel console lockout */
+bool console_override = false;
 
 /** Standard input and output character devices */
@@ -122,10 +122,10 @@
 }
 
-static void stdout_write(outdev_t *dev, wchar_t ch, bool silent)
+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);
 	}
 }
@@ -156,4 +156,5 @@
 	klog_parea.frames = SIZE2FRAMES(sizeof(klog));
 	klog_parea.unpriv = false;
+	klog_parea.mapped = false;
 	ddi_parea_register(&klog_parea);
 	
@@ -167,11 +168,11 @@
 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.
@@ -183,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
@@ -196,11 +196,4 @@
 	return false;
 #endif
-}
-
-/** Tell kernel to relinquish keyboard/console access */
-sysarg_t sys_debug_disable_console(void)
-{
-	release_console();
-	return true;
 }
 
@@ -289,5 +282,5 @@
 			 */
 			spinlock_unlock(&klog_lock);
-			stdout->op->write(stdout, tmp, silent);
+			stdout->op->write(stdout, tmp);
 			spinlock_lock(&klog_lock);
 		}
@@ -317,5 +310,5 @@
 		 * it should be no longer buffered.
 		 */
-		stdout->op->write(stdout, ch, silent);
+		stdout->op->write(stdout, ch);
 	} else {
 		/*
Index: kernel/generic/src/ddi/ddi.c
===================================================================
--- kernel/generic/src/ddi/ddi.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/ddi/ddi.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -122,5 +122,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 +179,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 +186,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 +199,11 @@
 	 * Mapping is created on-demand during page fault.
 	 */
-	return 0;
+	
+	if (parea != NULL) {
+		parea->mapped = true;
+		mutex_unlock(&parea_lock);
+	}
+	
+	return EOK;
 }
 
Index: kernel/generic/src/ddi/irq.c
===================================================================
--- kernel/generic/src/ddi/irq.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/ddi/irq.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/debug/panic.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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) {
Index: kernel/generic/src/lib/elf.c
===================================================================
--- kernel/generic/src/lib/elf.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/lib/elf.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -47,4 +47,6 @@
 #include <macros.h>
 #include <arch.h>
+
+#include <lib/elf_load.h>
 
 static const char *error_codes[] = {
Index: kernel/generic/src/lib/rd.c
===================================================================
--- kernel/generic/src/lib/rd.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/lib/rd.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/mm/as.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -1284,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.
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/proc/program.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -48,5 +48,5 @@
 #include <ipc/ipcrsc.h>
 #include <security/cap.h>
-#include <lib/elf.h>
+#include <lib/elf_load.h>
 #include <errno.h>
 #include <print.h>
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/syscall/syscall.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -186,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/time/clock.c
===================================================================
--- kernel/generic/src/time/clock.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ kernel/generic/src/time/clock.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -94,4 +94,5 @@
 	clock_parea.frames = 1;
 	clock_parea.unpriv = true;
+	clock_parea.mapped = false;
 	ddi_parea_register(&clock_parea);
 	
Index: release/Makefile
===================================================================
--- release/Makefile	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ release/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ tools/autotool.py	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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)})
@@ -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/imgutil.py
===================================================================
--- tools/imgutil.py	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ tools/imgutil.py	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/mkext2.py
===================================================================
--- tools/mkext2.py	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ tools/mkext2.py	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ tools/mkfat.py	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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):
@@ -303,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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ tools/mktmpfs.py	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ tools/toolchain.sh	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -54,5 +54,5 @@
 
 BINUTILS_VERSION="2.21"
-GCC_VERSION="4.6.0"
+GCC_VERSION="4.6.1"
 GDB_VERSION="7.2"
 
@@ -274,7 +274,7 @@
 	
 	download_fetch "${BINUTILS_SOURCE}" "${BINUTILS}" "c84c5acc9d266f1a7044b51c85a823f5"
-	download_fetch "${GCC_SOURCE}" "${GCC_CORE}" "b1957f3209080b2f55bc3756d3a62b7c"
-	download_fetch "${GCC_SOURCE}" "${GCC_OBJC}" "120d4675366ee82ea52f9ed65b57da04"
-	download_fetch "${GCC_SOURCE}" "${GCC_CPP}" "a30090fa655d0db4c970740d353c81f1"
+	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"
 }
Index: tools/xstruct.py
===================================================================
--- tools/xstruct.py	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ tools/xstruct.py	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -153,5 +153,4 @@
 ifeq ($(UARCH),sparc64)
 	DIRS += \
-		srv/hw/irc/fhc \
 		srv/hw/irc/obio
 endif
@@ -165,4 +164,5 @@
 	lib/block \
 	lib/clui \
+	lib/scsi \
 	lib/softint \
 	lib/softfloat \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/Makefile.common	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -120,4 +120,6 @@
 LIBNET_PREFIX = $(LIB_PREFIX)/net
 
+LIBSCSI_PREFIX = $(LIB_PREFIX)/scsi
+
 ifeq ($(STATIC_NEEDED),y)
 	STATIC_BUILD = y
Index: uspace/app/bdsh/Makefile
===================================================================
--- uspace/app/bdsh/Makefile	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/bdsh/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -54,4 +54,5 @@
 	cmds/mod_cmds.c \
 	cmds/builtin_cmds.c \
+	compl.c \
 	errors.c \
 	input.c \
Index: uspace/app/bdsh/cmds/modules/cp/cp.c
===================================================================
--- uspace/app/bdsh/cmds/modules/cp/cp.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/bdsh/cmds/modules/cp/cp.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -71,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;
@@ -104,37 +104,11 @@
 	}
 
-	for (;;) {
-		ssize_t res;
-		size_t written = 0;
-
-		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 + written, res);
-			if (bytes < 0)
-				goto err;
-			written += bytes;
-			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/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -169,11 +169,11 @@
 		
 		/* fill the name field */
-		tosort[nbdirs].name = (char *) malloc(str_length(dp->d_name) + 1);
+		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_length(dp->d_name) + 1, dp->d_name);
+
+		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';
Index: uspace/app/bdsh/compl.c
===================================================================
--- uspace/app/bdsh/compl.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/app/bdsh/compl.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,354 @@
+/*
+ * 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 <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"
+
+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 p;
+	size_t pref_size;
+	char *stext = NULL;
+	char *prefix = NULL;
+	char *dirname = NULL;
+	char *rpath_sep;
+	static const char *dirlist_arg[] = { ".", NULL };
+	int retval;
+
+	cs = calloc(1, sizeof(compl_t));
+	if (!cs) {
+		retval = ENOMEM;
+		goto error;
+	}
+
+	/*
+	 * Copy token pointed to by caret from start up to the caret.
+	 * XXX Ideally we would use the standard tokenizer.
+	 */
+	p = pos;
+	while (p > 0 && text[p - 1] != (wchar_t) ' ')
+		--p;
+	*cstart = p;
+
+	/* Convert text buffer to string */
+	stext = wstr_to_astr(text + *cstart);
+	if (stext == NULL) {
+		retval = ENOMEM;
+		goto error;
+	}
+
+	/* Extract the prefix being completed */
+	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, 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.
+	 * XXX Again we should use the standard tokenizer/parser.
+	 */
+
+	/* Skip any whitespace before current token */
+	while (p > 0 && text[p - 1] == (wchar_t) ' ')
+		--p;
+
+	/*
+	 * It is a command if it is the first token or if it immediately
+	 * follows a pipe token.
+	 */
+	if (p == 0 || text[p - 1] == '|')
+		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);
+
+	*state = cs;
+	return EOK;
+
+error:
+	/* Error cleanup */
+
+	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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/app/bdsh/compl.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/bdsh/config.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -40,8 +40,4 @@
 #endif
 
-/* Work around for getenv() */
-#define PATH "/srv:/app"
-#define PATH_DELIM ":"
-
 /* Used in many places */
 #define SMALL_BUFLEN 256
Index: uspace/app/bdsh/exec.c
===================================================================
--- uspace/app/bdsh/exec.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/bdsh/exec.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -52,4 +52,6 @@
 static int try_access(const char *);
 
+const char *search_dir[] = { "/app", "/srv", NULL };
+
 /* work-around for access() */
 static int try_access(const char *f)
@@ -69,8 +71,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);
@@ -81,24 +80,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;
 		}
@@ -106,5 +90,4 @@
 
 	/* We didn't find it, just give it back as-is. */
-	free(path_tok);
 	return (char *) cmd;
 }
Index: uspace/app/bdsh/exec.h
===================================================================
--- uspace/app/bdsh/exec.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/bdsh/exec.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -33,4 +33,6 @@
 #include "scli.h"
 
+extern const char *search_dir[];
+
 extern unsigned int try_exec(char *, char **, iostate_t *);
 
Index: uspace/app/bdsh/input.c
===================================================================
--- uspace/app/bdsh/input.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/bdsh/input.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2008 Tim Post
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -43,4 +44,5 @@
 
 #include "config.h"
+#include "compl.h"
 #include "util.h"
 #include "scli.h"
@@ -168,5 +170,5 @@
 	}
 	
-	rc = run_command(cmd, usr, &new_iostate);
+	rc = run_command(actual_cmd, usr, &new_iostate);
 	
 finit_with_files:
@@ -226,9 +228,5 @@
 	int rc;
 	
-	console_flush(tinput->console);
-	console_set_style(tinput->console, STYLE_EMPHASIS);
-	printf("%s", usr->prompt);
-	console_flush(tinput->console);
-	console_set_style(tinput->console, STYLE_NORMAL);
+	tinput_set_prompt(tinput, usr->prompt);
 
 	rc = tinput_read(tinput, &str);
@@ -263,4 +261,6 @@
 	}
 
+	tinput_set_compl_ops(tinput, &compl_ops);
+
 	return 0;
 }
Index: uspace/app/bdsh/scli.h
===================================================================
--- uspace/app/bdsh/scli.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/bdsh/scli.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -32,4 +32,5 @@
 #include "config.h"
 #include <stdint.h>
+#include <stdio.h>
 
 typedef struct {
Index: uspace/app/ext2info/ext2info.c
===================================================================
--- uspace/app/ext2info/ext2info.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/ext2info/ext2info.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -590,5 +590,5 @@
 	printf("  Directory contents:\n");
 	
-	rc = ext2_directory_iterator_init(&it, fs, inode_ref);
+	rc = ext2_directory_iterator_init(&it, fs, inode_ref, 0);
 	if (rc != EOK) {
 		printf("Failed initializing directory iterator\n");
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/init/init.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -270,5 +270,4 @@
 	spawn("/srv/apic");
 	spawn("/srv/i8259");
-	spawn("/srv/fhc");
 	spawn("/srv/obio");
 	srv_start("/srv/cuda_adb");
@@ -295,4 +294,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/sbi/src/input.c
===================================================================
--- uspace/app/sbi/src/input.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/sbi/src/input.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/sbi/src/os/helenos.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/sbi/src/os/os.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/sbi/src/os/posix.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/taskdump/elf_core.c
===================================================================
--- uspace/app/taskdump/elf_core.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/taskdump/elf_core.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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,10 +62,10 @@
 #include <udebug.h>
 #include <macros.h>
-
-#include <elf.h>
-#include "include/elf_core.h"
+#include <libarch/istate.h>
+
+#include "elf_core.h"
 
 static off64_t align_foff_up(off64_t, uintptr_t, size_t);
-static int write_all(int, void *, size_t);
+static int align_pos(int, size_t);
 static int write_mem_area(int, as_area_info_t *, async_sess_t *);
 
@@ -83,5 +87,5 @@
  */
 int elf_core_save(const char *file_name, as_area_info_t *ainfo, unsigned int n,
-    async_sess_t *sess)
+    async_sess_t *sess, istate_t *istate)
 {
 	elf_header_t elf_hdr;
@@ -90,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");
@@ -115,7 +136,8 @@
 	 * 	ELF header
 	 *	program headers
+	 *	note segment
 	 * repeat:
 	 *	(pad for alignment)
-	 *	segment data
+	 *	core segment
 	 * end repeat
 	 */
@@ -147,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);
@@ -180,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);
@@ -187,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");
@@ -193,5 +270,5 @@
 			return EIO;
 		}
-		if (write_mem_area(fd, &ainfo[i], sess) != EOK) {
+		if (write_mem_area(fd, &ainfo[i - 1], sess) != EOK) {
 			printf("Failed writing memory data.\n");
 			free(p_hdr);
@@ -210,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)));
 }
@@ -231,5 +308,5 @@
 	size_t total;
 	uintptr_t addr;
-	int rc;
+	ssize_t rc;
 
 	addr = area->start_addr;
@@ -245,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;
@@ -257,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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/taskdump/include/elf_core.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -37,7 +37,9 @@
 
 #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 *);
+    async_sess_t *, istate_t *);
 
 #endif
Index: uspace/app/taskdump/include/symtab.h
===================================================================
--- uspace/app/taskdump/include/symtab.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/taskdump/include/symtab.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/taskdump/symtab.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/taskdump/taskdump.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -34,4 +34,5 @@
 
 #include <async.h>
+#include <elf/elf_linux.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -72,4 +73,6 @@
 static char *get_app_task_name(void);
 static char *fmt_sym_address(uintptr_t addr);
+
+static istate_t reg_state;
 
 int main(int argc, char *argv[])
@@ -293,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, sess);
+
+		rc = elf_core_save(core_file_name, ainfo_buf, n_areas, sess,
+		    &reg_state);
+
 		if (rc != EOK) {
 			printf("Failed writing core file.\n");
@@ -321,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);
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/app/trace/syscalls.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -80,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/drv/bus/isa/isa.c
===================================================================
--- uspace/drv/bus/isa/isa.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/isa/isa.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -352,4 +352,6 @@
 		    str_error(rc));
 	}
+
+	free(id);
 }
 
Index: uspace/drv/bus/pci/pciintel/pci.c
===================================================================
--- uspace/drv/bus/pci/pciintel/pci.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/pci/pciintel/pci.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -342,4 +342,6 @@
 	}
 	
+	free(match_id_str);
+	
 	/* TODO add more ids (with subsys ids, using class id etc.) */
 }
Index: uspace/drv/bus/usb/ohci/hc.c
===================================================================
--- uspace/drv/bus/usb/ohci/hc.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/ohci/hc.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -46,8 +46,73 @@
 #define OHCI_USED_INTERRUPTS \
     (I_SO | I_WDH | I_UE | I_RHSC)
-static int interrupt_emulator(hc_t *instance);
+
+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
@@ -83,17 +148,14 @@
 	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(%d) to add OHCI rh endpoint 0.\n", ret);
-
-	char *match_str = NULL;
-	/* DDF needs heap allocated string */
-	ret = asprintf(&match_str, "usb&class=hub");
-	ret = ret > 0 ? 0 : ret;
-	CHECK_RET_RELEASE(ret, "Failed(%d) to create match-id string.\n", ret);
-
-	ret = ddf_fun_add_match_id(hub_fun, match_str, 100);
-	CHECK_RET_RELEASE(ret, "Failed(%d) add root hub match-id.\n", ret);
+	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(%d) to bind root hub function.\n", ret);
+	CHECK_RET_RELEASE(ret,
+	    "Failed to bind root hub function: %s.\n", str_error(ret));
 
 	return EOK;
@@ -112,5 +174,5 @@
 {
 	assert(instance);
-	int ret = EOK;
+
 #define CHECK_RET_RETURN(ret, message...) \
 if (ret != EOK) { \
@@ -119,11 +181,12 @@
 } else (void)0
 
-	ret = pio_enable((void*)regs, reg_size, (void**)&instance->registers);
+	int ret =
+	    pio_enable((void*)regs, reg_size, (void**)&instance->registers);
 	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to gain access to device registers: %s.\n",
-	    ret, str_error(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);
@@ -137,7 +200,6 @@
 
 	fibril_mutex_initialize(&instance->guard);
+
 	hc_gain_control(instance);
-
-	rh_init(&instance->rh, instance->registers);
 
 	if (!interrupts) {
@@ -147,8 +209,11 @@
 	}
 
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/** Create end register endpoint structures
+	rh_init(&instance->rh, instance->registers);
+	hc_start(instance);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Create and register endpoint structures.
  *
  * @param[in] instance OHCI driver structure.
@@ -168,13 +233,8 @@
     size_t mps, size_t size, unsigned interval)
 {
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	endpoint_t *ep =
+	    endpoint_get(address, endpoint, direction, type, speed, mps);
 	if (ep == NULL)
 		return ENOMEM;
-	int ret =
-	    endpoint_init(ep, address, endpoint, direction, type, speed, mps);
-	if (ret != EOK) {
-		free(ep);
-		return ret;
-	}
 
 	hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep);
@@ -184,5 +244,6 @@
 	}
 
-	ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
+	int ret =
+	    usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size);
 	if (ret != EOK) {
 		hcd_endpoint_clear(ep);
@@ -212,6 +273,4 @@
 		    &instance->lists[ep->transfer_type], hcd_ep);
 		instance->registers->control |= C_PLE | C_IE;
-		break;
-	default:
 		break;
 	}
@@ -312,5 +371,6 @@
 	/* Check for root hub communication */
 	if (batch->ep->address == instance->rh.address) {
-		return rh_request(&instance->rh, batch);
+		rh_request(&instance->rh, batch);
+		return EOK;
 	}
 
@@ -374,5 +434,5 @@
 
 	if (status & I_UE) {
-		hc_start_hw(instance);
+		hc_start(instance);
 	}
 
@@ -399,4 +459,7 @@
 /** 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.
  */
@@ -404,14 +467,22 @@
 {
 	assert(instance);
+
 	usb_log_debug("Requesting OHCI control.\n");
-	/* Turn off legacy emulation */
-	volatile uint32_t *ohci_emulation_reg =
-	    (uint32_t*)((char*)instance->registers + 0x100);
-	usb_log_debug("OHCI legacy register %p: %x.\n",
-	    ohci_emulation_reg, *ohci_emulation_reg);
-	/* Do not change A20 state */
-	*ohci_emulation_reg &= 0x100;
-	usb_log_debug("OHCI legacy register %p: %x.\n",
-	    ohci_emulation_reg, *ohci_emulation_reg);
+	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 */
@@ -419,15 +490,15 @@
 		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");
-		instance->registers->control &= (C_HCFS_RESET << C_HCFS_SHIFT);
+		C_HCFS_SET(instance->registers->control, C_HCFS_RESET);
 		async_usleep(50000);
 		return;
 	}
 
-	const unsigned hc_status =
-	    (instance->registers->control >> C_HCFS_SHIFT) & C_HCFS_MASK;
+	const unsigned hc_status = C_HCFS_GET(instance->registers->control);
 	/* Interrupt routing disabled && status != USB_RESET => BIOS active */
 	if (hc_status != C_HCFS_RESET) {
@@ -437,6 +508,6 @@
 			return;
 		}
-		/* HC is suspended assert resume for 20ms */
-		instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
+		/* 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");
@@ -454,5 +525,5 @@
  * @param[in] instance OHCI hc driver structure.
  */
-void hc_start_hw(hc_t *instance)
+void hc_start(hc_t *instance)
 {
 	/* OHCI guide page 42 */
@@ -516,5 +587,5 @@
 	    instance->registers->periodic_start, frame_length);
 
-	instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
+	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);
@@ -534,6 +605,6 @@
 	int ret = endpoint_list_init(&instance->lists[type], name); \
 	if (ret != EOK) { \
-		usb_log_error("Failed(%d) to setup %s endpoint list.\n", \
-		    ret, name); \
+		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]); \
@@ -587,38 +658,7 @@
 	    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
 
-	/* Init interrupt code */
-	instance->interrupt_code.cmds = instance->interrupt_commands;
-	instance->interrupt_code.cmdcount = OHCI_NEEDED_IRQ_COMMANDS;
-	{
-		/* Read status register */
-		instance->interrupt_commands[0].cmd = CMD_MEM_READ_32;
-		instance->interrupt_commands[0].dstarg = 1;
-		instance->interrupt_commands[0].addr =
-		    (void*)&instance->registers->interrupt_status;
-
-		/* Test whether we are the interrupt cause */
-		instance->interrupt_commands[1].cmd = CMD_BTEST;
-		instance->interrupt_commands[1].value =
-		    OHCI_USED_INTERRUPTS;
-		instance->interrupt_commands[1].srcarg = 1;
-		instance->interrupt_commands[1].dstarg = 2;
-
-		/* Predicate cleaning and accepting */
-		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
-		instance->interrupt_commands[2].value = 2;
-		instance->interrupt_commands[2].srcarg = 2;
-
-		/* Write-clean status register */
-		instance->interrupt_commands[3].cmd = CMD_MEM_WRITE_A_32;
-		instance->interrupt_commands[3].srcarg = 1;
-		instance->interrupt_commands[3].addr =
-		    (void*)&instance->registers->interrupt_status;
-
-		/* Accept interrupt */
-		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
-	}
-
-	return EOK;
-}
+	return EOK;
+}
+
 /**
  * @}
Index: uspace/drv/bus/usb/ohci/hc.h
===================================================================
--- uspace/drv/bus/usb/ohci/hc.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/ohci/hc.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -51,7 +51,5 @@
 #include "hw_struct/hcca.h"
 
-#define OHCI_NEEDED_IRQ_COMMANDS 5
-
-/** Main OHCI drier structure */
+/** Main OHCI driver structure */
 typedef struct hc {
 	/** USB bus driver, devices and addresses */
@@ -76,17 +74,13 @@
 	fibril_mutex_t guard;
 
-	/** Code to be executed in kernel interrupt handler */
-	irq_code_t interrupt_code;
-
-	/** Commands that form interrupt code */
-	irq_cmd_t interrupt_commands[OHCI_NEEDED_IRQ_COMMANDS];
-
 	/** 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);
-int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts);
-void hc_start_hw(hc_t *instance);
 
 /** Safely dispose host controller internal structures
Index: uspace/drv/bus/usb/ohci/ohci.c
===================================================================
--- uspace/drv/bus/usb/ohci/ohci.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/ohci/ohci.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -58,8 +58,6 @@
 {
 	assert(dev);
-	assert(dev->driver_data);
 	return dev->driver_data;
 }
-
 /** IRQ handling callback, identifies device
  *
@@ -70,8 +68,13 @@
 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
 {
-	hc_t *hc = &dev_to_ohci(dev)->hc;
-	assert(hc);
+	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(hc, status);
+	hc_interrupt(&ohci->hc, status);
 }
 /*----------------------------------------------------------------------------*/
@@ -166,4 +169,5 @@
 	} \
 	free(instance); \
+	device->driver_data = NULL; \
 	usb_log_error(message); \
 	return ret; \
@@ -173,5 +177,6 @@
 	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.\n");
+	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;
@@ -179,5 +184,6 @@
 	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.\n");
+	CHECK_RET_DEST_FREE_RETURN(ret,
+	    "Failed to create OHCI RH function: %s.\n", str_error(ret));
 	instance->rh_fun->ops = &rh_ops;
 
@@ -193,40 +199,48 @@
 	    (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;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, "
-	    "falling back to polling.\n");
-#else
 	ret = pci_enable_interrupts(device);
 	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
-		    str_error(ret));
-		usb_log_info("HW interrupts not available, "
-		    "falling back to polling.\n");
+		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;
 	}
-#endif
 
 	ret = hc_init(&instance->hc, reg_base, reg_size, interrupts);
-	CHECK_RET_DEST_FREE_RETURN(ret, "Failed(%d) to init ohci_hcd.\n", ret);
+	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
 
-	/* It does no harm if we register this on polling */
-	ret = register_interrupt_handler(device, irq, irq_handler,
-	    &instance->hc.interrupt_code);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register interrupt handler.\n", ret);
 
 	ret = ddf_fun_bind(instance->hc_fun);
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to bind OHCI device function: %s.\n",
-	    ret, str_error(ret));
+	    "Failed to bind OHCI device function: %s.\n", str_error(ret));
 
 	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
@@ -234,7 +248,4 @@
 	    "Failed to add OHCI to HC class: %s.\n", str_error(ret));
 
-	device->driver_data = instance;
-
-	hc_start_hw(&instance->hc);
 	hc_register_hub(&instance->hc, instance->rh_fun);
 	return EOK;
Index: uspace/drv/bus/usb/ohci/ohci_regs.h
===================================================================
--- uspace/drv/bus/usb/ohci/ohci_regs.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/ohci/ohci_regs.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -34,16 +34,22 @@
 #ifndef DRV_OHCI_OHCI_REGS_H
 #define DRV_OHCI_OHCI_REGS_H
-#include <stdint.h>
+#include <sys/types.h>
+
+#define LEGACY_REGS_OFFSET 0x100
 
 /** OHCI memory mapped registers structure */
 typedef struct ohci_regs {
-	const volatile uint32_t revision;
-	volatile uint32_t control;
-#define C_CSBR_MASK (0x3) /* Control-bulk service ratio */
-#define C_CSBR_1_1  (0x0)
-#define C_CSBR_1_2  (0x1)
-#define C_CSBR_1_3  (0x2)
-#define C_CSBR_1_4  (0x3)
-#define C_CSBR_SHIFT (0)
+	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 */
@@ -59,9 +65,18 @@
 #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 */
 
-	volatile uint32_t command_status;
+	ioport32_t command_status;
 #define CS_HCR (1 << 0)   /* Host controller reset */
 #define CS_CLF (1 << 1)   /* Control list filled */
@@ -75,7 +90,7 @@
 	 * writing causes enable/disable,
 	 * status is write-clean (writing 1 clears the bit*/
-	volatile uint32_t interrupt_status;
-	volatile uint32_t interrupt_enable;
-	volatile uint32_t interrupt_disable;
+	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 */
@@ -89,27 +104,27 @@
 
 	/** HCCA pointer (see hw_struct hcca.h) */
-	volatile uint32_t hcca;
+	ioport32_t hcca;
 #define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
 
 	/** Currently executed periodic endpoint */
-	const volatile uint32_t periodic_current;
+	const ioport32_t periodic_current;
 
 	/** The first control endpoint */
-	volatile uint32_t control_head;
+	ioport32_t control_head;
 
 	/** Currently executed control endpoint */
-	volatile uint32_t control_current;
+	ioport32_t control_current;
 
 	/** The first bulk endpoint */
-	volatile uint32_t bulk_head;
+	ioport32_t bulk_head;
 
 	/** Currently executed bulk endpoint */
-	volatile uint32_t bulk_current;
+	ioport32_t bulk_current;
 
 	/** Done TD list, this value is periodically written to HCCA */
-	const volatile uint32_t done_head;
+	const ioport32_t done_head;
 
 	/** Frame time and max packet size for all transfers */
-	volatile uint32_t fm_interval;
+	ioport32_t fm_interval;
 #define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/
 #define FMI_FI_SHIFT (0)
@@ -119,5 +134,5 @@
 
 	/** Bit times remaining in current frame */
-	const volatile uint32_t fm_remaining;
+	const ioport32_t fm_remaining;
 #define FMR_FR_MASK FMI_FI_MASK
 #define FMR_FR_SHIFT FMI_FI_SHIFT
@@ -125,17 +140,17 @@
 
 	/** Frame number */
-	const volatile uint32_t fm_number;
+	const ioport32_t fm_number;
 #define FMN_NUMBER_MASK (0xffff)
 
 	/** Remaining bit time in frame to start periodic transfers */
-	volatile uint32_t periodic_start;
+	ioport32_t periodic_start;
 #define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
 
 	/** Threshold for starting LS transaction */
-	volatile uint32_t ls_threshold;
+	ioport32_t ls_threshold;
 #define LST_LST_MASK (0x7fff)
 
 	/** The first root hub control register */
-	volatile uint32_t rh_desc_a;
+	ioport32_t rh_desc_a;
 #define RHDA_NDS_MASK (0xff) /* Number of downstream ports, max 15 */
 #define RHDA_NDS_SHIFT (0)
@@ -144,10 +159,10 @@
 #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      (1 << 12) /* OC control: 0-use OCPM, 1-OC off */
+#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 */
-	volatile uint32_t rh_desc_b;
+	ioport32_t rh_desc_b;
 #define RHDB_DR_MASK (0xffff) /* Device removable mask */
 #define RHDB_DR_SHIFT (0)
@@ -161,5 +176,5 @@
 
 	/** Root hub status register */
-	volatile uint32_t rh_status;
+	ioport32_t rh_status;
 #define RHS_LPS_FLAG  (1 <<  0)/* read: 0,
                                 * write: 0-no effect,
@@ -167,5 +182,5 @@
                                 *        specified in PPCM(RHDB), or all ports,
                                 *        if power is set globally */
-#define RHS_CLEAR_PORT_POWER RHS_LPS_FLAG /* synonym for the above */
+#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
@@ -178,10 +193,10 @@
                                 *        specified in PPCM(RHDB), or all ports,
                                 *        if power is set globally */
-#define RHS_SET_PORT_POWER RHS_LPSC_FLAG /* synonym for the above */
+#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 */
-	volatile uint32_t rh_port_status[];
+	ioport32_t rh_port_status[];
 #define RHPS_CCS_FLAG (1 << 0) /* r: current connect status,
                                 * w: 1-clear port enable, 0-nothing */
Index: uspace/drv/bus/usb/ohci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/ohci/root_hub.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/ohci/root_hub.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -40,4 +40,5 @@
 #include "root_hub.h"
 #include <usb/classes/classes.h>
+#include <usb/classes/hub.h>
 #include <usb/dev/driver.h>
 #include "ohci_regs.h"
@@ -56,7 +57,7 @@
 	.device_subclass = 0,
 	.device_version = 0,
-	.length = sizeof (usb_standard_device_descriptor_t),
-	.max_packet_size = 8,
-	.vendor_id = 0x16db,
+	.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,
@@ -73,6 +74,6 @@
 	.descriptor_type = USB_DESCTYPE_CONFIGURATION,
 	.interface_count = 1,
-	.length = sizeof (usb_standard_configuration_descriptor_t),
-	.max_power = 100,
+	.length = sizeof(usb_standard_configuration_descriptor_t),
+	.max_power = 0, /* root hubs don't need no power */
 	.str_configuration = 0,
 };
@@ -89,5 +90,5 @@
 	.interface_protocol = 0,
 	.interface_subclass = 0,
-	.length = sizeof (usb_standard_interface_descriptor_t),
+	.length = sizeof(usb_standard_interface_descriptor_t),
 	.str_interface = 0,
 };
@@ -100,345 +101,268 @@
 	.descriptor_type = USB_DESCTYPE_ENDPOINT,
 	.endpoint_address = 1 + (1 << 7),
-	.length = sizeof (usb_standard_endpoint_descriptor_t),
-	.max_packet_size = 8,
+	.length = sizeof(usb_standard_endpoint_descriptor_t),
+	.max_packet_size = 2,
 	.poll_interval = 255,
 };
 
-/**
- * bitmask of hub features that are valid to be cleared
- */
-static const uint32_t hub_clear_feature_valid_mask =
-    RHS_OCIC_FLAG |
-    RHS_CLEAR_PORT_POWER;
-
-/**
- * bitmask of hub features that are cleared by writing 1 (and not 0)
- */
-static const uint32_t hub_clear_feature_by_writing_one_mask =
-    RHS_CLEAR_PORT_POWER;
-
-/**
- * bitmask of hub features that are valid to be set
- */
-static const uint32_t hub_set_feature_valid_mask =
-    RHS_LPSC_FLAG |
-    RHS_OCIC_FLAG;
-
-/**
- * bitmask of hub features that are set by writing 1 and cleared by writing 0
- */
-static const uint32_t hub_set_feature_direct_mask =
-    RHS_SET_PORT_POWER;
-
-/**
- * bitmask of port features that are valid to be set
- */
-static const uint32_t port_set_feature_valid_mask =
-    RHPS_SET_PORT_ENABLE |
-    RHPS_SET_PORT_SUSPEND |
-    RHPS_SET_PORT_RESET |
-    RHPS_SET_PORT_POWER;
-
-/**
- * bitmask of port features that can be cleared
- */
-static const uint32_t port_clear_feature_valid_mask =
-    RHPS_CCS_FLAG |
-    RHPS_SET_PORT_SUSPEND |
-    RHPS_POCI_FLAG |
-    RHPS_SET_PORT_POWER |
-    RHPS_CSC_FLAG |
-    RHPS_PESC_FLAG |
-    RHPS_PSSC_FLAG |
-    RHPS_OCIC_FLAG |
-    RHPS_PRSC_FLAG;
-
-//note that USB_HUB_FEATURE_PORT_POWER bit is translated into
-//USB_HUB_FEATURE_PORT_LOW_SPEED for port set feature request
-
-/**
- * bitmask with port status changes
- */
-static const uint32_t port_status_change_mask = RHPS_CHANGE_WC_MASK;
-
-static int create_serialized_hub_descriptor(rh_t *instance);
-
-static int rh_init_descriptors(rh_t *instance);
-
-static int process_get_port_status_request(rh_t *instance, uint16_t port,
-    usb_transfer_batch_t * request);
-
-static int process_get_hub_status_request(rh_t *instance,
-    usb_transfer_batch_t * request);
-
-static int process_get_status_request(rh_t *instance,
-    usb_transfer_batch_t * request);
-
-static void create_interrupt_mask_in_instance(rh_t *instance);
-
-static int process_get_descriptor_request(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_get_configuration_request(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_hub_feature_set_request(rh_t *instance, uint16_t feature);
-
-static int process_hub_feature_clear_request(rh_t *instance,
-    uint16_t feature);
-
-static int process_port_feature_set_request(rh_t *instance,
-    uint16_t feature, uint16_t port);
-
-static int process_port_feature_clear_request(rh_t *instance,
-    uint16_t feature, uint16_t port);
-
-static int process_address_set_request(rh_t *instance,
-    uint16_t address);
-
-static int process_request_with_output(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_request_with_input(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_request_without_data(rh_t *instance,
-    usb_transfer_batch_t *request);
-
-static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
-
-static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request);
-
-static bool is_zeros(void * buffer, size_t size);
-
-/** Root hub initialization
- * @return Error code.
- */
-int rh_init(rh_t *instance, ohci_regs_t *regs) {
-	assert(instance);
+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;
-	int opResult = rh_init_descriptors(instance);
-	if (opResult != EOK) {
-		return opResult;
-	}
-	// set port power mode to no-power-switching
+	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;
-	instance->unfinished_interrupt_transfer = NULL;
-	instance->interrupt_mask_size = (instance->port_count + 8) / 8;
-	instance->interrupt_buffer = malloc(instance->interrupt_mask_size);
-	if (!instance->interrupt_buffer)
-		return ENOMEM;
+	/* 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);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process root hub request
- *
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-int rh_request(rh_t *instance, usb_transfer_batch_t *request) {
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * 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);
-	int opResult;
-	if (request->ep->transfer_type == USB_TRANSFER_CONTROL) {
+
+	switch (request->ep->transfer_type)
+	{
+	case USB_TRANSFER_CONTROL:
 		usb_log_debug("Root hub got CONTROL packet\n");
-		opResult = process_ctrl_request(instance, request);
-		usb_transfer_batch_finish_error(request, opResult);
-	} else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) {
+		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");
-		create_interrupt_mask_in_instance(instance);
-		if (is_zeros(instance->interrupt_buffer,
-		    instance->interrupt_mask_size)) {
+		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;
-			//will be finished later
-		} else {
-			usb_log_debug("Processing changes..\n");
-			process_interrupt_mask_in_instance(instance, request);
+			break;
 		}
-		opResult = EOK;
-	} else {
-
-		opResult = EINVAL;
-		usb_transfer_batch_finish_error(request, opResult);
-	}
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * process interrupt on a hub
+		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) {
-	if (!instance->unfinished_interrupt_transfer) {
+void rh_interrupt(rh_t *instance)
+{
+	assert(instance);
+
+	if (!instance->unfinished_interrupt_transfer)
 		return;
-	}
+
 	usb_log_debug("Finalizing interrupt transfer\n");
-	create_interrupt_mask_in_instance(instance);
-	process_interrupt_mask_in_instance(instance,
-	    instance->unfinished_interrupt_transfer);
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * Create hub descriptor used in hub-driver <-> hub communication
- *
- * This means creating byt array from data in root hub registers. For more
- * info see usb hub specification.
- *
+	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 error code
- */
-static int create_serialized_hub_descriptor(rh_t *instance) {
-	size_t size = 7 +
-	    ((instance->port_count + 7) / 8) * 2;
-	size_t var_size = (instance->port_count + 7) / 8;
-	uint8_t * result = (uint8_t*) malloc(size);
-	if (!result) return ENOMEM;
-
-	bzero(result, size);
-	//size
-	result[0] = size;
-	//descriptor type
-	result[1] = USB_DESCTYPE_HUB;
-	result[2] = instance->port_count;
-	uint32_t hub_desc_reg = instance->registers->rh_desc_a;
-	result[3] =
-	    ((hub_desc_reg >> 8) % 2) +
-	    (((hub_desc_reg >> 9) % 2) << 1) +
-	    (((hub_desc_reg >> 10) % 2) << 2) +
-	    (((hub_desc_reg >> 11) % 2) << 3) +
-	    (((hub_desc_reg >> 12) % 2) << 4);
-	result[4] = 0;
-	result[5] = /*descriptor->pwr_on_2_good_time*/ 50;
-	result[6] = 50;
-
-	size_t port;
-	for (port = 1; port <= instance->port_count; ++port) {
-		uint8_t is_non_removable =
-		    instance->registers->rh_desc_b >> port % 2;
-		result[7 + port / 8] +=
-		    is_non_removable << (port % 8);
-	}
-	size_t i;
-	for (i = 0; i < var_size; ++i) {
-		result[7 + var_size + i] = 255;
-	}
-	instance->hub_descriptor = result;
-	instance->descriptor_size = size;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/** initialize hub descriptors
- *
- * Initialized are device and full configuration descriptor. These need to
- * be initialized only once per hub.
- * @instance root hub instance
- * @return error code
- */
-static int rh_init_descriptors(rh_t *instance) {
-	memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor,
-	    sizeof (ohci_rh_device_descriptor)
-	    );
-	usb_standard_configuration_descriptor_t descriptor;
-	memcpy(&descriptor, &ohci_rh_conf_descriptor,
-	    sizeof (ohci_rh_conf_descriptor));
-
-	int opResult = create_serialized_hub_descriptor(instance);
-	if (opResult != EOK) {
-		return opResult;
-	}
-	descriptor.total_length =
-	    sizeof (usb_standard_configuration_descriptor_t) +
-	    sizeof (usb_standard_endpoint_descriptor_t) +
-	    sizeof (usb_standard_interface_descriptor_t) +
-	    instance->descriptor_size;
-
-	uint8_t * full_config_descriptor =
-	    (uint8_t*) malloc(descriptor.total_length);
-	if (!full_config_descriptor) {
-		return ENOMEM;
-	}
-	memcpy(full_config_descriptor, &descriptor, sizeof (descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor),
-	    &ohci_rh_iface_descriptor, sizeof (ohci_rh_iface_descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor) +
-	    sizeof (ohci_rh_iface_descriptor),
-	    &ohci_rh_ep_descriptor, sizeof (ohci_rh_ep_descriptor));
-	memcpy(full_config_descriptor + sizeof (descriptor) +
-	    sizeof (ohci_rh_iface_descriptor) +
-	    sizeof (ohci_rh_ep_descriptor),
-	    instance->hub_descriptor, instance->descriptor_size);
-
-	instance->descriptors.configuration = full_config_descriptor;
-	instance->descriptors.configuration_size = descriptor.total_length;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to port status_request
- *
- * Copy content of corresponding port status register to answer buffer. The
- * format of the port status register and port status data is the same (
- * see OHCI root hub and USB hub documentation).
- *
- * @param instance root hub instance
- * @param port port number, counted from 1
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_port_status_request(rh_t *instance, uint16_t port,
-    usb_transfer_batch_t * request) {
-	if (port < 1 || port > instance->port_count)
-		return EINVAL;
-	request->transfered_size = 4;
-	uint32_t data = instance->registers->rh_port_status[port - 1];
-	memcpy(request->data_buffer, &data, 4);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to port status_request
- *
- * This copies flags in hub status register into the buffer. The format of the
- * status register and status message is the same, according to USB hub
- * specification and OHCI root hub specification.
- *
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_hub_status_request(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	request->transfered_size = 4;
-	//bits, 0,1,16,17
-	uint32_t mask = 1 | (1 << 1) | (1 << 16) | (1 << 17);
-	uint32_t data = mask & instance->registers->rh_status;
-	memcpy(request->data_buffer, &data, 4);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to status request
+ * @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,
@@ -448,204 +372,119 @@
  * @return error code
  */
-static int process_get_status_request(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	size_t buffer_size = request->buffer_size;
-	usb_device_request_setup_packet_t * request_packet =
-	    (usb_device_request_setup_packet_t*)
-	    request->setup_buffer;
-
-	usb_hub_bm_request_type_t request_type = request_packet->request_type;
-	if (buffer_size < 4) {
-		usb_log_warning("Requested more data than buffer size\n");
-		return EINVAL;
-	}
-
-	if (request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)
-		return process_get_hub_status_request(instance, request);
-	if (request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)
-		return process_get_port_status_request(instance,
-	    request_packet->index,
-	    request);
+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 status interrupt consisting of change bitmap
- *
- * 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).
- * Uses instance`s interrupt buffer to store the interrupt information.
- * @param instance root hub instance
- */
-static void create_interrupt_mask_in_instance(rh_t * instance) {
-	uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer);
-	uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16))
-	    | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16));
-	bzero(bitmap, instance->interrupt_mask_size);
-	if ((instance->registers->rh_status & mask) != 0) {
-		bitmap[0] = 1;
-	}
-	size_t port;
-	mask = port_status_change_mask;
-	for (port = 1; port <= instance->port_count; ++port) {
-		if ((mask & instance->registers->rh_port_status[port - 1]) != 0) {
-
-			bitmap[(port) / 8] += 1 << (port % 8);
-		}
-	}
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * create answer to a descriptor request
+/**
+ * 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
- */
-static int process_get_descriptor_request(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
+ * @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 * result_descriptor = NULL;
+	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");
-			result_descriptor = instance->hub_descriptor;
-			size = instance->descriptor_size;
-			break;
-		}
-		case USB_DESCTYPE_DEVICE:
-		{
-			usb_log_debug2("USB_DESCTYPE_DEVICE\n");
-			result_descriptor = &ohci_rh_device_descriptor;
-			size = sizeof (ohci_rh_device_descriptor);
-			break;
-		}
-		case USB_DESCTYPE_CONFIGURATION:
-		{
-			usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n");
-			result_descriptor = instance->descriptors.configuration;
-			size = instance->descriptors.configuration_size;
-			break;
-		}
-		case USB_DESCTYPE_INTERFACE:
-		{
-			usb_log_debug2("USB_DESCTYPE_INTERFACE\n");
-			result_descriptor = &ohci_rh_iface_descriptor;
-			size = sizeof (ohci_rh_iface_descriptor);
-			break;
-		}
-		case USB_DESCTYPE_ENDPOINT:
-		{
-			usb_log_debug2("USB_DESCTYPE_ENDPOINT\n");
-			result_descriptor = &ohci_rh_ep_descriptor;
-			size = sizeof (ohci_rh_ep_descriptor);
-			break;
-		}
-		default:
-		{
-			usb_log_debug2("USB_DESCTYPE_EINVAL %d \n",
-			    setup_request->value);
-			usb_log_debug2("\ttype %d\n\trequest %d\n\tvalue "
-			    "%d\n\tindex %d\n\tlen %d\n ",
-			    setup_request->request_type,
-			    setup_request->request,
-			    setup_request_value,
-			    setup_request->index,
-			    setup_request->length
-			    );
-			return EINVAL;
-		}
+	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;
 	}
-	request->transfered_size = size;
-	memcpy(request->data_buffer, result_descriptor, size);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * answer to get configuration request
- *
- * Root hub works independently on the configuration.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_get_configuration_request(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	//set and get configuration requests do not have any meaning, only dummy
-	//values are returned
-	if (request->buffer_size != 1)
-		return EINVAL;
-	request->data_buffer[0] = 1;
-	request->transfered_size = 1;
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-enabling request on hub
- *
- * @param instance root hub instance
- * @param feature feature selector
- * @return error code
- */
-static int process_hub_feature_set_request(rh_t *instance,
-    uint16_t feature) {
-	if (!((1 << feature) & hub_set_feature_valid_mask))
-		return EINVAL;
-	if (feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
-		feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
-	instance->registers->rh_status =
-	    (instance->registers->rh_status | (1 << feature))
-	    & (~hub_clear_feature_by_writing_one_mask);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-disabling request on hub
- *
- * @param instance root hub instance
- * @param feature feature selector
- * @return error code
- */
-static int process_hub_feature_clear_request(rh_t *instance,
-    uint16_t feature) {
-	if (!((1 << feature) & hub_clear_feature_valid_mask))
-		return EINVAL;
-	//is the feature cleared directly?
-	if ((1 << feature) & hub_set_feature_direct_mask) {
-		instance->registers->rh_status =
-		    (instance->registers->rh_status & (~(1 << feature)))
-		    & (~hub_clear_feature_by_writing_one_mask);
-	} else {//the feature is cleared by writing '1'
-
-		instance->registers->rh_status =
-		    (instance->registers->rh_status
-		    & (~hub_clear_feature_by_writing_one_mask))
-		    | (1 << feature);
-	}
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
+
+	memcpy(request->data_buffer, descriptor, size);
+	TRANSFER_OK(size);
+}
+/*----------------------------------------------------------------------------*/
 /**
  * process feature-enabling request on hub
@@ -657,19 +496,36 @@
  * @return error code
  */
-static int process_port_feature_set_request(rh_t *instance,
-    uint16_t feature, uint16_t port) {
-	if (!((1 << feature) & port_set_feature_valid_mask))
-		return EINVAL;
+int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
+{
+	assert(instance);
+
 	if (port < 1 || port > instance->port_count)
 		return EINVAL;
-	instance->registers->rh_port_status[port - 1] =
-	    (instance->registers->rh_port_status[port - 1] | (1 << feature))
-	    & (~port_clear_feature_valid_mask);
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process feature-disabling request on hub
+
+	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
@@ -679,93 +535,52 @@
  * @return error code
  */
-static int process_port_feature_clear_request(rh_t *instance,
-    uint16_t feature, uint16_t port) {
-	if (!((1 << feature) & port_clear_feature_valid_mask))
-		return EINVAL;
+int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
+{
+	assert(instance);
+
 	if (port < 1 || port > instance->port_count)
 		return EINVAL;
-	if (feature == USB_HUB_FEATURE_PORT_POWER)
-		feature = USB_HUB_FEATURE_PORT_LOW_SPEED;
-	if (feature == USB_HUB_FEATURE_PORT_SUSPEND)
-		feature = USB_HUB_FEATURE_PORT_OVER_CURRENT;
-	instance->registers->rh_port_status[port - 1] =
-	    (instance->registers->rh_port_status[port - 1]
-	    & (~port_clear_feature_valid_mask))
-	    | (1 << feature);
-
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * register address to this device
- *
- * @param instance root hub instance
- * @param address new address
- * @return error code
- */
-static int process_address_set_request(rh_t *instance,
-    uint16_t address) {
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process one of requests that requere output data
- *
- * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or
- * USB_DEVREQ_GET_CONFIGURATION.
- * @param instance root hub instance
- * @param request structure containing both request and response information
- * @return error code
- */
-static int process_request_with_output(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	if (setup_request->request == USB_DEVREQ_GET_STATUS) {
-		usb_log_debug("USB_DEVREQ_GET_STATUS\n");
-		return process_get_status_request(instance, request);
-	}
-	if (setup_request->request == USB_DEVREQ_GET_DESCRIPTOR) {
-		usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");
-		return process_get_descriptor_request(instance, request);
-	}
-	if (setup_request->request == USB_DEVREQ_GET_CONFIGURATION) {
-		usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");
-
-		return process_get_configuration_request(instance, request);
-	}
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process one of requests that carry input data
- *
- * Request can be one of 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
- */
-static int process_request_with_input(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	request->transfered_size = 0;
-	if (setup_request->request == USB_DEVREQ_SET_DESCRIPTOR) {
+
+	/* 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;
 	}
-	if (setup_request->request == USB_DEVREQ_SET_CONFIGURATION) {
-		//set and get configuration requests do not have any meaning,
-		//only dummy values are returned
-
-		return EOK;
-	}
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
+}
+/*----------------------------------------------------------------------------*/
 /**
  * process one of requests that do not request nor carry additional data
@@ -777,55 +592,76 @@
  * @return error code
  */
-static int process_request_without_data(rh_t *instance,
-    usb_transfer_batch_t *request) {
-	usb_device_request_setup_packet_t * setup_request =
-	    (usb_device_request_setup_packet_t*) request->setup_buffer;
-	request->transfered_size = 0;
-	if (setup_request->request == USB_DEVREQ_CLEAR_FEATURE) {
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
-			return process_hub_feature_clear_request(instance,
-			    setup_request->value);
-		}
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
-			usb_log_debug2("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-			return process_port_feature_clear_request(instance,
-			    setup_request->value,
-			    setup_request->index);
-		}
-		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
+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;
 	}
-	if (setup_request->request == USB_DEVREQ_SET_FEATURE) {
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");
-			return process_hub_feature_set_request(instance,
-			    setup_request->value);
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * 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);
 		}
-		if (setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE) {
-			usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");
-			return process_port_feature_set_request(instance,
-			    setup_request->value,
-			    setup_request->index);
-		}
-		usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",
+	default:
+		usb_log_error("Invalid clear feature request type: %d\n",
 		    setup_request->request_type);
 		return EINVAL;
 	}
-	if (setup_request->request == USB_DEVREQ_SET_ADDRESS) {
-		usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");
-		return process_address_set_request(instance,
-		    setup_request->value);
-	}
-	usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",
-	    setup_request->request_type);
-
-	return ENOTSUP;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process hub control request
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process hub control request.
  *
  * If needed, writes answer into the request structure.
@@ -844,95 +680,65 @@
  * @return error code
  */
-static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request) {
+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?");
+		usb_log_error("Root hub received empty transaction!");
 		return EINVAL;
 	}
-	int opResult;
-	if (sizeof (usb_device_request_setup_packet_t) > request->setup_size) {
+
+	if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) {
 		usb_log_error("Setup packet too small\n");
-		return EINVAL;
-	}
-	usb_log_debug("CTRL packet: %s.\n",
-	    usb_debug_str_buffer(
-	    (const uint8_t *) request->setup_buffer, 8, 8));
-	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:
-		case USB_DEVREQ_GET_DESCRIPTOR:
-		case USB_DEVREQ_GET_CONFIGURATION:
-			usb_log_debug2("Processing request with output\n");
-			opResult = process_request_with_output(
-			    instance, request);
-			break;
-		case USB_DEVREQ_CLEAR_FEATURE:
-		case USB_DEVREQ_SET_FEATURE:
-		case USB_DEVREQ_SET_ADDRESS:
-			usb_log_debug2("Processing request without "
-			    "additional data\n");
-			opResult = process_request_without_data(
-			    instance, request);
-			break;
-		case USB_DEVREQ_SET_DESCRIPTOR:
-		case USB_DEVREQ_SET_CONFIGURATION:
-			usb_log_debug2("Processing request with input\n");
-			opResult = process_request_with_input(
-			    instance, request);
-
-			break;
-		default:
-			usb_log_warning("Received unsupported request: %d.\n",
-			    setup_request->request);
-			opResult = ENOTSUP;
-	}
-	return opResult;
-}
-/*----------------------------------------------------------------------------*/
-
-/**
- * process hanging interrupt request
- *
- * If an interrupt transfer has been received and there was no change,
- * the driver stores the transfer information and waits for change to occcur.
- * This routine is called when that happens and it finalizes the interrupt
- * transfer.
- *
- * @param instance hub instance
- * @param request batch request to be processed
- *
- * @return
- */
-static int process_interrupt_mask_in_instance(rh_t *instance,
-    usb_transfer_batch_t * request) {
-	memcpy(request->data_buffer, instance->interrupt_buffer,
-	    instance->interrupt_mask_size);
-	request->transfered_size = instance->interrupt_mask_size;
-	instance->unfinished_interrupt_transfer = NULL;
-	usb_transfer_batch_finish_error(request, EOK);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/**
- * return whether the buffer is full of zeros
- *
- * Convenience function.
- * @param buffer
- * @param size
- * @return
- */
-static bool is_zeros(void *buffer, size_t size) {
-	if (!buffer) return true;
-	if (!size) return true;
-	size_t i;
-	for (i = 0; i < size; ++i) {
-		if (((char*) buffer)[i])
-			return false;
-	}
-	return true;
+		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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/ohci/root_hub.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -41,4 +41,6 @@
 #include "batch.h"
 
+#define HUB_DESCRIPTOR_MAX_SIZE (7 + 2 + 2)
+
 /**
  * ohci root hub representation
@@ -51,28 +53,23 @@
 	/** hub port count */
 	size_t port_count;
-	/** hubs descriptors */
-	usb_device_descriptors_t descriptors;
 	/** interrupt transfer waiting for an actual interrupt to occur */
-	usb_transfer_batch_t * unfinished_interrupt_transfer;
-	/** pre-allocated interrupt mask
-	 *
-	 * This is allocated when initializing instance, so that memory
-	 * allocation is not needed when processing request. Buffer is used for
-	 * interrupt bitmask.
-	 */
-	uint8_t * interrupt_buffer;
+	usb_transfer_batch_t *unfinished_interrupt_transfer;
 	/** size of interrupt buffer */
 	size_t interrupt_mask_size;
-	/** instance`s descriptor*/
-	uint8_t * hub_descriptor;
+	/** 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 descriptor_size;
-
+	size_t hub_descriptor_size;
 
 } rh_t;
 
-int rh_init(rh_t *instance, ohci_regs_t *regs);
+void rh_init(rh_t *instance, ohci_regs_t *regs);
 
-int rh_request(rh_t *instance, usb_transfer_batch_t *request);
+void rh_request(rh_t *instance, usb_transfer_batch_t *request);
 
 void rh_interrupt(rh_t *instance);
Index: uspace/drv/bus/usb/uhci/hc.c
===================================================================
--- uspace/drv/bus/usb/uhci/hc.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/uhci/hc.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -47,4 +47,13 @@
     (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);
@@ -54,4 +63,37 @@
 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
@@ -69,5 +111,5 @@
 int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
 {
-	assert(reg_size >= sizeof(regs_t));
+	assert(reg_size >= sizeof(uhci_regs_t));
 	int ret;
 
@@ -82,17 +124,16 @@
 
 	/* allow access to hc control registers */
-	regs_t *io;
+	uhci_regs_t *io;
 	ret = pio_enable(regs, reg_size, (void **)&io);
-	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to gain access to registers at %p: %s.\n",
-	    ret, io, str_error(ret));
+	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);
+	usb_log_debug(
+	    "Device registers at %p (%zuB) accessible.\n", io, reg_size);
 
 	ret = hc_init_mem_structures(instance);
 	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to initialize UHCI memory structures: %s.\n",
-	    ret, str_error(ret));
+	    "Failed to initialize UHCI memory structures: %s.\n",
+	    str_error(ret));
 
 	hc_init_hw(instance);
@@ -116,12 +157,12 @@
 {
 	assert(instance);
-	regs_t *registers = instance->registers;
+	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(10000); /* 10ms according to USB spec */
+	async_usleep(50000); /* 50ms according to USB spec(root hub reset) */
 	pio_write_16(&registers->usbcmd, 0);
 
-	/* Reset hc, all states and counters */
+	/* Reset hc, all states and counters. Hope that hw is not broken */
 	pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
 	do { async_usleep(10); }
@@ -141,7 +182,7 @@
 	}
 
-	const uint16_t status = pio_read_16(&registers->usbcmd);
-	if (status != 0)
-		usb_log_warning("Previous command value: %x.\n", status);
+	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 */
@@ -170,60 +211,12 @@
 	} else (void) 0
 
-	/* Init interrupt code */
-	instance->interrupt_code.cmds = instance->interrupt_commands;
-	{
-		/* Read status register */
-		instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;
-		instance->interrupt_commands[0].dstarg = 1;
-		instance->interrupt_commands[0].addr =
-		    &instance->registers->usbsts;
-
-		/* Test whether we are the interrupt cause */
-		instance->interrupt_commands[1].cmd = CMD_BTEST;
-		instance->interrupt_commands[1].value =
-		    UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;
-		instance->interrupt_commands[1].srcarg = 1;
-		instance->interrupt_commands[1].dstarg = 2;
-
-		/* Predicate cleaning and accepting */
-		instance->interrupt_commands[2].cmd = CMD_PREDICATE;
-		instance->interrupt_commands[2].value = 2;
-		instance->interrupt_commands[2].srcarg = 2;
-
-		/* Write clean status register */
-		instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;
-		instance->interrupt_commands[3].srcarg = 1;
-		instance->interrupt_commands[3].addr =
-		    &instance->registers->usbsts;
-
-		/* Accept interrupt */
-		instance->interrupt_commands[4].cmd = CMD_ACCEPT;
-
-		instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;
-	}
-
 	/* Init transfer lists */
 	int ret = hc_init_transfer_lists(instance);
-	CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
+	CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
 	usb_log_debug("Initialized transfer lists.\n");
-
-	/* Init USB frame list page*/
-	instance->frame_list = get_page();
-	ret = instance->frame_list ? EOK : ENOMEM;
-	CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
-	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;
-	}
 
 	/* Init device keeper */
 	usb_device_keeper_init(&instance->manager);
-	usb_log_debug("Initialized device manager.\n");
+	usb_log_debug("Initialized device keeper.\n");
 
 	ret = usb_endpoint_manager_init(&instance->ep_manager,
@@ -232,4 +225,21 @@
 	    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
@@ -252,6 +262,6 @@
 	int ret = transfer_list_init(&instance->transfers_##type, name); \
 	if (ret != EOK) { \
-		usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
-		    ret, name, str_error(ret)); \
+		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); \
Index: uspace/drv/bus/usb/uhci/hc.h
===================================================================
--- uspace/drv/bus/usb/uhci/hc.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/uhci/hc.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -84,5 +84,5 @@
 	/** SOF modification to match external timers */
 	uint8_t sofmod;
-} regs_t;
+} uhci_regs_t;
 
 #define UHCI_FRAME_LIST_COUNT 1024
@@ -100,5 +100,5 @@
 
 	/** Addresses of I/O registers */
-	regs_t *registers;
+	uhci_regs_t *registers;
 
 	/** Frame List contains 1024 link pointers */
@@ -116,14 +116,6 @@
 	/** Pointer table to the above lists, helps during scheduling */
 	transfer_list_t *transfers[2][4];
-
-	/** Code to be executed in kernel interrupt handler */
-	irq_code_t interrupt_code;
-
-	/** Commands that form interrupt code */
-	irq_cmd_t interrupt_commands[UHCI_NEEDED_IRQ_COMMANDS];
-
 	/** Fibril periodically checking status register*/
 	fid_t interrupt_emulator;
-
 	/** Indicator of hw interrupts availability */
 	bool hw_interrupts;
@@ -132,9 +124,9 @@
 	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);
 
Index: uspace/drv/bus/usb/uhci/root_hub.c
===================================================================
--- uspace/drv/bus/usb/uhci/root_hub.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/uhci/root_hub.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -50,21 +50,12 @@
 int rh_init(rh_t *instance, ddf_fun_t *fun, uintptr_t reg_addr, size_t reg_size)
 {
+	int ret;
+
 	assert(fun);
 
-	char *match_str = NULL;
-	int ret = asprintf(&match_str, "usb&uhci&root-hub");
-	if (ret < 0) {
-		usb_log_error(
-		    "Failed(%d) to create root hub match string: %s.\n",
-		    ret, str_error(ret));
-		return ret;
-	}
-	assert(match_str);
-
-	ret = ddf_fun_add_match_id(fun, match_str, 100);
+	ret = ddf_fun_add_match_id(fun, "usb&uhci&root-hub", 100);
 	if (ret != EOK) {
-		free(match_str);
-		usb_log_error("Failed(%d) to add root hub match id: %s\n",
-		    ret, str_error(ret));
+		usb_log_error("Failed to add root hub match id: %s\n",
+		    str_error(ret));
 		return ret;
 	}
Index: uspace/drv/bus/usb/uhci/transfer_list.c
===================================================================
--- uspace/drv/bus/usb/uhci/transfer_list.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/uhci/transfer_list.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -141,5 +141,5 @@
 	list_append(&batch->link, &instance->batch_list);
 
-	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
+	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);
Index: uspace/drv/bus/usb/uhci/uhci.c
===================================================================
--- uspace/drv/bus/usb/uhci/uhci.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/uhci/uhci.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -64,5 +64,4 @@
 {
 	assert(dev);
-	assert(dev->driver_data);
 	return dev->driver_data;
 }
@@ -78,8 +77,10 @@
 	assert(dev);
 	uhci_t *uhci = dev_to_uhci(dev);
-	hc_t *hc = &uhci->hc;
+	if (!uhci) {
+		usb_log_error("Interrupt on not yet initialized device.\n");
+		return;
+	}
 	const uint16_t status = IPC_GET_ARG1(*call);
-	assert(hc);
-	hc_interrupt(hc, status);
+	hc_interrupt(&uhci->hc, status);
 }
 /*----------------------------------------------------------------------------*/
@@ -192,4 +193,5 @@
 	} \
 	free(instance); \
+	device->driver_data = NULL; \
 	usb_log_error(message); \
 	return ret; \
@@ -222,27 +224,35 @@
 	ret = pci_disable_legacy(device);
 	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(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;
-#ifdef CONFIG_USBHC_NO_INTERRUPTS
-	usb_log_warning("Interrupts disabled in OS config, " \
-	    "falling back to polling.\n");
-#else
 	ret = pci_enable_interrupts(device);
 	if (ret != EOK) {
-		usb_log_warning("Failed to enable interrupts: %s.\n",
-		    str_error(ret));
-		usb_log_info("HW interrupts not available, " \
-		    "falling back to polling.\n");
+		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;
 	}
-#endif
-
 
 	ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
 	CHECK_RET_DEST_FREE_RETURN(ret,
-	    "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret));
+	    "Failed to init uhci_hcd: %s.\n", str_error(ret));
+
+	device->driver_data = instance;
 
 #define CHECK_RET_FINI_RETURN(ret, message...) \
@@ -253,15 +263,7 @@
 } else (void)0
 
-	/* It does no harm if we register this on polling */
-	ret = register_interrupt_handler(device, irq, irq_handler,
-	    &instance->hc.interrupt_code);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to register interrupt handler: %s.\n",
-	    ret, str_error(ret));
-
 	ret = ddf_fun_bind(instance->hc_fun);
-	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to bind UHCI device function: %s.\n",
-	    ret, str_error(ret));
+	CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n",
+	    str_error(ret));
 
 	ret = ddf_fun_add_to_class(instance->hc_fun, USB_HC_DDF_CLASS_NAME);
@@ -272,11 +274,10 @@
 	    (uintptr_t)instance->hc.registers + 0x10, 4);
 	CHECK_RET_FINI_RETURN(ret,
-	    "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(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(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
-
-	device->driver_data = instance;
+	    "Failed to register UHCI root hub: %s.\n", str_error(ret));
+
 	return EOK;
 #undef CHECK_RET_FINI_RETURN
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -220,9 +220,9 @@
  * @return error code
  */
-static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info) {
+int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
+{
 	// get hub descriptor
-	usb_log_debug("Creating serialized descriptor\n");
+	usb_log_debug("Retrieving descriptor\n");
 	uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
-	usb_hub_descriptor_t * descriptor;
 	int opResult;
 
@@ -234,47 +234,53 @@
 
 	if (opResult != EOK) {
-		usb_log_error("Failed when receiving hub descriptor, "
-		    "%s\n",
-		    str_error(opResult));
-		free(serialized_descriptor);
+		usb_log_error("Failed to receive hub descriptor: %s.\n",
+		    str_error(opResult));
 		return opResult;
 	}
-	usb_log_debug2("Deserializing descriptor\n");
-	descriptor = usb_create_deserialized_hub_desriptor(
-	    serialized_descriptor);
-	if (descriptor == NULL) {
-		usb_log_warning("could not deserialize descriptor \n");
-		return ENOMEM;
-	}
-	usb_log_debug("setting port count to %d\n", descriptor->ports_count);
-	hub_info->port_count = descriptor->ports_count;
-	bool is_power_switched =
-	    ((descriptor->hub_characteristics & 1) == 0);
-	bool has_individual_port_powering =
-	    ((descriptor->hub_characteristics & 1) != 0);
-	hub_info->ports = malloc(
-	    sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
+	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");
-
-		if (!has_individual_port_powering) {
-			//this setting actually makes no difference
-			usb_log_debug("Hub has global powering\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,
+			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;
+				}
 			}
 		}
@@ -283,6 +289,4 @@
 		usb_log_debug("Power not switched, not going to be powered\n");
 	}
-	usb_log_debug2("Freeing data\n");
-	free(descriptor);
 	return EOK;
 }
Index: uspace/drv/bus/usb/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -171,9 +171,6 @@
     void * serialized_descriptor);
 
-usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
-    void * serialized_descriptor);
-
-void usb_deserialize_hub_desriptor(void * serialized_descriptor,
-    usb_hub_descriptor_t * descriptor);
+int usb_deserialize_hub_desriptor(
+    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor);
 
 
Index: uspace/drv/bus/usb/usbhub/utils.c
===================================================================
--- uspace/drv/bus/usb/usbhub/utils.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/usbhub/utils.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -110,53 +110,45 @@
 }
 
+/*----------------------------------------------------------------------------*/
 /**
- * create deserialized desriptor structure out of serialized descriptor
+ * Deserialize descriptor into given pointer
  *
- * The serialized descriptor must be proper usb hub descriptor,
- * otherwise an eerror might occur.
- *
- * @param sdescriptor serialized descriptor
- * @return newly created deserialized descriptor pointer
- */
-usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
-    void *serialized_descriptor) {
-	uint8_t * sdescriptor = serialized_descriptor;
-
-	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
-		usb_log_warning("trying to deserialize wrong descriptor %x\n",
-		    sdescriptor[1]);
-		return NULL;
-	}
-
-	usb_hub_descriptor_t * result = malloc(sizeof (usb_hub_descriptor_t));
-	if (result)
-		usb_deserialize_hub_desriptor(serialized_descriptor, result);
-	return result;
-}
-
-/**
- * deserialize descriptor into given pointer
- * 
  * @param serialized_descriptor
  * @param descriptor
  * @return
  */
-void usb_deserialize_hub_desriptor(
-    void * serialized_descriptor, usb_hub_descriptor_t *descriptor) {
+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];
-	/// @fixme handling of endianness??
-	descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
+	descriptor->hub_characteristics = sdescriptor[3] + 256 * sdescriptor[4];
 	descriptor->pwr_on_2_good_time = sdescriptor[5];
 	descriptor->current_requirement = sdescriptor[6];
-	size_t var_size = (descriptor->ports_count + 7) / 8;
+	const size_t var_size = (descriptor->ports_count + 7) / 8;
 	//descriptor->devices_removable = (uint8_t*) malloc(var_size);
 
-	size_t i;
-	for (i = 0; i < var_size; ++i) {
+	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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/usbmast/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -32,17 +32,20 @@
 	$(LIBUSBDEV_PREFIX)/libusbdev.a \
 	$(LIBUSB_PREFIX)/libusb.a \
-	$(LIBDRV_PREFIX)/libdrv.a
+	$(LIBDRV_PREFIX)/libdrv.a \
+	$(LIBSCSI_PREFIX)/libscsi.a
 
 EXTRA_CFLAGS += \
 	-I$(LIBUSB_PREFIX)/include \
 	-I$(LIBUSBDEV_PREFIX)/include \
-	-I$(LIBDRV_PREFIX)/include
+	-I$(LIBDRV_PREFIX)/include \
+	-I$(LIBSCSI_PREFIX)/include
 
 BINARY = usbmast
 
 SOURCES = \
-	inquiry.c \
+	bo_trans.c \
+	cmdw.c \
 	main.c \
-	mast.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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/drv/bus/usb/usbmast/bo_trans.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/drv/bus/usb/usbmast/bo_trans.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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: pace/drv/bus/usb/usbmast/cmds.h
===================================================================
--- uspace/drv/bus/usb/usbmast/cmds.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * 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 USB_USBMAST_CMDS_H_
-#define USB_USBMAST_CMDS_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;
-
-static inline 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, 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);
-}
-
-#endif
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbmast/cmdw.c
===================================================================
--- uspace/drv/bus/usb/usbmast/cmdw.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/drv/bus/usb/usbmast/cmdw.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/drv/bus/usb/usbmast/cmdw.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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: pace/drv/bus/usb/usbmast/inquiry.c
===================================================================
--- uspace/drv/bus/usb/usbmast/inquiry.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,193 +1,0 @@
-/*
- * 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
- * Main routines of USB mass storage driver.
- */
-#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 <str.h>
-#include <ctype.h>
-#include "cmds.h"
-#include "scsi.h"
-#include "mast.h"
-
-#define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
-#define BITS_GET_MID_MASK(type, bitcount, offset) \
-	((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
-#define BITS_GET(type, number, bitcount, offset) \
-	((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
-
-#define INQUIRY_RESPONSE_LENGTH 36
-
-#define STR_UNKNOWN "<unknown>"
-
-/** String constants for SCSI peripheral device types. */
-static const char *str_peripheral_device_types[] = {
-	"direct-access device",
-	"sequential-access device",
-	"printer device",
-	"processor device",
-	"write-once device",
-	"CDROM device",
-	"scanner device",
-	"optical memory device",
-	"medium changer",
-	"communications device",
-	"graphic arts pre-press device",
-	"graphic arts pre-press device",
-	"storage array controller device",
-	"enclosure services device",
-	"simplified direct-access device",
-	"optical card reader/writer device",
-	"bridging expander",
-	"object-based storage device",
-	"automation driver interface",
-	STR_UNKNOWN, // 0x13
-	STR_UNKNOWN, // 0x14
-	STR_UNKNOWN, // 0x15
-	STR_UNKNOWN, // 0x16
-	STR_UNKNOWN, // 0x17
-	STR_UNKNOWN, // 0x18
-	STR_UNKNOWN, // 0x19
-	STR_UNKNOWN, // 0x1A
-	STR_UNKNOWN, // 0x1B
-	STR_UNKNOWN, // 0x1C
-	STR_UNKNOWN, // 0x1D
-	"well-known logical unit",
-	"uknown or no device state"
-};
-#define str_peripheral_device_types_count \
-	(sizeof(str_peripheral_device_types)/sizeof(str_peripheral_device_types[0]))
-
-/** Get string representation for SCSI peripheral device type.
- *
- * See for example here for a list
- * http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type.
- *
- * @param type SCSI peripheral device type code.
- * @return String representation.
- */
-const char *usb_str_masstor_scsi_peripheral_device_type(int type)
-{
-	if ((type < 0)
-	    || ((size_t)type >= str_peripheral_device_types_count)) {
-		return STR_UNKNOWN;
-	}
-	return str_peripheral_device_types[type];
-}
-
-/** Trim trailing spaces from a string (rewrite with string terminator).
- *
- * @param name String to be trimmed (in-out parameter).
- */
-static void trim_trailing_spaces(char *name)
-{
-	size_t len = str_length(name);
-	while ((len > 0) && isspace((int) name[len - 1])) {
-		name[len - 1] = 0;
-		len--;
-	}
-}
-
-/** Perform SCSI INQUIRY command on USB mass storage device.
- *
- * @param dev USB device.
- * @param bulk_in_idx Index (in dev->pipes) of bulk in pipe.
- * @param bulk_out_idx Index of bulk out pipe.
- * @param inquiry_result Where to store parsed inquiry result.
- * @return Error code.
- */
-int usb_massstor_inquiry(usb_device_t *dev,
-    size_t bulk_in_idx, size_t bulk_out_idx,
-    usb_massstor_inquiry_result_t *inquiry_result)
-{
-	scsi_cmd_inquiry_t inquiry = {
-		.op_code = 0x12,
-		.lun_evpd = 0,
-		.page_code = 0,
-		.alloc_length = host2uint16_t_be(INQUIRY_RESPONSE_LENGTH),
-		.ctrl = 0
-	};
-	size_t response_len;
-	uint8_t response[INQUIRY_RESPONSE_LENGTH];
-
-	int rc;
-
-	rc = usb_massstor_data_in(dev, bulk_in_idx, bulk_out_idx,
-	    0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
-	    response, INQUIRY_RESPONSE_LENGTH, &response_len);
-
-	if (rc != EOK) {
-		usb_log_error("Failed to probe device %s using %s: %s.\n",
-		   dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
-		return rc;
-	}
-
-	if (response_len < 8) {
-		usb_log_error("The SCSI response is too short.\n");
-		return ERANGE;
-	}
-
-	/*
-	 * This is an ugly part of the code. We will parse the returned
-	 * data by hand and try to get as many useful data as possible.
-	 */
-	bzero(inquiry_result, sizeof(*inquiry_result));
-
-	/* This shall be returned by all devices. */
-	inquiry_result->peripheral_device_type
-	    = BITS_GET(uint8_t, response[0], 5, 0);
-	inquiry_result->removable = BITS_GET(uint8_t, response[1], 1, 7);
-
-	if (response_len < 32) {
-		return EOK;
-	}
-
-	str_ncpy(inquiry_result->vendor_id, 9,
-	    (const char *) &response[8], 8);
-	trim_trailing_spaces(inquiry_result->vendor_id);
-
-	str_ncpy(inquiry_result->product_and_revision, 12,
-	    (const char *) &response[16], 11);
-	trim_trailing_spaces(inquiry_result->product_and_revision);
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,4 +35,8 @@
  * 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>
@@ -40,12 +45,10 @@
 #include <errno.h>
 #include <str_error.h>
-#include "cmds.h"
-#include "scsi.h"
-#include "mast.h"
+#include "cmdw.h"
+#include "bo_trans.h"
+#include "scsi_ms.h"
+#include "usbmast.h"
 
 #define NAME "usbmast"
-
-#define BULK_IN_EP 0
-#define BULK_OUT_EP 1
 
 #define GET_BULK_IN(dev) ((dev)->pipes[BULK_IN_EP].pipe)
@@ -75,4 +78,8 @@
 };
 
+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.
  *
@@ -83,20 +90,19 @@
 {
 	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 mass storage `%s'.\n",
+	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",
@@ -107,23 +113,189 @@
 	    (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
 
-	size_t lun_count = usb_masstor_get_lun_count(dev);
-
-	usb_massstor_inquiry_result_t inquiry;
-	rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry);
+	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 inquiry device `%s': %s.\n",
-		    dev->ddf_dev->name, str_error(rc));
-		return EOK;
-	}
-
-	usb_log_info("Mass storage `%s': " \
-	    "`%s' by `%s' is %s (%s), %zu LUN(s).\n",
-	    dev->ddf_dev->name,
-	    inquiry.product_and_revision, inquiry.vendor_id,
-	    usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type),
-	    inquiry.removable ? "removable" : "non-removable",
-	    lun_count);
+		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);
+		}
+	}
 }
 
Index: pace/drv/bus/usb/usbmast/mast.c
===================================================================
--- uspace/drv/bus/usb/usbmast/mast.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,222 +1,0 @@
-/*
- * 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
- * Generic functions for USB mass storage (implementation).
- */
-#include "mast.h"
-#include "cmds.h"
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <usb/debug.h>
-#include <usb/dev/request.h>
-
-bool usb_mast_verbose = true;
-
-#define MASTLOG(format, ...) \
-	do { \
-		if (usb_mast_verbose) { \
-			usb_log_debug("USB cl08: " format, ##__VA_ARGS__); \
-		} \
-	} while (false)
-
-/** Request data from mass storage device.
- *
- * @param bulk_in_pipe Bulk in pipe to the device.
- * @param bulk_out_pipe Bulk out pipe to the device.
- * @param tag Command block wrapper tag (automatically compared with answer).
- * @param lun LUN index.
- * @param cmd SCSI command buffer (in SCSI endianness).
- * @param cmd_size Length of SCSI command @p cmd in bytes.
- * @param in_buffer Buffer where to store the answer (CSW is not returned).
- * @param in_buffer_size Size of the buffer (size of the request to the device).
- * @param received_size Number of actually received bytes.
- * @return Error code.
- */
-int usb_massstor_data_in(usb_device_t *dev,
-    size_t bulk_in_pipe_index, size_t bulk_out_pipe_index,
-    uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
-    void *in_buffer, size_t in_buffer_size, size_t *received_size)
-{
-	int rc;
-	size_t act_size;
-	usb_pipe_t *bulk_in_pipe = dev->pipes[bulk_in_pipe_index].pipe;
-	usb_pipe_t *bulk_out_pipe = dev->pipes[bulk_out_pipe_index].pipe;
-
-	/* Prepare CBW - command block wrapper */
-	usb_massstor_cbw_t cbw;
-	usb_massstor_cbw_prepare(&cbw, tag, in_buffer_size,
-	    USB_DIRECTION_IN, lun, cmd_size, cmd);
-
-	/* First, send the CBW. */
-	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 rc;
-	}
-
-	/* Try to retrieve the data from the device. */
-	act_size = 0;
-	rc = usb_pipe_read(bulk_in_pipe, in_buffer, in_buffer_size, &act_size);
-	MASTLOG("Received %zuB (%s): %s.\n", act_size,
-	    usb_debug_str_buffer((uint8_t *) in_buffer, act_size, 0),
-	    str_error(rc));
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Read CSW. */
-	usb_massstor_csw_t csw;
-	size_t csw_size;
-	rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
-	MASTLOG("CSW '%s' received (%zuB): %s.\n",
-	    usb_debug_str_buffer((uint8_t *) &csw, csw_size, 0), csw_size,
-	    str_error(rc));
-	if (rc != EOK) {
-		return rc;
-	}
-	if (csw_size != sizeof(csw)) {
-		return ERANGE;
-	}
-
-	if (csw.dCSWTag != tag) {
-		return EBADCHECKSUM;
-	}
-
-	/*
-	 * Determine the actual return value from the CSW.
-	 */
-	if (csw.dCSWStatus != 0) {
-		// FIXME: better error code
-		// FIXME: distinguish 0x01 and 0x02
-		return EXDEV;
-	}
-
-	size_t residue = (size_t) uint32_usb2host(csw.dCSWDataResidue);
-	if (residue > in_buffer_size) {
-		return ERANGE;
-	}
-	if (act_size != in_buffer_size - residue) {
-		return ERANGE;
-	}
-	if (received_size != NULL) {
-		*received_size = in_buffer_size - residue;
-	}
-
-	return EOK;
-}
-
-/** Perform bulk-only mass storage reset.
- *
- * @param dev Device to be reseted.
- * @return Error code.
- */
-int usb_massstor_reset(usb_device_t *dev)
-{
-	return usb_control_request_set(&dev->ctrl_pipe,
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
-	    0xFF, 0, 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 dev Device to be reseted.
- * @param bulk_in_idx Index of bulk in pipe.
- * @param bulk_out_idx Index of bulk out pipe.
- */
-void usb_massstor_reset_recovery(usb_device_t *dev,
-    size_t bulk_in_idx, size_t bulk_out_idx)
-{
-	/* We would ignore errors here because if this fails
-	 * we are doomed anyway and any following transaction would fail.
-	 */
-	usb_massstor_reset(dev);
-	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_in_idx].pipe);
-	usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_out_idx].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 dev Mass storage device.
- * @return Error code of maximum LUN (index, not count).
- */
-int usb_massstor_get_max_lun(usb_device_t *dev)
-{
-	uint8_t max_lun;
-	size_t data_recv_len;
-	int rc = usb_control_request_get(&dev->ctrl_pipe,
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
-	    0xFE, 0, 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 dev Mass storage device.
- * @return Number of LUNs.
- */
-size_t usb_masstor_get_lun_count(usb_device_t *dev)
-{
-	int max_lun = usb_massstor_get_max_lun(dev);
-	if (max_lun < 0) {
-		max_lun = 1;
-	} else {
-		max_lun++;
-	}
-
-	return (size_t) max_lun;
-}
-
-/**
- * @}
- */
Index: pace/drv/bus/usb/usbmast/mast.h
===================================================================
--- uspace/drv/bus/usb/usbmast/mast.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * 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
- * Generic functions for USB mass storage.
- */
-
-#ifndef USB_USBMAST_MAST_H_
-#define USB_USBMAST_MAST_H_
-
-#include <sys/types.h>
-#include <usb/usb.h>
-#include <usb/dev/pipes.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. */
-	int peripheral_device_type;
-	/** Whether the device is removable. */
-	bool removable;
-	/** Vendor ID string. */
-	char vendor_id[9];
-	/** Product ID and product revision string. */
-	char product_and_revision[12];
-} usb_massstor_inquiry_result_t;
-
-int usb_massstor_data_in(usb_device_t *dev, size_t, size_t,
-    uint32_t, uint8_t, void *, size_t, void *, size_t, size_t *);
-int usb_massstor_reset(usb_device_t *);
-void usb_massstor_reset_recovery(usb_device_t *, size_t, size_t);
-int usb_massstor_get_max_lun(usb_device_t *);
-size_t usb_masstor_get_lun_count(usb_device_t *);
-int usb_massstor_inquiry(usb_device_t *, size_t, size_t,
-    usb_massstor_inquiry_result_t *);
-const char *usb_str_masstor_scsi_peripheral_device_type(int);
-
-#endif
-
-/**
- * @}
- */
Index: pace/drv/bus/usb/usbmast/scsi.h
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * 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 related structures.
- */
-
-#ifndef USB_USBMAST_SCSI_H_
-#define USB_USBMAST_SCSI_H_
-
-#include <sys/types.h>
-#include <usb/usb.h>
-
-typedef struct {
-	uint8_t op_code;
-	uint8_t lun_evpd;
-	uint8_t page_code;
-	uint16_t alloc_length;
-	uint8_t ctrl;
-} __attribute__((packed)) scsi_cmd_inquiry_t;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbmast/scsi_ms.c
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/drv/bus/usb/usbmast/usbmast.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/vhc/connhost.c
===================================================================
--- uspace/drv/bus/usb/vhc/connhost.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/bus/usb/vhc/connhost.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -141,19 +141,14 @@
     size_t max_packet_size, unsigned int interval)
 {
-	VHC_DATA(vhc, fun);
-
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
+	/* 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 = endpoint_init(ep, address, endpoint, direction, transfer_type,
-	    USB_SPEED_FULL, 1);
-	if (rc != EOK) {
-		free(ep);
-		return rc;
-	}
-
-	rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
+	int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
 	if (rc != EOK) {
 		endpoint_destroy(ep);
Index: uspace/drv/infrastructure/root/root.c
===================================================================
--- uspace/drv/infrastructure/root/root.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/infrastructure/root/root.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -176,4 +176,6 @@
 	}
 
+	free(match_id);
+
 	rc = ddf_fun_bind(fun);
 	if (rc != EOK) {
Index: uspace/drv/test/test1/test1.c
===================================================================
--- uspace/drv/test/test1/test1.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/drv/test/test1/test1.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -74,5 +74,5 @@
 	}
 
-	rc = ddf_fun_add_match_id(fun, str_dup(match_id), match_score);
+	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",
Index: uspace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/block/libblock.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -258,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);
 }
 
@@ -264,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]);
 }
 
@@ -305,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);
@@ -344,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);
@@ -398,5 +401,9 @@
 	block_t *b;
 	link_t *l;
-	unsigned long key = ba;
+	unsigned long key[2] = {
+		LOWER32(ba),
+		UPPER32(ba)
+	};
+
 	int rc;
 	
@@ -413,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:
@@ -451,5 +458,4 @@
 			 * Try to recycle a block from the free list.
 			 */
-			unsigned long temp_key;
 recycle:
 			if (list_empty(&cache->free_list)) {
@@ -499,5 +505,5 @@
 					goto retry;
 				}
-				l = hash_table_find(&cache->block_hash, &key);
+				l = hash_table_find(&cache->block_hash, key);
 				if (l) {
 					/*
@@ -522,6 +528,9 @@
 			 */
 			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);
 		}
 
@@ -531,5 +540,5 @@
 		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);
 
 		/*
@@ -643,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);
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -59,6 +59,4 @@
 -include arch/$(UARCH)/Makefile.inc
 
-EXTRA_CFLAGS += -I../../srv/loader/include
-
 GENERIC_SOURCES = \
 	generic/libc.c \
@@ -70,4 +68,5 @@
 	generic/device/hw_res.c \
 	generic/device/char_dev.c \
+	generic/elf/elf_load.c \
 	generic/event.c \
 	generic/errno.c \
@@ -134,5 +133,4 @@
 		generic/dlfcn.c \
 		generic/rtld/rtld.c \
-		generic/rtld/elf_load.c \
 		generic/rtld/dynamic.c \
 		generic/rtld/module.c \
Index: uspace/lib/c/arch/abs32le/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/abs32le/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/amd64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/amd64/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/amd64/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/arm32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/arm32/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/arm32/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/ia32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ia32/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/ia32/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/ia64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ia64/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/ia64/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/mips32/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips32/Makefile.common	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32/Makefile.common	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -27,5 +27,5 @@
 #
 
-GCC_CFLAGS += -mips3
+GCC_CFLAGS += -mips3 -mabi=32
 
 ENDIANESS = LE
Index: uspace/lib/c/arch/mips32/include/atomic.h
===================================================================
--- uspace/lib/c/arch/mips32/include/atomic.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32/include/atomic.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @ingroup libcmips32eb
+ * @ingroup libcmips32
  */
 
Index: uspace/lib/c/arch/mips32/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/mips32/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips32/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32/include/fibril.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -27,9 +27,9 @@
  */
 
-/** @addtogroup libcmips32	
+/** @addtogroup libcmips32
  * @{
  */
 /** @file
- * @ingroup libcmips32eb	
+ * @ingroup libcmips32
  */
 
Index: uspace/lib/c/arch/mips32/include/thread.h
===================================================================
--- uspace/lib/c/arch/mips32/include/thread.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32/include/thread.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32/include/tls.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32/include/types.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @ingroup libcmips32eb
+ * @ingroup libcmips32
  */
 
Index: uspace/lib/c/arch/mips32/src/syscall.c
===================================================================
--- uspace/lib/c/arch/mips32/src/syscall.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32/src/syscall.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32/src/tls.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/arch/mips32eb/Makefile.common	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -27,5 +27,5 @@
 #
 
-GCC_CFLAGS += -mips3
+GCC_CFLAGS += -mips3 -mabi=32
 
 ENDIANESS = BE
Index: uspace/lib/c/arch/mips32eb/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/mips32eb/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips32eb/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,1 @@
+../../mips32/include/elf_linux.h
Index: uspace/lib/c/arch/mips64/Makefile.common
===================================================================
--- uspace/lib/c/arch/mips64/Makefile.common	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/Makefile.common	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/Makefile.inc	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/_link.ld.in	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/atomic.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/config.h
===================================================================
--- uspace/lib/c/arch/mips64/include/config.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/config.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/ddi.h
===================================================================
--- uspace/lib/c/arch/mips64/include/ddi.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/ddi.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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_linux.h
===================================================================
--- uspace/lib/c/arch/mips64/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/faddr.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/fibril.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/inttypes.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/istate.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,43 @@
+/*
+ * 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
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_mips64__ISTATE_H_
+#define LIBC_mips64__ISTATE_H_
+
+#include <arch/istate.h>
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/arch/mips64/include/syscall.h
===================================================================
--- uspace/lib/c/arch/mips64/include/syscall.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/syscall.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/thread.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/tls.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/include/types.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/src/entry.s	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/src/entryjmp.s	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/src/fibril.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 <arch/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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/src/stacktrace.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/src/stacktrace_asm.S	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/src/syscall.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/src/thread_entry.s	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/mips64/src/tls.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/ppc32/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/sparc64/include/elf_linux.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/arch/sparc64/include/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/generic/elf/elf_load.c
===================================================================
--- uspace/lib/c/generic/elf/elf_load.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/generic/elf/elf_load.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/io/console.c
===================================================================
--- uspace/lib/c/generic/io/console.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/generic/io/console.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -76,9 +76,5 @@
 bool console_kcon(void)
 {
-#if 0
 	return __SYSCALL0(SYS_DEBUG_ACTIVATE_CONSOLE);
-#endif
-	
-	return false;
 }
 
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/generic/io/io.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -594,9 +594,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 +607,4 @@
 		}
 	}
-	
-	if (total_written > 0)
-		stream->buf_state = _bs_write;
 
 	if (need_flush)
@@ -714,4 +712,5 @@
 off64_t ftell(FILE *stream)
 {
+	_fflushbuf(stream);
 	return lseek(stream->fd, 0, SEEK_CUR);
 }
Index: pace/lib/c/generic/rtld/elf_load.c
===================================================================
--- uspace/lib/c/generic/rtld/elf_load.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../../../../srv/loader/elf_load.c
Index: uspace/lib/c/generic/rtld/module.c
===================================================================
--- uspace/lib/c/generic/rtld/module.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/generic/rtld/module.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -35,10 +35,11 @@
  */
 
+#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 <fcntl.h>
-#include <adt/list.h>
-#include <loader/pcb.h>
 
 #include <rtld/rtld.h>
@@ -47,5 +48,4 @@
 #include <rtld/rtld_arch.h>
 #include <rtld/module.h>
-#include <elf_load.h>
 
 /** (Eagerly) process all relocation tables in a module.
@@ -93,7 +93,4 @@
 module_t *module_find(const char *name)
 {
-	link_t *head = &runtime_env->modules_head;
-
-	link_t *cur;
 	module_t *m;
 	const char *p, *soname;
@@ -110,6 +107,5 @@
 
 	/* Traverse list of all modules. Not extremely fast, but simple */
-	DPRINTF("head = %p\n", head);
-	for (cur = head->next; cur != head; cur = cur->next) {
+	list_foreach(runtime_env->modules, cur) {
 		DPRINTF("cur = %p\n", cur);
 		m = list_get_instance(cur, module_t, modules_link);
@@ -177,5 +173,5 @@
 
 	/* Insert into the list of loaded modules */
-	list_append(&m->modules_link, &runtime_env->modules_head);
+	list_append(&m->modules_link, &runtime_env->modules);
 
 	return m;
@@ -249,10 +245,7 @@
 void modules_process_relocs(module_t *start)
 {
-	link_t *head = &runtime_env->modules_head;
-
-	link_t *cur;
-	module_t *m;
-
-	for (cur = head->next; cur != head; cur = cur->next) {
+	module_t *m;
+
+	list_foreach(runtime_env->modules, cur) {
 		m = list_get_instance(cur, module_t, modules_link);
 
@@ -268,10 +261,7 @@
 void modules_untag(void)
 {
-	link_t *head = &runtime_env->modules_head;
-
-	link_t *cur;
-	module_t *m;
-
-	for (cur = head->next; cur != head; cur = cur->next) {
+	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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/generic/rtld/rtld.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -44,5 +44,5 @@
 {
 	runtime_env = &rt_env_static;
-	list_initialize(&runtime_env->modules_head);
+	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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/generic/rtld/symbol.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -38,8 +38,8 @@
 #include <stdlib.h>
 
+#include <elf/elf.h>
 #include <rtld/rtld.h>
 #include <rtld/rtld_debug.h>
 #include <rtld/symbol.h>
-#include <elf.h>
 
 /*
@@ -118,5 +118,5 @@
 	module_t *m, *dm;
 	elf_symbol_t *sym, *s;
-	link_t queue_head;
+	list_t queue;
 	size_t i;
 
@@ -132,7 +132,7 @@
 
 	/* Insert root (the program) into the queue and tag it */
-	list_initialize(&queue_head);
+	list_initialize(&queue);
 	start->bfs_tag = true;
-	list_append(&start->queue_link, &queue_head);
+	list_append(&start->queue_link, &queue);
 
 	/* If the symbol is found, it will be stored in 'sym' */
@@ -140,7 +140,7 @@
 
 	/* While queue is not empty */
-	while (!list_empty(&queue_head)) {
+	while (!list_empty(&queue)) {
 		/* Pop first element from the queue */
-		m = list_get_instance(queue_head.next, module_t, queue_link);
+		m = list_get_instance(list_first(&queue), module_t, queue_link);
 		list_remove(&m->queue_link);
 
@@ -162,5 +162,5 @@
 			if (dm->bfs_tag == false) {
 				dm->bfs_tag = true;
-				list_append(&dm->queue_link, &queue_head);
+				list_append(&dm->queue_link, &queue);
 			}
 		}
@@ -168,6 +168,6 @@
 
 	/* Empty the queue so that we leave it in a clean state */
-	while (!list_empty(&queue_head))
-		list_remove(queue_head.next);
+	while (!list_empty(&queue))
+		list_remove(list_first(&queue));
 
 	if (!sym) {
Index: uspace/lib/c/generic/str.c
===================================================================
--- uspace/lib/c/generic/str.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/generic/str.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -544,4 +544,67 @@
 	
 	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;
 }
 
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -417,4 +417,66 @@
 }
 
+/** 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)
 {
Index: uspace/lib/c/include/bitops.h
===================================================================
--- uspace/lib/c/include/bitops.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/include/bitops.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/elf/elf.h
===================================================================
--- uspace/lib/c/include/elf/elf.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/include/elf/elf.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,43 @@
+/*
+ * 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 <kernel/lib/elf.h>
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/elf/elf_linux.h
===================================================================
--- uspace/lib/c/include/elf/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/include/elf/elf_linux.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/include/elf/elf_load.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,102 @@
+/*
+ * 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 <arch/elf.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/fourcc.h
===================================================================
--- uspace/lib/c/include/fourcc.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/include/fourcc.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/ipc/console.h
===================================================================
--- uspace/lib/c/include/ipc/console.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/include/ipc/console.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/services.h
===================================================================
--- uspace/lib/c/include/ipc/services.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/include/ipc/services.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -38,23 +38,25 @@
 #define LIBC_SERVICES_H_
 
+#include <fourcc.h>
+
 typedef enum {
-	SERVICE_NONE = 0,
-	SERVICE_LOAD,
-	SERVICE_VIDEO,
-	SERVICE_VFS,
-	SERVICE_LOC,
-	SERVICE_DEVMAN,
-	SERVICE_IRC,
-	SERVICE_CLIPBOARD,
-	SERVICE_NETWORKING,
-	SERVICE_LO,
-	SERVICE_NE2000,
-	SERVICE_ETHERNET,
-	SERVICE_NILDUMMY,
-	SERVICE_IP,
-	SERVICE_ARP,
-	SERVICE_ICMP,
-	SERVICE_UDP,
-	SERVICE_TCP
+	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/rtld/elf_dyn.h
===================================================================
--- uspace/lib/c/include/rtld/elf_dyn.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/include/rtld/elf_dyn.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -39,5 +39,5 @@
 #include <sys/types.h>
 
-#include <elf.h>
+#include <elf/elf.h>
 #include <libarch/rtld/elf_dyn.h>
 
Index: uspace/lib/c/include/rtld/rtld.h
===================================================================
--- uspace/lib/c/include/rtld/rtld.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/include/rtld/rtld.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -49,5 +49,5 @@
 
 	/** List of all loaded modules including rtld and the program */
-	link_t modules_head;
+	list_t modules;
 
 	/** Temporary hack to place each module at different address. */
Index: uspace/lib/c/include/rtld/symbol.h
===================================================================
--- uspace/lib/c/include/rtld/symbol.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/include/rtld/symbol.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -36,6 +36,6 @@
 #define LIBC_RTLD_SYMBOL_H_
 
+#include <elf/elf.h>
 #include <rtld/rtld.h>
-#include <elf.h>
 
 elf_symbol_t *symbol_bfs_find(const char *name, module_t *start, module_t **mod);
Index: uspace/lib/c/include/str.h
===================================================================
--- uspace/lib/c/include/str.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/include/str.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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);
Index: uspace/lib/c/include/typedefs.h
===================================================================
--- uspace/lib/c/include/typedefs.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/c/include/typedefs.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -0,0 +1,46 @@
+/*
+ * 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
+ *
+ * This header allows including a kernel header using typedefs.h from
+ * libc. User-space code should use sys/types.h directly.
+ */
+
+#ifndef LIBC_TYPEDEFS_H_
+#define LIBC_TYPEDEFS_H_
+
+#include <sys/types.h>
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/unistd.h
===================================================================
--- uspace/lib/c/include/unistd.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/c/include/unistd.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/clui/tinput.c
===================================================================
--- uspace/lib/clui/tinput.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/clui/tinput.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 {
@@ -61,4 +65,10 @@
 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,6 +110,5 @@
 	tinput_sel_get_bounds(ti, &sa, &sb);
 	
-	console_set_pos(ti->console, (ti->col0 + start) % ti->con_cols,
-	    ti->row0 + (ti->col0 + start) / ti->con_cols);
+	tinput_console_set_lpos(ti, ti->text_coord + start);
 	console_set_style(ti->console, STYLE_NORMAL);
 	
@@ -134,17 +155,45 @@
 static void tinput_position_caret(tinput_t *ti)
 {
-	console_set_pos(ti->console, (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;
 }
 
@@ -154,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. */
@@ -185,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. */
@@ -511,4 +560,141 @@
 }
 
+/** 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;
+}
+
+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);
+			for (i = 0; i < cnum; i++)
+				printf("%s\n", compl[i]);
+			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.
  *
@@ -521,4 +707,33 @@
 	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;
 }
 
@@ -539,7 +754,4 @@
 		return EIO;
 	
-	if (console_get_pos(ti->console, &ti->col0, &ti->row0) != EOK)
-		return EIO;
-	
 	ti->pos = 0;
 	ti->sel_start = 0;
@@ -549,4 +761,7 @@
 	ti->exit_clui = false;
 	
+	if (tinput_display(ti) != EOK)
+		return EIO;
+	
 	while (!ti->done) {
 		console_flush(ti->console);
@@ -714,4 +929,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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/clui/tinput.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -37,11 +37,65 @@
 #define LIBCLUI_TINPUT_H_
 
-#include <stdio.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).
@@ -53,10 +107,17 @@
 	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 */
@@ -90,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/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/drv/generic/driver.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -314,4 +314,10 @@
 		    " %" PRIun " was found.\n", driver->name, handle);
 		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (fun->conn_handler != NULL) {
+		/* Driver has a custom connection handler. */
+		(*fun->conn_handler)(iid, icall, (void *)fun);
 		return;
 	}
@@ -614,5 +620,5 @@
 		return ENOMEM;
 	
-	match_id->id = match_id_str;
+	match_id->id = str_dup(match_id_str);
 	match_id->score = 90;
 	
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 */
Index: uspace/lib/ext2/libext2_directory.c
===================================================================
--- uspace/lib/ext2/libext2_directory.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/ext2/libext2_directory.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -86,32 +86,17 @@
  * @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)
-{
-	int rc;
-	uint32_t block_id;
-	uint32_t block_size;
-	
+    ext2_filesystem_t *fs, ext2_inode_ref_t *inode_ref, aoff64_t pos)
+{	
 	it->inode_ref = inode_ref;
 	it->fs = fs;
-	
-	/* Get the first data block, so we can get the first entry */
-	rc = ext2_filesystem_get_inode_data_block_index(fs, inode_ref->inode, 0, 
-	    &block_id);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	rc = block_get(&it->current_block, fs->device, block_id, 0);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	block_size = ext2_superblock_get_block_size(fs->superblock);
-	
-	it->current_offset = 0;	
-	return ext2_directory_iterator_set(it, block_size);
+	it->current = NULL;
+	it->current_offset = 0;
+	it->current_block = NULL;
+	
+	return ext2_directory_iterator_seek(it, pos);
 }
 
@@ -124,6 +109,23 @@
 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;
-	uint16_t skip;
+	
 	uint64_t size;
 	aoff64_t current_block_idx;
@@ -132,19 +134,20 @@
 	uint32_t block_size;
 	
-	assert(it->current != NULL);
-	
-	skip = ext2_directory_entry_ll_get_entry_length(it->current);
 	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 (it->current_offset + skip >= size) {
-		rc = block_put(it->current_block);
-		it->current_block = NULL;
-		it->current = NULL;
-		if (rc != EOK) {
-			return rc;
+	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 += skip;
+		it->current_offset = pos;
 		return EOK;
 	}
@@ -152,15 +155,16 @@
 	block_size = ext2_superblock_get_block_size(it->fs->superblock);
 	current_block_idx = it->current_offset / block_size;
-	next_block_idx = (it->current_offset + skip) / block_size;
-	
-	/* If we are moving accross block boundary,
+	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 (current_block_idx != next_block_idx) {
-		rc = block_put(it->current_block);
-		it->current_block = NULL;
-		it->current = NULL;
-		if (rc != EOK) {
-			return rc;
+	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;
+			}
 		}
 		
@@ -179,8 +183,15 @@
 	}
 	
-	it->current_offset += skip;
+	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)
Index: uspace/lib/ext2/libext2_directory.h
===================================================================
--- uspace/lib/ext2/libext2_directory.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/ext2/libext2_directory.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -71,6 +71,7 @@
 
 extern int ext2_directory_iterator_init(ext2_directory_iterator_t *,
-    ext2_filesystem_t *, ext2_inode_ref_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 *);
 
Index: uspace/lib/fs/libfs.c
===================================================================
--- uspace/lib/fs/libfs.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/fs/libfs.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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.
  *
@@ -68,16 +291,14 @@
  *
  * @param sess Session 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 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(async_sess_t *sess, 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)
 {
 	/*
@@ -104,13 +325,19 @@
 	
 	/*
+	 * Set VFS_OUT and libfs operations.
+	 */
+	vfs_out_ops = vops;
+	libfs_ops = lops;
+
+	/*
 	 * Ask VFS for callback connection.
 	 */
-	async_connect_to_me(exch, 0, 0, 0, conn, NULL);
+	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);
@@ -121,5 +348,5 @@
 	 * Request sharing the Path Lookup Buffer with VFS.
 	 */
-	rc = async_share_in_start_0_0(exch, reg->plb_ro, PLB_SIZE);
+	rc = async_share_in_start_0_0(exch, reg.plb_ro, PLB_SIZE);
 	
 	async_exchange_end(exch);
@@ -134,5 +361,5 @@
 	 */
 	async_wait_for(req, NULL);
-	reg->fs_handle = (int) IPC_GET_ARG1(answer);
+	reg.fs_handle = (int) IPC_GET_ARG1(answer);
 	
 	/*
@@ -140,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);
@@ -151,10 +378,10 @@
 
 void libfs_mount(libfs_ops_t *ops, fs_handle_t fs_handle, ipc_callid_t rid,
-    ipc_call_t *request)
-{
-	service_id_t mp_service_id = (service_id_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);
-	service_id_t mr_service_id = (service_id_t) IPC_GET_ARG4(*request);
+    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);
@@ -208,12 +435,12 @@
 	 * 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)
-{
-	service_id_t mp_service_id = (service_id_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;
@@ -259,4 +486,9 @@
 }
 
+static char plb_get_char(unsigned pos)
+{
+	return reg.plb_ro[pos % PLB_SIZE];
+}
+
 /** Lookup VFS triplet by name in the file system name space.
  *
@@ -273,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;
-	service_id_t service_id = 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;
@@ -298,5 +530,6 @@
 		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);
+		    cur->mp_data.service_id, lflag, index,
+		    IPC_FF_ROUTE_FROM_ME);
 		async_exchange_end(exch);
 		
@@ -306,5 +539,5 @@
 	
 	/* Eat slash */
-	if (ops->plb_get_char(next) == '/')
+	if (plb_get_char(next) == '/')
 		next++;
 	
@@ -319,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 */
@@ -325,5 +558,5 @@
 				goto out;
 			}
-			component[len++] = ops->plb_get_char(next);
+			component[len++] = plb_get_char(next);
 			/* Process next character */
 			next++;
@@ -357,6 +590,6 @@
 			
 			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,
+			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);
@@ -451,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);
@@ -463,5 +696,5 @@
 				}
 				
-				component[len++] = ops->plb_get_char(next);
+				component[len++] = plb_get_char(next);
 				/* Process next character */
 				next++;
@@ -637,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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/fs/libfs.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -43,4 +43,17 @@
 
 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;
 	async_sess_t *sess;
@@ -71,11 +84,10 @@
 	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 *);
@@ -88,15 +100,8 @@
 } fs_reg_t;
 
-extern int fs_register(async_sess_t *, 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/net/il/ip_remote.c
===================================================================
--- uspace/lib/net/il/ip_remote.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/net/il/ip_remote.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -123,7 +123,9 @@
  *
  */
-int ip_device_req_remote(async_sess_t *sess, device_id_t device_id)
-{
-	return generic_device_req_remote(sess, NET_IP_DEVICE, device_id, 0, 0);
+int ip_device_req_remote(async_sess_t *sess, device_id_t device_id,
+    services_t service)
+{
+	return generic_device_req_remote(sess, NET_IP_DEVICE, device_id, 0,
+	    service);
 }
 
Index: uspace/lib/net/include/ip_remote.h
===================================================================
--- uspace/lib/net/include/ip_remote.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/net/include/ip_remote.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -48,5 +48,5 @@
 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);
+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);
Index: uspace/lib/net/include/netif_skel.h
===================================================================
--- uspace/lib/net/include/netif_skel.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/net/include/netif_skel.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -205,5 +205,5 @@
 extern packet_t *netif_packet_get_1(size_t);
 
-extern int netif_module_start(sysarg_t);
+extern int netif_module_start(void);
 
 #endif
Index: uspace/lib/net/include/nil_remote.h
===================================================================
--- uspace/lib/net/include/nil_remote.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/net/include/nil_remote.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -58,6 +58,7 @@
 	    packet_get_id(packet), sender, 0)
 
-#define nil_device_req(sess, device_id, mtu) \
-	generic_device_req_remote(sess, NET_NIL_DEVICE, device_id, mtu, 0)\
+#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(async_sess_t *, device_id_t, sysarg_t);
Index: uspace/lib/net/netif/netif_skel.c
===================================================================
--- uspace/lib/net/netif/netif_skel.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/net/netif/netif_skel.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -228,4 +228,29 @@
 }
 
+/** Register the device notification receiver,
+ *
+ * Register a network interface layer module as the device
+ * notification receiver.
+ *
+ * @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(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;
+	}
+	
+	netif_globals.nil_sess = sess;
+	
+	fibril_rwlock_write_unlock(&netif_globals.lock);
+	return EOK;
+}
+
 /** Process the netif module messages.
  *
@@ -257,4 +282,9 @@
 		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 NET_NETIF_PROBE:
@@ -358,6 +388,4 @@
  * messages in an infinite loop.
  *
- * @param[in] nil_service Network interface layer service.
- *
  * @return EOK on success.
  * @return Other error codes as defined for each specific module
@@ -365,10 +393,10 @@
  *
  */
-int netif_module_start(sysarg_t nil_service)
+int netif_module_start(void)
 {
 	async_set_client_connection(netif_client_connection);
 	
 	netif_globals.sess = connect_to_service(SERVICE_NETWORKING);
-	netif_globals.nil_sess = connect_to_service(nil_service);
+	netif_globals.nil_sess = NULL;
 	netif_device_map_initialize(&netif_globals.device_map);
 	
Index: uspace/lib/scsi/Makefile
===================================================================
--- uspace/lib/scsi/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/scsi/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/scsi/include/scsi/sbc.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/scsi/include/scsi/spc.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/scsi/src/spc.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/softfloat/arch/mips32/include/functions.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 86ffa27f45682aa2a5736f665f400ad262ce5baf)
+++ uspace/lib/softfloat/arch/mips64/include/functions.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -119,4 +119,6 @@
      */
     uint16_t hub_characteristics;
+#define HUB_CHAR_POWER_PER_PORT_FLAG  (1 << 0)
+#define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)
 
     /**
Index: uspace/lib/usbhost/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -61,7 +61,7 @@
 } endpoint_t;
 
-int endpoint_init(endpoint_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);
+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);
Index: uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -82,21 +82,15 @@
     size_t data_size)
 {
-	endpoint_t *ep = malloc(sizeof(endpoint_t));
-	if (ep == NULL)
+	endpoint_t *ep = endpoint_get(
+	    address, endpoint, direction, type, speed, max_packet_size);
+	if (!ep)
 		return ENOMEM;
 
-	int ret = endpoint_init(ep, address, endpoint, direction, type, speed,
-	    max_packet_size);
-	if (ret != EOK) {
-		free(ep);
-		return ret;
-	}
-
-	ret = usb_endpoint_manager_register_ep(instance, ep, data_size);
+	const int ret =
+	    usb_endpoint_manager_register_ep(instance, ep, data_size);
 	if (ret != EOK) {
 		endpoint_destroy(ep);
-		return ret;
 	}
-	return EOK;
+	return ret;
 }
 #endif
Index: uspace/lib/usbhost/src/batch.c
===================================================================
--- uspace/lib/usbhost/src/batch.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/usbhost/src/batch.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -109,4 +109,5 @@
 	assert(instance);
 	assert(instance->ep);
+	assert(instance->next_step);
 	endpoint_release(instance->ep);
 	instance->next_step(instance);
@@ -128,5 +129,5 @@
 	memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
 
-	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
+	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));
@@ -145,5 +146,5 @@
 	assert(instance->callback_out);
 
-	usb_log_debug("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n",
+	usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed: %s.\n",
 	    instance, USB_TRANSFER_BATCH_ARGS(*instance),
 	    str_error(instance->error));
Index: uspace/lib/usbhost/src/endpoint.c
===================================================================
--- uspace/lib/usbhost/src/endpoint.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/lib/usbhost/src/endpoint.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -39,21 +39,23 @@
 #include <usb/host/endpoint.h>
 
-int endpoint_init(endpoint_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)
+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)
 {
-	assert(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 EOK;
+	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;
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -80,7 +80,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. */
@@ -281,4 +278,5 @@
 	sysarg_t method;
 	service_id_t dsid;
+	size_t comm_size;	/**< Size of the communication area. */
 	unsigned int flags;
 	int retval;
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/devman/devman.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -270,7 +270,8 @@
 	}
 	
-	ssize_t read_bytes = safe_read(fd, buf, len);
+	ssize_t read_bytes = read_all(fd, buf, len);
 	if (read_bytes <= 0) {
-		log_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
+		log_msg(LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
+		    read_bytes);
 		goto cleanup;
 	}
@@ -421,7 +422,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);
Index: uspace/srv/devman/util.c
===================================================================
--- uspace/srv/devman/util.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/devman/util.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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)
 {
@@ -111,31 +100,4 @@
 }
 
-ssize_t safe_read(int fd, void *buffer, size_t size)
-{
-	if (size == 0) {
-		return 0;
-	}
-
-	uint8_t *buf_ptr = (uint8_t *) buffer;
-
-	size_t total_read = 0;
-	while (total_read < size) {
-		ssize_t bytes_read = read(fd, buf_ptr, size - total_read);
-		if (bytes_read < 0) {
-			/* Error. */
-			return bytes_read;
-		} else if (bytes_read == 0) {
-			/* Possibly end of file. */
-			break;
-		} else {
-			/* Read at least something. */
-			buf_ptr += bytes_read;
-			total_read += bytes_read;
-		}
-	}
-
-	return (ssize_t) total_read;
-}
-
 /** @}
  */
Index: uspace/srv/devman/util.h
===================================================================
--- uspace/srv/devman/util.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/devman/util.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -44,8 +44,5 @@
 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);
-
-extern ssize_t safe_read(int, void *, size_t);
 
 #endif
Index: uspace/srv/fs/ext2fs/ext2fs.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/ext2fs/ext2fs.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -1,5 +1,4 @@
 /*
  * Copyright (c) 2006 Martin Decky
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -55,90 +54,4 @@
 };
 
-fs_reg_t ext2fs_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 EXT2FS. To overcome this bottleneck, VFS can send EXT2FS 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, EXT2FS 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, EXT2FS might want to keep the connections open after the
- * request has been completed.
- */
-static void ext2fs_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);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	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:
-			ext2fs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			ext2fs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			ext2fs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			ext2fs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			ext2fs_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			ext2fs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			ext2fs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			ext2fs_truncate(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			ext2fs_stat(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			ext2fs_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			ext2fs_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			ext2fs_open_node(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			ext2fs_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
@@ -158,5 +71,6 @@
 	}	
 		
-	rc = fs_register(vfs_sess, &ext2fs_reg, &ext2fs_vfs_info, ext2fs_connection);
+	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);
Index: uspace/srv/fs/ext2fs/ext2fs.h
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/ext2fs/ext2fs.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -1,4 +1,3 @@
 /*
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -36,35 +35,14 @@
 
 #include <libext2.h>
-#include <fibril_synch.h>
 #include <libfs.h>
-#include <atomic.h>
 #include <sys/types.h>
-#include <bool.h>
-#include "../../vfs/vfs.h"
-
-#ifndef dprintf
-#define dprintf(...)	printf(__VA_ARGS__)
-#endif
 
 #define min(a, b)		((a) < (b) ? (a) : (b))
 
-extern fs_reg_t ext2fs_reg;
+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);
-extern void ext2fs_mounted(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_mount(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_unmount(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_lookup(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_read(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_write(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_truncate(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_close(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_destroy(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_open_node(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_stat(ipc_callid_t, ipc_call_t *);
-extern void ext2fs_sync(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -1,4 +1,3 @@
 /*
- * Copyright (c) 2008 Jakub Jermar
  * Copyright (c) 2011 Martin Sucha
  * All rights reserved.
@@ -87,8 +86,8 @@
  */
 static int ext2fs_instance_get(service_id_t, ext2fs_instance_t **);
-static void ext2fs_read_directory(ipc_callid_t, ipc_callid_t, aoff64_t,
-	size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
-static void ext2fs_read_file(ipc_callid_t, ipc_callid_t, aoff64_t,
-	size_t, ext2fs_instance_t *, ext2_inode_ref_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);
@@ -111,5 +110,4 @@
 static aoff64_t ext2fs_size_get(fs_node_t *);
 static unsigned ext2fs_lnkcnt_get(fs_node_t *);
-static char ext2fs_plb_get_char(unsigned);
 static bool ext2fs_is_directory(fs_node_t *);
 static bool ext2fs_is_file(fs_node_t *node);
@@ -240,5 +238,5 @@
 	}
 	
-	rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref);
+	rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref, 0);
 	if (rc != EOK) {
 		return rc;
@@ -478,5 +476,5 @@
 	}
 	
-	rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref);
+	rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref, 0);
 	if (rc != EOK) {
 		EXT2FS_DBG("error %u", rc);
@@ -538,9 +536,4 @@
 	EXT2FS_DBG("%u", count);
 	return count;
-}
-
-char ext2fs_plb_get_char(unsigned pos)
-{
-	return ext2fs_reg.plb_ro[pos % PLB_SIZE];
 }
 
@@ -586,5 +579,4 @@
 	.size_get = ext2fs_size_get,
 	.lnkcnt_get = ext2fs_lnkcnt_get,
-	.plb_get_char = ext2fs_plb_get_char,
 	.is_directory = ext2fs_is_directory,
 	.is_file = ext2fs_is_file,
@@ -596,30 +588,17 @@
  */
 
-void ext2fs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	int rc;
-	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
+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;
 	
-	/* 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;
-	}
-
-	free(opts);
-	
 	/* Allocate libext2 filesystem structure */
 	fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
-	if (fs == NULL) {
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (fs == NULL)
+		return ENOMEM;
 	
 	/* Allocate instance structure */
@@ -627,6 +606,5 @@
 	if (inst == NULL) {
 		free(fs);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	
@@ -636,6 +614,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -646,6 +623,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -656,6 +632,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -673,6 +648,5 @@
 		free(fs);
 		free(inst);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	ext2fs_node_t *enode = EXT2FS_NODE(root_node);
@@ -683,22 +657,16 @@
 	fibril_mutex_unlock(&instance_list_mutex);
 	
-	async_answer_3(rid, EOK,
-	    EXT2_INODE_ROOT_INDEX,
-	    0,
-	    ext2_inode_get_usage_count(enode->inode_ref->inode));
+	*index = EXT2_INODE_ROOT_INDEX;
+	*size = 0;
+	*lnkcnt = ext2_inode_get_usage_count(enode->inode_ref->inode);
 	
 	ext2fs_node_put(root_node);
-}
-
-void ext2fs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_mount(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
+
+	return EOK;
+}
+
+static int ext2fs_unmounted(service_id_t service_id)
+{
+	EXT2FS_DBG("");
 	ext2fs_instance_t *inst;
 	int rc;
@@ -706,8 +674,6 @@
 	rc = ext2fs_instance_get(service_id, &inst);
 	
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 	
 	fibril_mutex_lock(&open_nodes_lock);
@@ -716,6 +682,5 @@
 	if (inst->open_nodes_count != 0) {
 		fibril_mutex_unlock(&open_nodes_lock);
-		async_answer_0(rid, EBUSY);
-		return;
+		return EBUSY;
 	}
 	
@@ -729,26 +694,12 @@
 	ext2_filesystem_fini(inst->filesystem);
 	
-	async_answer_0(rid, EOK);
-}
-
-void ext2fs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_unmount(&ext2fs_libfs_ops, rid, request);
-}
-
-void ext2fs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_lookup(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	service_id_t service_id = (service_id_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));
+	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;
@@ -763,6 +714,5 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 	
@@ -770,6 +720,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -777,24 +726,24 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
 	if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
-		    EXT2_INODE_MODE_FILE)) {
-		ext2fs_read_file(rid, callid, pos, size, inst, inode_ref);
-	}
-	else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
-		    EXT2_INODE_MODE_DIRECTORY)) {
-		ext2fs_read_directory(rid, callid, pos, size, inst, inode_ref);
-	}
-	else {
+	    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);
-		async_answer_0(rid, ENOTSUP);
+		rc = ENOTSUP;
 	}
 	
 	ext2_filesystem_put_inode_ref(inode_ref);
 	
+	return rc;
 }
 
@@ -814,9 +763,9 @@
 }
 
-void ext2fs_read_directory(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
-	size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
+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 cur;
+	aoff64_t next;
 	uint8_t *buf;
 	size_t name_size;
@@ -824,18 +773,14 @@
 	bool found = false;
 	
-	rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref);
+	rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref, pos);
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
-	}
-	
-	/* Find the index we want to read
-	 * Note that we need to iterate and count as
-	 * the underlying structure is a linked list
-	 * Moreover, we want to skip . and .. entries
+		return rc;
+	}
+	
+	/* Find next interesting directory entry.
+	 * We want to skip . and .. entries
 	 * as these are not used in HelenOS
 	 */
-	cur = 0;
 	while (it.current != NULL) {
 		if (it.current->inode == 0) {
@@ -844,5 +789,5 @@
 		
 		name_size = ext2_directory_entry_ll_get_name_length(
-			inst->filesystem->superblock, it.current);
+		    inst->filesystem->superblock, it.current);
 		
 		/* skip . and .. */
@@ -851,25 +796,20 @@
 		}
 		
-		/* Is this the dir entry we want to read? */
-		if (cur == pos) {
-			/* 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);
-				async_answer_0(rid, ENOMEM);
-				return;
-			}
-			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;
-		}
-		cur++;
+		/* 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:
@@ -878,26 +818,30 @@
 			ext2_directory_iterator_fini(&it);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
-		}
+			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) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 	
 	if (found) {
-		async_answer_1(rid, EOK, 1);
-	}
-	else {
+		*rbytes = next - pos;
+		return EOK;
+	} else {
 		async_answer_0(callid, ENOENT);
-		async_answer_0(rid, ENOENT);
-	}
-}
-
-void ext2fs_read_file(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
-	size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
+		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;
@@ -917,6 +861,6 @@
 		/* Read 0 bytes successfully */
 		async_data_read_finalize(callid, NULL, 0);
-		async_answer_1(rid, EOK, 0);
-		return;
+		*rbytes = 0;
+		return EOK;
 	}
 	
@@ -937,6 +881,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -950,6 +893,5 @@
 		if (buffer == NULL) {
 			async_answer_0(callid, ENOMEM);
-			async_answer_0(rid, ENOMEM);
-			return;
+			return ENOMEM;
 		}
 		
@@ -957,9 +899,9 @@
 		
 		async_data_read_finalize(callid, buffer, bytes);
-		async_answer_1(rid, EOK, bytes);
+		*rbytes = bytes;
 		
 		free(buffer);
 		
-		return;
+		return EOK;
 	}
 	
@@ -968,6 +910,5 @@
 	if (rc != EOK) {
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 	
@@ -976,75 +917,57 @@
 	
 	rc = block_put(block);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-		
-	async_answer_1(rid, EOK, bytes);
-}
-
-void ext2fs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	service_id_t service_id = (service_id_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));
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	service_id_t service_id = (service_id_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));
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	async_answer_0(rid, EOK);
-}
-
-void ext2fs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	service_id_t service_id = (service_id_t)IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
-
-void ext2fs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_open_node(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-	libfs_stat(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
-}
-
-void ext2fs_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	EXT2FS_DBG("");
-//	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
-//	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	// TODO
-	async_answer_0(rid, ENOTSUP);
-}
+	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/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/fat/fat.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -56,91 +56,4 @@
 };
 
-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, 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);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	
-	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:
-			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)
 {
@@ -158,5 +71,5 @@
 	}
 	
-	rc = fs_register(vfs_sess, &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();
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/fat/fat.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -224,20 +224,6 @@
 } 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 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);
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/fat/fat_ops.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -85,5 +85,4 @@
 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);
@@ -901,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)
 {
@@ -936,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,
@@ -943,22 +936,15 @@
 
 /*
- * VFS operations.
+ * FAT VFS_OUT operations.
  */
 
-void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	service_id_t service_id = (service_id_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)
@@ -967,12 +953,8 @@
 		cmode = CACHE_MODE_WB;
 
-	free(opts);
-
 	/* initialize libblock */
 	rc = block_init(EXCHANGE_SERIALIZE, service_id, BS_SIZE);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 
 	/* prepare the boot block */
@@ -980,6 +962,5 @@
 	if (rc != EOK) {
 		block_fini(service_id);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -989,6 +970,5 @@
 	if (BPS(bs) != BS_SIZE) {
 		block_fini(service_id);
-		async_answer_0(rid, ENOTSUP);
-		return;
+		return ENOTSUP;
 	}
 
@@ -997,6 +977,5 @@
 	if (rc != EOK) {
 		block_fini(service_id);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -1006,6 +985,5 @@
 		(void) block_cache_fini(service_id);
 		block_fini(service_id);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -1014,6 +992,5 @@
 		(void) block_cache_fini(service_id);
 		block_fini(service_id);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -1024,6 +1001,5 @@
 		block_fini(service_id);
 		fat_idx_fini_by_service_id(service_id);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	fs_node_initialize(rfn);
@@ -1034,6 +1010,5 @@
 		block_fini(service_id);
 		fat_idx_fini_by_service_id(service_id);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	fat_node_initialize(rootp);
@@ -1046,6 +1021,5 @@
 		block_fini(service_id);
 		fat_idx_fini_by_service_id(service_id);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	assert(ridxp->index == 0);
@@ -1064,15 +1038,13 @@
 	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)
-{
-	service_id_t service_id = (service_id_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;
@@ -1080,8 +1052,6 @@
 
 	rc = fat_root_get(&fn, service_id);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 	nodep = FAT_NODE(fn);
 
@@ -1092,6 +1062,5 @@
 	if (nodep->refcnt != 2) {
 		(void) fat_node_put(fn);
-		async_answer_0(rid, EBUSY);
-		return;
+		return EBUSY;
 	}
 	
@@ -1112,23 +1081,11 @@
 	block_fini(service_id);
 
-	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)
-{
-	service_id_t service_id = (service_id_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));
+	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;
@@ -1139,12 +1096,8 @@
 
 	rc = fat_node_get(&fn, service_id, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1154,6 +1107,5 @@
 		fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -1178,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,
@@ -1186,6 +1137,5 @@
 			if (rc != EOK) {
 				fat_node_put(fn);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 		}
@@ -1244,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:
@@ -1259,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)
-{
-	service_id_t service_id = (service_id_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;
@@ -1278,12 +1226,8 @@
 	
 	rc = fat_node_get(&fn, service_id, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 	
@@ -1293,6 +1237,5 @@
 		(void) fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -1322,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);
@@ -1329,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,
@@ -1338,6 +1279,5 @@
 		if (rc != EOK) {
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		if (pos + bytes > nodep->size) {
@@ -1345,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 {
 		/*
@@ -1364,6 +1304,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/* zero fill any gaps */
@@ -1373,6 +1312,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, service_id, lcl, NULL,
@@ -1382,6 +1320,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,
@@ -1392,6 +1329,5 @@
 			(void) fat_free_clusters(bs, service_id, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/*
@@ -1403,21 +1339,17 @@
 			(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)
-{
-	service_id_t service_id = (service_id_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;
@@ -1426,12 +1358,8 @@
 
 	rc = fat_node_get(&fn, service_id, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1477,17 +1405,14 @@
 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)
-{
-	service_id_t service_id = (service_id_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;
@@ -1495,12 +1420,8 @@
 
 	rc = fat_node_get(&fn, service_id, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 
 	nodep = FAT_NODE(fn);
@@ -1512,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)
-{
-	service_id_t service_id = (service_id_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, service_id, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	
 	fat_node_t *nodep = FAT_NODE(fn);
@@ -1547,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/locfs.c
===================================================================
--- uspace/srv/fs/locfs/locfs.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/locfs/locfs.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -57,65 +57,4 @@
 };
 
-fs_reg_t locfs_reg;
-
-static void locfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	if (iid)
-		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:
-			locfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			locfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			locfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			locfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			locfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			locfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			locfs_stat(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			locfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			locfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			locfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			locfs_close(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			locfs_sync(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			locfs_destroy(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char *argv[])
 {
@@ -134,6 +73,6 @@
 	}
 	
-	int rc = fs_register(vfs_sess, &locfs_reg, &locfs_vfs_info,
-	    locfs_connection);
+	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);
@@ -152,2 +91,3 @@
  * @}
  */
+
Index: uspace/srv/fs/locfs/locfs.h
===================================================================
--- uspace/srv/fs/locfs/locfs.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/locfs/locfs.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -36,5 +36,6 @@
 #include <libfs.h>
 
-extern fs_reg_t locfs_reg;
+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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/locfs/locfs_ops.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -404,9 +404,4 @@
 }
 
-static char locfs_plb_get_char(unsigned pos)
-{
-	return locfs_reg.plb_ro[pos % PLB_SIZE];
-}
-
 static bool locfs_is_directory(fs_node_t *fn)
 {
@@ -448,5 +443,4 @@
 	.size_get = locfs_size_get,
 	.lnkcnt_get = locfs_lnkcnt_get,
-	.plb_get_char = locfs_plb_get_char,
 	.is_directory = locfs_is_directory,
 	.is_file = locfs_is_file,
@@ -463,56 +457,22 @@
 }
 
-void locfs_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 locfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&locfs_libfs_ops, locfs_reg.fs_handle, rid, request);
-}
-
-void locfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void locfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&locfs_libfs_ops, rid, request);
-}
-
-void locfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&locfs_libfs_ops, locfs_reg.fs_handle, rid, request);
-}
-
-void locfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&locfs_libfs_ops, locfs_reg.fs_handle, rid, request);
-}
-
-void locfs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&locfs_libfs_ops, locfs_reg.fs_handle, rid, request);
-}
-
-void locfs_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));
-	
+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;
@@ -520,6 +480,5 @@
 		if (!async_data_read_receive(&callid, &size)) {
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -541,6 +500,6 @@
 			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 			free(desc);
-			async_answer_1(rid, EOK, 1);
-			return;
+			*rbytes = 1;
+			return EOK;
 		}
 		
@@ -556,6 +515,6 @@
 				async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 				free(desc);
-				async_answer_1(rid, EOK, 1);
-				return;
+				*rbytes = 1;
+				return EOK;
 			}
 			
@@ -564,6 +523,5 @@
 		
 		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
+		return ENOENT;
 	}
 	
@@ -576,6 +534,5 @@
 		if (!async_data_read_receive(&callid, &size)) {
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -586,12 +543,11 @@
 			async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
 			free(desc);
-			async_answer_1(rid, EOK, 1);
-			return;
+			*rbytes = 1;
+			return EOK;
 		}
 		
 		free(desc);
 		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
+		return ENOENT;
 	}
 	
@@ -607,6 +563,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&services_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
@@ -618,6 +573,5 @@
 			fibril_mutex_unlock(&services_mutex);
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -626,7 +580,6 @@
 		
 		ipc_call_t answer;
-		aid_t msg = async_send_3(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
-		    IPC_GET_ARG3(*request), &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 */
@@ -640,21 +593,18 @@
 		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 locfs_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;
-	}
+		
+		*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);
@@ -662,6 +612,5 @@
 	if (type == LOC_OBJECT_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, ENOTSUP);
-		return;
+		return ENOTSUP;
 	}
 	
@@ -676,6 +625,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&services_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
@@ -687,6 +635,5 @@
 			fibril_mutex_unlock(&services_mutex);
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -695,7 +642,6 @@
 		
 		ipc_call_t answer;
-		aid_t msg = async_send_3(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
-		    IPC_GET_ARG3(*request), &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 */
@@ -709,27 +655,23 @@
 		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 locfs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void locfs_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;
-	}
+		
+		*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);
@@ -737,6 +679,5 @@
 	if (type == LOC_OBJECT_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
+		return EOK;
 	}
 	
@@ -750,6 +691,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&services_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
@@ -765,19 +705,14 @@
 		fibril_mutex_unlock(&services_mutex);
 		
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void locfs_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;
-	}
+		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);
@@ -785,6 +720,5 @@
 	if (type == LOC_OBJECT_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
+		return EOK;
 	}
 	
@@ -798,6 +732,5 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&services_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
@@ -809,6 +742,6 @@
 		
 		ipc_call_t answer;
-		aid_t msg = async_send_2(exch, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
+		aid_t msg = async_send_2(exch, VFS_OUT_SYNC, service_id,
+		    index, &answer);
 		
 		async_exchange_end(exch);
@@ -820,16 +753,25 @@
 		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 locfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
+		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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/locfs/locfs_ops.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -34,22 +34,7 @@
 #define LOCFS_LOCFS_OPS_H_
 
-#include <ipc/common.h>
 #include <bool.h>
 
 extern bool locfs_init(void);
-
-extern void locfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void locfs_mount(ipc_callid_t, ipc_call_t *);
-extern void locfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void locfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void locfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void locfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void locfs_stat(ipc_callid_t, ipc_call_t *);
-extern void locfs_sync(ipc_callid_t, ipc_call_t *);
-extern void locfs_read(ipc_callid_t, ipc_call_t *);
-extern void locfs_write(ipc_callid_t, ipc_call_t *);
-extern void locfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void locfs_close(ipc_callid_t, ipc_call_t *);
-extern void locfs_destroy(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -61,92 +61,4 @@
 };
 
-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, 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);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	
-	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:
-			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)
 {
@@ -165,6 +77,6 @@
 	}
 	
-	int rc = fs_register(vfs_sess, &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);
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -70,24 +70,8 @@
 } 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(service_id_t);
 
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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)
 {
@@ -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,
@@ -433,33 +427,25 @@
 }
 
-void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	service_id_t service_id = (service_id_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, 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(service_id)) {
-		free(opts);
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!tmpfs_instance_init(service_id))
+		return ENOMEM;
 
 	rc = tmpfs_root_get(&rootfn, service_id);
@@ -467,46 +453,24 @@
 	tmpfs_node_t *rootp = TMPFS_NODE(rootfn);
 	if (str_cmp(opts, "restore") == 0) {
-		if (tmpfs_restore(service_id))
-			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)
-{
-	service_id_t service_id = (service_id_t) IPC_GET_ARG1(*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);
-	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)
-{
-	service_id_t service_id = (service_id_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));
-	
+	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.
@@ -518,8 +482,6 @@
 	};
 	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);
@@ -532,6 +494,5 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -556,6 +517,5 @@
 		if (lnk == NULL) {
 			async_answer_0(callid, ENOENT);
-			async_answer_1(rid, ENOENT, 0);
-			return;
+			return ENOENT;
 		}
 
@@ -567,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)
-{
-	service_id_t service_id = (service_id_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.
@@ -589,8 +544,6 @@
 	};
 	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);
@@ -603,6 +556,5 @@
 	if (!async_data_write_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);	
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -612,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;
@@ -627,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. */
@@ -635,14 +587,14 @@
 	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)
-{
-	service_id_t service_id = (service_id_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.
@@ -653,26 +605,17 @@
 	};
 	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) {
@@ -683,18 +626,14 @@
 	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)
-{
-	service_id_t service_id = (service_id_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[] = {
@@ -703,25 +642,12 @@
 	};
 	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)
 {
 	/*
@@ -729,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: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/console/console.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -357,5 +357,5 @@
 		console_serialize_end();
 		
-		if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
+		if (console_kcon()) {
 			prev_console = active_console;
 			active_console = kernel_console;
@@ -711,7 +711,4 @@
 			console_serialize_start();
 			continue;
-		case CONSOLE_KCON_ENABLE:
-			change_console(kernel_console);
-			break;
 		}
 		async_answer_3(callid, EOK, arg1, arg2, arg3);
@@ -833,7 +830,4 @@
 	}
 	
-	/* Disable kernel output to the console */
-	__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
-	
 	/* Initialize the screen */
 	console_serialize_start();
Index: uspace/srv/hid/fb/Makefile
===================================================================
--- uspace/srv/hid/fb/Makefile	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/fb/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -84,11 +84,4 @@
 		EXTRA_CFLAGS += -DNIAGARA_ENABLED
 	endif
-	
-	ifeq ($(MACHINE),serengeti)
-		SOURCES += \
-			sgcn.c \
-			serial_console.c
-		EXTRA_CFLAGS += -DSGCN_ENABLED
-	endif
 endif
 
Index: uspace/srv/hid/fb/main.c
===================================================================
--- uspace/srv/hid/fb/main.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/fb/main.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/fb/niagara.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/fb/niagara.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -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/sgcn.c
===================================================================
--- uspace/srv/hid/fb/sgcn.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/input/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -49,7 +49,5 @@
 	port/ns16550.c \
 	port/pl050.c \
-	port/sgcn.c \
 	port/ski.c \
-	port/z8530.c \
 	proto/adb.c \
 	proto/mousedev.c \
Index: uspace/srv/hid/input/ctl/stty.c
===================================================================
--- uspace/srv/hid/input/ctl/stty.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/input/ctl/stty.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -34,4 +34,6 @@
  * @file
  * @brief Serial TTY-like keyboard controller driver.
+ *
+ * Keyboard emulation on a serial terminal.
  */
 
@@ -63,4 +65,9 @@
 #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 */
@@ -81,4 +88,5 @@
 	0,	KC_MINUS,	0x2d, GSP_END,
 	0,	KC_EQUALS,	0x3d, GSP_END,
+
 	0,	KC_BACKSPACE,	0x08, GSP_END,
 
@@ -216,4 +224,11 @@
 	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
 };
Index: uspace/srv/hid/input/generic/gsp.c
===================================================================
--- uspace/srv/hid/input/generic/gsp.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/input/generic/gsp.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -104,5 +104,5 @@
 		if (key == 0) break;
 
-		/* Insert one sequence. */		
+		/* Insert one sequence. */
 		rc = gsp_insert_seq(p, dp, mods, key);
 		if (rc != 0)
@@ -197,5 +197,6 @@
 
 	if (t == NULL) {
-		printf("gsp_step: not found\n");
+		printf("gsp_step: not found, state=%d, input=0x%x\n",
+		    state, input);
 		*mods = 0;
 		*key = 0;
@@ -205,4 +206,5 @@
 	*mods = t->out_mods;
 	*key = t->out_key;
+
 	return t->new_state;
 }
Index: uspace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/input/generic/input.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -410,5 +410,5 @@
 #endif
 #if defined(MACHINE_msim)
-	kbd_add_dev(&msim_port, &pc_ctl);
+	kbd_add_dev(&msim_port, &stty_ctl);
 #endif
 #if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
@@ -424,9 +424,5 @@
 	kbd_add_dev(&niagara_port, &stty_ctl);
 #endif
-#if defined(UARCH_sparc64) && defined(MACHINE_serengeti)
-	kbd_add_dev(&sgcn_port, &stty_ctl);
-#endif
 #if defined(UARCH_sparc64) && defined(MACHINE_generic)
-	kbd_add_dev(&z8530_port, &sun_ctl);
 	kbd_add_dev(&ns16550_port, &sun_ctl);
 #endif
@@ -556,5 +552,4 @@
 	printf("%s: HelenOS input service\n", NAME);
 	
-	sysarg_t fhc;
 	sysarg_t obio;
 	
@@ -562,6 +557,5 @@
 	list_initialize(&mouse_devs);
 	
-	if (((sysinfo_get_value("kbd.cir.fhc", &fhc) == EOK) && (fhc))
-	    || ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio)))
+	if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio))
 		irc_service = true;
 	
Index: uspace/srv/hid/input/include/kbd_port.h
===================================================================
--- uspace/srv/hid/input/include/kbd_port.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/input/include/kbd_port.h	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -56,7 +56,5 @@
 extern kbd_port_ops_t ns16550_port;
 extern kbd_port_ops_t pl050_port;
-extern kbd_port_ops_t sgcn_port;
 extern kbd_port_ops_t ski_port;
-extern kbd_port_ops_t z8530_port;
 
 #endif
Index: uspace/srv/hid/input/port/niagara.c
===================================================================
--- uspace/srv/hid/input/port/niagara.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hid/input/port/niagara.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -154,5 +154,5 @@
 
 /**
- * Thread to poll SGCN for keypresses.
+ * Thread to poll Niagara console for keypresses.
  */
 static void niagara_thread_impl(void *arg)
Index: pace/srv/hid/input/port/sgcn.c
===================================================================
--- uspace/srv/hid/input/port/sgcn.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,205 +1,0 @@
-/*
- * 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 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>
-
-static int sgcn_port_init(kbd_dev_t *);
-static void sgcn_port_yield(void);
-static void sgcn_port_reclaim(void);
-static void sgcn_port_write(uint8_t data);
-
-kbd_port_ops_t sgcn_port = {
-	.init = sgcn_port_init,
-	.yield = sgcn_port_yield,
-	.reclaim = sgcn_port_reclaim,
-	.write = sgcn_port_write
-};
-
-static kbd_dev_t *kbd_dev;
-
-#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. 
- */
-static int sgcn_port_init(kbd_dev_t *kdev)
-{
-	kbd_dev = kdev;
-	
-	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;
-}
-
-static void sgcn_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-static void sgcn_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-static void sgcn_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_data(kbd_dev, 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/input/port/z8530.c
===================================================================
--- uspace/srv/hid/input/port/z8530.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,152 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * 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 Z8530 keyboard 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 <sys/types.h>
-#include <ddi.h>
-#include <errno.h>
-
-static int z8530_port_init(kbd_dev_t *);
-static void z8530_port_yield(void);
-static void z8530_port_reclaim(void);
-static void z8530_port_write(uint8_t data);
-
-kbd_port_ops_t z8530_port = {
-	.init = z8530_port_init,
-	.yield = z8530_port_yield,
-	.reclaim = z8530_port_reclaim,
-	.write = z8530_port_write
-};
-
-static kbd_dev_t *kbd_dev;
-
-#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
-	}
-};
-
-static 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);
-
-static int z8530_port_init(kbd_dev_t *kdev)
-{
-	kbd_dev = kdev;
-	
-	sysarg_t z8530;
-	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
-		return -1;
-	if (!z8530)
-		return -1;
-	
-	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_port_yield(void)
-{
-}
-
-static void z8530_port_reclaim(void)
-{
-}
-
-static void z8530_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-static void z8530_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/hw/irc/apic/apic.c
===================================================================
--- uspace/srv/hw/irc/apic/apic.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hw/irc/apic/apic.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -42,20 +42,113 @@
 #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/loc.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;
 }
 
@@ -111,4 +204,8 @@
 		return false;
 	}
+
+	if (pio_enable((void *) IO_APIC_BASE, IO_APIC_SIZE,
+	    (void **) &io_apic) != EOK)
+		return false;	
 	
 	async_set_client_connection(apic_connection);
Index: pace/srv/hw/irc/fhc/Makefile
===================================================================
--- uspace/srv/hw/irc/fhc/Makefile	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,161 +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 <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/loc.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.
- * @param arg		Local argument.
- */
-static void fhc_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	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("%s: Error mapping FHC UART registers\n", NAME);
-		return false;
-	}
-	
-	printf("%s: FHC UART registers at %p, %zu bytes\n", NAME,
-	    fhc_uart_phys, fhc_uart_size);
-	
-	async_set_client_connection(fhc_connection);
-	service_register(SERVICE_IRC);
-	
-	return true;
-}
-
-int main(int argc, char **argv)
-{
-	printf("%s: HelenOS FHC bus controller driver\n", NAME);
-	
-	if (!fhc_init())
-		return -1;
-	
-	printf("%s: Accepting connections\n", NAME);
-	task_retval(0);
-	async_manager();
-	
-	/* Never reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: uspace/srv/hw/netif/ne2000/ne2000.c
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/hw/netif/ne2000/ne2000.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -404,5 +404,5 @@
 {
 	/* Start the module */
-	return netif_module_start(SERVICE_ETHERNET);
+	return netif_module_start();
 }
 
Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/loader/Makefile	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -39,6 +39,4 @@
 LINKER_SCRIPT = $(LIBC_PREFIX)/arch/$(UARCH)/_link-loader.ld
 
-EXTRA_CFLAGS = -Iinclude
-
 BINARY = loader
 STATIC_ONLY = y
@@ -46,5 +44,4 @@
 GENERIC_SOURCES = \
 	main.c \
-	elf_load.c \
 	interp.s
 
Index: pace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,482 +1,0 @@
-/*
- * 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 <unistd.h>
-#include <fcntl.h>
-#include <smc.h>
-#include <loader/pcb.h>
-#include <entry_point.h>
-
-#include "elf.h"
-#include "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);
-
-/** 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, 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 = 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 == "/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;
-	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 (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 = my_read(elf->fd, dp, now);
-
-		if (rc < 0) { 
-			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: pace/srv/loader/include/elf.h
===================================================================
--- uspace/srv/loader/include/elf.h	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(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 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ 	(revision )
@@ -1,91 +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"
-
-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;
-
-int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
-    elf_info_t *info);
-void elf_create_pcb(elf_info_t *info, pcb_t *pcb);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/loader/main.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -59,6 +59,6 @@
 #include <str.h>
 #include <as.h>
-#include <elf.h>
-#include <elf_load.h>
+#include <elf/elf.h>
+#include <elf/elf_load.h>
 
 #ifdef CONFIG_RTLD
@@ -348,6 +348,6 @@
 
 	/* Initialize list of loaded modules */
-	list_initialize(&runtime_env->modules_head);
-	list_append(&prog_mod.modules_link, &runtime_env->modules_head);
+	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. */
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/net/net/net.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -479,4 +479,5 @@
 	
 	/* Network interface layer startup */
+	services_t internet_service;
 	if (netif->nil) {
 		setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_MTU, 0);
@@ -486,12 +487,15 @@
 		
 		int mtu = setting ? strtol((char *) setting->value, NULL, 10) : 0;
-		
-		rc = nil_device_req(netif->nil->sess, netif->id, mtu);
+		rc = nil_device_req(netif->nil->sess, netif->id, mtu,
+		    netif->driver->service);
 		if (rc != EOK)
 			return rc;
-	}
+		
+		internet_service = netif->nil->service;
+	} else
+		internet_service = netif->driver->service;
 	
 	/* Inter-network layer startup */
-	rc = ip_device_req(netif->il->sess, netif->id);
+	rc = ip_device_req(netif->il->sess, netif->id, internet_service);
 	if (rc != EOK)
 		return rc;
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/net/netif/lo/lo.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -225,5 +225,5 @@
 {
 	/* Start the module */
-	return netif_module_start(SERVICE_NILDUMMY);
+	return netif_module_start();
 }
 
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 15f3c3fbb3cd87db466db2f9b1379fe5b0794299)
+++ uspace/srv/vfs/vfs_ops.c	(revision 86ffa27f45682aa2a5736f665f400ad262ce5baf)
@@ -76,5 +76,5 @@
 	vfs_node_t *mr_node;
 	fs_index_t rindex;
-	size_t rsize;
+	aoff64_t rsize;
 	unsigned rlnkcnt;
 	async_exch_t *exch;
@@ -146,6 +146,6 @@
 
 			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;
@@ -229,6 +229,7 @@
 	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;
@@ -795,14 +796,14 @@
 	ipc_call_t answer;
 	if (read) {
-		rc = async_data_read_forward_3_1(fs_exch, VFS_OUT_READ,
-		    file->node->service_id, 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_exch, VFS_OUT_WRITE,
-		    file->node->service_id, file->node->index, file->pos,
-		    &answer);
+		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);
 	}
 	
@@ -821,5 +822,6 @@
 		/* 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);
 	}
