Index: uspace/srv/bd/ata_bd/ata_bd.c
===================================================================
--- uspace/srv/bd/ata_bd/ata_bd.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/bd/ata_bd/ata_bd.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -81,7 +81,4 @@
 static const size_t identify_data_size = 512;
 
-/** Size of the communication area. */
-static size_t comm_size;
-
 /** I/O base address of the command registers. */
 static uintptr_t cmd_physical;
@@ -105,5 +102,5 @@
 static void print_syntax(void);
 static int ata_bd_init(void);
-static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
 static int ata_bd_read_blocks(int disk_id, uint64_t ba, size_t cnt,
     void *buf);
@@ -274,5 +271,5 @@
 
 /** Block device connection handler */
-static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void ata_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	void *fs_va = NULL;
@@ -281,4 +278,5 @@
 	sysarg_t method;
 	devmap_handle_t dh;
+	size_t comm_size;	/**< Size of the communication area. */
 	unsigned int flags;
 	int retval;
@@ -317,12 +315,15 @@
 	(void) async_share_out_finalize(callid, fs_va);
 
-	while (1) {
+	while (true) {
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -66,5 +66,5 @@
 static void print_usage(void);
 static int file_bd_init(const char *fname);
-static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
 static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf);
 static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
@@ -170,5 +170,5 @@
 }
 
-static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	void *fs_va = NULL;
@@ -198,12 +198,15 @@
 	(void) async_share_out_finalize(callid, fs_va);
 
-	while (1) {
+	while (true) {
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
Index: uspace/srv/bd/gxe_bd/gxe_bd.c
===================================================================
--- uspace/srv/bd/gxe_bd/gxe_bd.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -97,5 +97,5 @@
 
 static int gxe_bd_init(void);
-static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
 static int gxe_bd_read_blocks(int disk_id, uint64_t ba, unsigned cnt,
     void *buf);
@@ -153,5 +153,5 @@
 }
 
-static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	void *fs_va = NULL;
@@ -201,12 +201,15 @@
 	(void) async_share_out_finalize(callid, fs_va);
 
-	while (1) {
+	while (true) {
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
Index: uspace/srv/bd/part/guid_part/guid_part.c
===================================================================
--- uspace/srv/bd/part/guid_part/guid_part.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/bd/part/guid_part/guid_part.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -99,5 +99,5 @@
 static part_t *gpt_part_new(void);
 static void gpt_pte_to_part(const gpt_entry_t *pte, part_t *part);
-static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static int gpt_bd_read(part_t *p, aoff64_t ba, size_t cnt, void *buf);
 static int gpt_bd_write(part_t *p, aoff64_t ba, size_t cnt, const void *buf);
@@ -139,5 +139,5 @@
 	}
 
-	rc = block_init(indev_handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, indev_handle, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": could not init libblock.\n");
@@ -307,5 +307,5 @@
 }
 
-static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void gpt_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	size_t comm_size;
@@ -356,12 +356,15 @@
 	(void) async_share_out_finalize(callid, fs_va);
 
-	while (1) {
+	while (true) {
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
Index: uspace/srv/bd/part/mbr_part/mbr_part.c
===================================================================
--- uspace/srv/bd/part/mbr_part/mbr_part.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/bd/part/mbr_part/mbr_part.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -150,5 +150,5 @@
 static part_t *mbr_part_new(void);
 static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part);
-static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf);
 static int mbr_bd_write(part_t *p, uint64_t ba, size_t cnt, const void *buf);
@@ -190,5 +190,5 @@
 	}
 
-	rc = block_init(indev_handle, 2048);
+	rc = block_init(EXCHANGE_SERIALIZE, indev_handle, 2048);
 	if (rc != EOK)  {
 		printf(NAME ": could not init libblock.\n");
@@ -385,5 +385,5 @@
 }
 
-static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	size_t comm_size;
@@ -437,9 +437,12 @@
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
Index: uspace/srv/bd/rd/Makefile
===================================================================
--- uspace/srv/bd/rd/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/bd/rd/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../../..
 BINARY = rd
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/bd/rd/rd.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -84,5 +84,5 @@
  * @param icall Call data of the request that opened the connection.
  */
-static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void rd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -123,12 +123,15 @@
 	while (true) {
 		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!IPC_GET_IMETHOD(call)) {
 			/*
 			 * The other side has hung up.
-			 * Answer the message and exit the fibril.
+			 * Exit the fibril.
 			 */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
@@ -243,5 +246,5 @@
 		return false;
 	}
-
+	
 	fibril_rwlock_initialize(&rd_lock);
 	
@@ -258,5 +261,5 @@
 	printf("%s: Accepting connections\n", NAME);
 	async_manager();
-
+	
 	/* Never reached */
 	return 0;
Index: uspace/srv/clip/clip.c
===================================================================
--- uspace/srv/clip/clip.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/clip/clip.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -30,5 +30,5 @@
 #include <bool.h>
 #include <async.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <ipc/services.h>
 #include <ipc/clipboard.h>
@@ -148,18 +148,17 @@
 }
 
-static void clip_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void clip_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	/* Accept connection */
 	async_answer_0(iid, EOK);
 	
-	bool cont = true;
-	while (cont) {
+	while (true) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case CLIPBOARD_PUT_DATA:
 			clip_put_data(callid, &call);
@@ -179,5 +178,5 @@
 int main(int argc, char *argv[])
 {
-	printf(NAME ": HelenOS clipboard service\n");
+	printf("%s: HelenOS clipboard service\n", NAME);
 	
 	async_set_client_connection(clip_connection);
@@ -186,5 +185,6 @@
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
 	
Index: uspace/srv/devman/Makefile
===================================================================
--- uspace/srv/devman/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devman/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../..
 BINARY = devman
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devman/devman.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -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);
@@ -466,6 +467,5 @@
 	fibril_mutex_lock(&drivers_list->drivers_mutex);
 	
-	link_t *link = drivers_list->drivers.next;
-	while (link != &drivers_list->drivers) {
+	list_foreach(drivers_list->drivers, link) {
 		drv = list_get_instance(link, driver_t, drivers);
 		score = get_match_score(drv, node);
@@ -474,5 +474,4 @@
 			best_drv = drv;
 		}
-		link = link->next;
 	}
 	
@@ -536,10 +535,8 @@
 	driver_t *res = NULL;
 	driver_t *drv = NULL;
-	link_t *link;
 	
 	fibril_mutex_lock(&drv_list->drivers_mutex);
 	
-	link = drv_list->drivers.next;
-	while (link != &drv_list->drivers) {
+	list_foreach(drv_list->drivers, link) {
 		drv = list_get_instance(link, driver_t, drivers);
 		if (str_cmp(drv->name, drv_name) == 0) {
@@ -547,6 +544,4 @@
 			break;
 		}
-
-		link = link->next;
 	}
 	
@@ -564,5 +559,4 @@
 	dev_node_t *dev;
 	link_t *link;
-	int phone;
 
 	log_msg(LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")",
@@ -570,8 +564,11 @@
 
 	fibril_mutex_lock(&driver->driver_mutex);
-
-	phone = async_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0);
-
-	if (phone < 0) {
+	
+	async_exch_t *exch = async_exchange_begin(driver->sess);
+	async_sess_t *sess = async_connect_me_to(EXCHANGE_SERIALIZE, exch,
+	    DRIVER_DEVMAN, 0, 0);
+	async_exchange_end(exch);
+
+	if (!sess) {
 		fibril_mutex_unlock(&driver->driver_mutex);
 		return;
@@ -582,6 +579,6 @@
 	 * that has not been passed to the driver.
 	 */
-	link = driver->devices.next;
-	while (link != &driver->devices) {
+	link = driver->devices.head.next;
+	while (link != &driver->devices.head) {
 		dev = list_get_instance(link, dev_node_t, driver_devices);
 		if (dev->passed_to_driver) {
@@ -602,5 +599,5 @@
 		fibril_mutex_unlock(&driver->driver_mutex);
 
-		add_device(phone, driver, dev, tree);
+		add_device(sess, driver, dev, tree);
 
 		/*
@@ -620,8 +617,8 @@
 		 * Restart the cycle to go through all devices again.
 		 */
-		link = driver->devices.next;
-	}
-
-	async_hangup(phone);
+		link = driver->devices.head.next;
+	}
+
+	async_hangup(sess);
 
 	/*
@@ -673,5 +670,5 @@
 	list_initialize(&drv->devices);
 	fibril_mutex_initialize(&drv->driver_mutex);
-	drv->phone = -1;
+	drv->sess = NULL;
 }
 
@@ -737,5 +734,6 @@
  * @param node		The device's node in the device tree.
  */
-void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
+void add_device(async_sess_t *sess, driver_t *drv, dev_node_t *dev,
+    dev_tree_t *tree)
 {
 	/*
@@ -746,7 +744,4 @@
 	    drv->name, dev->pfun->name);
 	
-	sysarg_t rc;
-	ipc_call_t answer;
-	
 	/* Send the device to the driver. */
 	devman_handle_t parent_handle;
@@ -756,11 +751,17 @@
 		parent_handle = 0;
 	}
-
-	aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle,
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, DRIVER_ADD_DEVICE, dev->handle,
 	    parent_handle, &answer);
 	
-	/* Send the device's name to the driver. */
-	rc = async_data_write_start(phone, dev->pfun->name,
+	/* Send the device name to the driver. */
+	sysarg_t rc = async_data_write_start(exch, dev->pfun->name,
 	    str_size(dev->pfun->name) + 1);
+	
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
 		/* TODO handle error */
@@ -823,8 +824,12 @@
 	if (is_running) {
 		/* Notify the driver about the new device. */
-		int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);
-		if (phone >= 0) {
-			add_device(phone, drv, dev, tree);
-			async_hangup(phone);
+		async_exch_t *exch = async_exchange_begin(drv->sess);
+		async_sess_t *sess = async_connect_me_to(EXCHANGE_SERIALIZE, exch,
+		    DRIVER_DEVMAN, 0, 0);
+		async_exchange_end(exch);
+		
+		if (sess) {
+			add_device(sess, drv, dev, tree);
+			async_hangup(sess);
 		}
 	}
@@ -1177,9 +1182,6 @@
 
 	fun_node_t *fun;
-	link_t *link;
-
-	for (link = dev->functions.next;
-	    link != &dev->functions;
-	    link = link->next) {
+
+	list_foreach(dev->functions, link) {
 		fun = list_get_instance(link, fun_node_t, dev_functions);
 
@@ -1375,12 +1377,10 @@
 {
 	dev_class_t *cl;
-	link_t *link = class_list->classes.next;
-	
-	while (link != &class_list->classes) {
+	
+	list_foreach(class_list->classes, link) {
 		cl = list_get_instance(link, dev_class_t, link);
 		if (str_cmp(cl->name, class_name) == 0) {
 			return cl;
 		}
-		link = link->next;
 	}
 	
@@ -1398,8 +1398,5 @@
 	assert(dev_name != NULL);
 
-	link_t *link;
-	for (link = dev_class->devices.next;
-	    link != &dev_class->devices;
-	    link = link->next) {
+	list_foreach(dev_class->devices, link) {
 		dev_class_info_t *dev = list_get_instance(link,
 		    dev_class_info_t, link);
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devman/devman.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -44,4 +44,5 @@
 #include <fibril_synch.h>
 #include <atomic.h>
+#include <async.h>
 
 #include "util.h"
@@ -87,6 +88,6 @@
 	int state;
 	
-	/** Phone asociated with this driver. */
-	int phone;
+	/** Session asociated with this driver. */
+	async_sess_t *sess;
 	/** Name of the device driver. */
 	char *name;
@@ -95,9 +96,9 @@
 	/** List of device ids for device-to-driver matching. */
 	match_id_list_t match_ids;
-	/** Pointer to the linked list of devices controlled by this driver. */
-	link_t devices;
-	
-	/**
-	 * Fibril mutex for this driver - driver state, list of devices, phone.
+	/** List of devices controlled by this driver. */
+	list_t devices;
+	
+	/**
+	 * Fibril mutex for this driver - driver state, list of devices, session.
 	 */
 	fibril_mutex_t driver_mutex;
@@ -107,5 +108,5 @@
 typedef struct driver_list {
 	/** List of drivers */
-	link_t drivers;
+	list_t drivers;
 	/** Fibril mutex for list of drivers. */
 	fibril_mutex_t drivers_mutex;
@@ -129,5 +130,5 @@
 	
 	/** List of device functions. */
-	link_t functions;
+	list_t functions;
 	/** Driver of this device. */
 	driver_t *drv;
@@ -169,6 +170,6 @@
 	match_id_list_t match_ids;
 	
-	/** The list of device classes to which this device function belongs. */
-	link_t classes;
+	/** List of device classes to which this device function belongs. */
+	list_t classes;
 	/** Devmap handle if the device function is registered by devmap. */
 	devmap_handle_t devmap_handle;
@@ -227,5 +228,5 @@
 	 * this class.
 	 */
-	link_t devices;
+	list_t devices;
 	
 	/**
@@ -279,5 +280,5 @@
 typedef struct class_list {
 	/** List of classes. */
-	link_t classes;
+	list_t classes;
 	
 	/**
@@ -312,5 +313,5 @@
 extern void add_driver(driver_list_t *, driver_t *);
 extern void attach_driver(dev_node_t *, driver_t *);
-extern void add_device(int, driver_t *, dev_node_t *, dev_tree_t *);
+extern void add_device(async_sess_t *, driver_t *, dev_node_t *, dev_tree_t *);
 extern bool start_driver(driver_t *);
 
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devman/main.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -39,5 +39,5 @@
 #include <assert.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <stdio.h>
@@ -108,5 +108,5 @@
 	fibril_mutex_lock(&driver->driver_mutex);
 	
-	if (driver->phone >= 0) {
+	if (driver->sess) {
 		/* We already have a connection to the driver. */
 		log_msg(LVL_ERROR, "Driver '%s' already started.\n",
@@ -128,5 +128,5 @@
 		break;
 	case DRIVER_RUNNING:
-		/* Should not happen since we do not have a connected phone */
+		/* Should not happen since we do not have a connected session */
 		assert(false);
 	}
@@ -135,23 +135,17 @@
 	log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.",
 	    driver->name);
-	ipc_call_t call;
-	ipc_callid_t callid = async_get_call(&call);
-	if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
+	driver->sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (!driver->sess) {
 		fibril_mutex_unlock(&driver->driver_mutex);
-		async_answer_0(callid, ENOTSUP);
 		async_answer_0(iid, ENOTSUP);
 		return NULL;
 	}
 	
-	/* Remember driver's phone. */
-	driver->phone = IPC_GET_ARG5(call);
-	
 	fibril_mutex_unlock(&driver->driver_mutex);
 	
-	log_msg(LVL_NOTE, 
+	log_msg(LVL_NOTE,
 	    "The `%s' driver was successfully registered as running.",
 	    driver->name);
 	
-	async_answer_0(callid, EOK);
 	async_answer_0(iid, EOK);
 	
@@ -434,14 +428,12 @@
 	fibril_add_ready(fid);
 	
-	ipc_callid_t callid;
-	ipc_call_t call;
-	bool cont = true;
-	while (cont) {
-		callid = async_get_call(&call);
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			break;
 		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case DEVMAN_ADD_FUNCTION:
 			devman_add_function(callid, &call);
@@ -515,4 +507,41 @@
 }
 
+/** Find device path by its handle. */
+static void devman_get_device_path_by_handle(ipc_callid_t iid,
+    ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	size_t sent_length = str_size(fun->pathname);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->pathname, sent_length);
+	async_answer_0(iid, EOK);
+
+	free(buffer);
+}
+
 
 /** Function for handling connections from a client to the device manager. */
@@ -522,13 +551,12 @@
 	async_answer_0(iid, EOK);
 	
-	bool cont = true;
-	while (cont) {
+	while (true) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case DEVMAN_DEVICE_GET_HANDLE:
 			devman_function_get_handle(callid, &call);
@@ -536,4 +564,7 @@
 		case DEVMAN_DEVICE_GET_HANDLE_BY_CLASS:
 			devman_function_get_handle_by_class(callid, &call);
+			break;
+		case DEVMAN_DEVICE_GET_DEVICE_PATH:
+			devman_get_device_path_by_handle(callid, &call);
 			break;
 		default:
@@ -606,8 +637,7 @@
 		method = DRIVER_CLIENT;
 	
-	if (driver->phone < 0) {
-		log_msg(LVL_ERROR, 
-		    "Could not forward to driver `%s' (phone is %d).",
-		    driver->name, (int) driver->phone);
+	if (!driver->sess) {
+		log_msg(LVL_ERROR,
+		    "Could not forward to driver `%s'.", driver->name);
 		async_answer_0(iid, EINVAL);
 		return;
@@ -623,6 +653,8 @@
 		    dev->pfun->pathname, driver->name);
 	}
-
-	async_forward_fast(iid, driver->phone, method, fwd_h, 0, IPC_FF_NONE);
+	
+	async_exch_t *exch = async_exchange_begin(driver->sess);
+	async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE);
+	async_exchange_end(exch);
 }
 
@@ -646,12 +678,15 @@
 	dev = fun->dev;
 	
-	if (dev->state != DEVICE_USABLE || dev->drv->phone < 0) {
+	if ((dev->state != DEVICE_USABLE) || (!dev->drv->sess)) {
 		async_answer_0(iid, EINVAL);
 		return;
 	}
 	
-	async_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, fun->handle, 0,
+	async_exch_t *exch = async_exchange_begin(dev->drv->sess);
+	async_forward_fast(iid, exch, DRIVER_CLIENT, fun->handle, 0,
 	    IPC_FF_NONE);
-	log_msg(LVL_DEBUG, 
+	async_exchange_end(exch);
+	
+	log_msg(LVL_DEBUG,
 	    "Forwarding devmapper request for `%s' function to driver `%s'.",
 	    fun->pathname, dev->drv->name);
@@ -659,5 +694,5 @@
 
 /** Function for handling connections to device manager. */
-static void devman_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	/* Select interface. */
@@ -745,4 +780,5 @@
 
 	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
 	async_manager();
 
Index: uspace/srv/devman/match.c
===================================================================
--- uspace/srv/devman/match.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devman/match.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -59,9 +59,11 @@
 int get_match_score(driver_t *drv, dev_node_t *dev)
 {
-	link_t *drv_head = &drv->match_ids.ids;
-	link_t *dev_head = &dev->pfun->match_ids.ids;
+	link_t *drv_head = &drv->match_ids.ids.head;
+	link_t *dev_head = &dev->pfun->match_ids.ids.head;
 	
-	if (list_empty(drv_head) || list_empty(dev_head))
+	if (list_empty(&drv->match_ids.ids) ||
+	    list_empty(&dev->pfun->match_ids.ids)) {
 		return 0;
+	}
 	
 	/*
@@ -70,5 +72,5 @@
 	int highest_score = 0;
 	
-	link_t *drv_link = drv->match_ids.ids.next;
+	link_t *drv_link = drv->match_ids.ids.head.next;
 	while (drv_link != drv_head) {
 		link_t *dev_link = dev_head->next;
Index: uspace/srv/devman/util.c
===================================================================
--- uspace/srv/devman/util.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devman/util.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -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 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devman/util.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -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/devmap/Makefile
===================================================================
--- uspace/srv/devmap/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devmap/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../..
 BINARY = devmap
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/devmap/devmap.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -37,5 +37,5 @@
 
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <stdio.h>
@@ -57,12 +57,16 @@
  */
 typedef struct {
-	/** Pointers to previous and next drivers in linked list */
+	/** Link to drivers_list */
 	link_t drivers;
-	/** Pointer to the linked list of devices controlled by this driver */
-	link_t devices;
-	/** Phone asociated with this driver */
-	sysarg_t phone;
+	
+	/** List of devices controlled by this driver */
+	list_t devices;
+	
+	/** Session asociated with this driver */
+	async_sess_t *sess;
+	
 	/** Device driver name */
 	char *name;
+	
 	/** Fibril mutex for list of devices owned by this driver */
 	fibril_mutex_t devices_mutex;
@@ -73,10 +77,13 @@
  */
 typedef struct {
-	/** Pointer to the previous and next device in the list of all namespaces */
+	/** Link to namespaces_list */
 	link_t namespaces;
+	
 	/** Unique namespace identifier */
 	devmap_handle_t handle;
+	
 	/** Namespace name */
 	char *name;
+	
 	/** Reference count */
 	size_t refcnt;
@@ -87,8 +94,7 @@
  */
 typedef struct {
-	/** Pointer to the previous and next device in the list of all devices */
+	/** Link to global list of devices (devices_list) */
 	link_t devices;
-	/** Pointer to the previous and next device in the list of devices
-	    owned by one driver */
+	/** Link to driver list of devices (devmap_driver_t.devices) */
 	link_t driver_devices;
 	/** Unique device identifier */
@@ -218,9 +224,7 @@
 static devmap_namespace_t *devmap_namespace_find_name(const char *name)
 {
-	link_t *item;
-	
 	assert(fibril_mutex_is_locked(&devices_list_mutex));
 	
-	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
+	list_foreach(namespaces_list, item) {
 		devmap_namespace_t *namespace =
 		    list_get_instance(item, devmap_namespace_t, namespaces);
@@ -239,9 +243,7 @@
 static devmap_namespace_t *devmap_namespace_find_handle(devmap_handle_t handle)
 {
-	link_t *item;
-	
 	assert(fibril_mutex_is_locked(&devices_list_mutex));
 	
-	for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
+	list_foreach(namespaces_list, item) {
 		devmap_namespace_t *namespace =
 		    list_get_instance(item, devmap_namespace_t, namespaces);
@@ -257,9 +259,7 @@
     const char *name)
 {
-	link_t *item;
-	
 	assert(fibril_mutex_is_locked(&devices_list_mutex));
 	
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
+	list_foreach(devices_list, item) {
 		devmap_device_t *device =
 		    list_get_instance(item, devmap_device_t, devices);
@@ -279,9 +279,7 @@
 static devmap_device_t *devmap_device_find_handle(devmap_handle_t handle)
 {
-	link_t *item;
-	
 	assert(fibril_mutex_is_locked(&devices_list_mutex));
 	
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
+	list_foreach(devices_list, item) {
 		devmap_device_t *device =
 		    list_get_instance(item, devmap_device_t, devices);
@@ -405,17 +403,11 @@
 	 * Create connection to the driver
 	 */
-	ipc_call_t call;
-	ipc_callid_t callid = async_get_call(&call);
-	
-	if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
+	driver->sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (!driver->sess) {
 		free(driver->name);
 		free(driver);
-		async_answer_0(callid, ENOTSUP);
 		async_answer_0(iid, ENOTSUP);
 		return NULL;
 	}
-	
-	driver->phone = IPC_GET_ARG5(call);
-	async_answer_0(callid, EOK);
 	
 	/*
@@ -462,6 +454,6 @@
 	fibril_mutex_lock(&drivers_list_mutex);
 	
-	if (driver->phone != 0)
-		async_hangup(driver->phone);
+	if (driver->sess)
+		async_hangup(driver->sess);
 	
 	/* Remove it from list of drivers */
@@ -472,7 +464,8 @@
 	fibril_mutex_lock(&driver->devices_mutex);
 	
-	while (!list_empty(&(driver->devices))) {
-		devmap_device_t *device = list_get_instance(driver->devices.next,
-		    devmap_device_t, driver_devices);
+	while (!list_empty(&driver->devices)) {
+		devmap_device_t *device = list_get_instance(
+		    list_first(&driver->devices), devmap_device_t,
+		    driver_devices);
 		devmap_device_unregister_core(device);
 	}
@@ -607,5 +600,5 @@
 	devmap_device_t *dev = devmap_device_find_handle(handle);
 	
-	if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
+	if ((dev == NULL) || (dev->driver == NULL) || (!dev->driver->sess)) {
 		fibril_mutex_unlock(&devices_list_mutex);
 		async_answer_0(callid, ENOENT);
@@ -613,13 +606,13 @@
 	}
 	
-	if (dev->forward_interface == 0) {
-		async_forward_fast(callid, dev->driver->phone,
-		    dev->handle, 0, 0,
-		    IPC_FF_NONE);
-	} else {
-		async_forward_fast(callid, dev->driver->phone,
-		    dev->forward_interface, dev->handle, 0,
-		    IPC_FF_NONE);
-	}
+	async_exch_t *exch = async_exchange_begin(dev->driver->sess);
+	
+	if (dev->forward_interface == 0)
+		async_forward_fast(callid, exch, dev->handle, 0, 0, IPC_FF_NONE);
+	else
+		async_forward_fast(callid, exch, dev->forward_interface,
+		    dev->handle, 0, IPC_FF_NONE);
+	
+	async_exchange_end(exch);
 	
 	fibril_mutex_unlock(&devices_list_mutex);
@@ -814,8 +807,6 @@
 	}
 	
-	link_t *item;
 	size_t pos = 0;
-	for (item = namespaces_list.next; item != &namespaces_list;
-	    item = item->next) {
+	list_foreach(namespaces_list, item) {
 		devmap_namespace_t *namespace =
 		    list_get_instance(item, devmap_namespace_t, namespaces);
@@ -880,7 +871,6 @@
 	}
 	
-	link_t *item;
 	size_t pos = 0;
-	for (item = devices_list.next; item != &devices_list; item = item->next) {
+	list_foreach(devices_list, item) {
 		devmap_device_t *device =
 		    list_get_instance(item, devmap_device_t, devices);
@@ -1029,13 +1019,12 @@
 		return;
 	
-	bool cont = true;
-	while (cont) {
+	while (true) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case DEVMAP_DRIVER_UNREGISTER:
 			if (NULL == driver)
@@ -1080,13 +1069,12 @@
 	async_answer_0(iid, EOK);
 	
-	bool cont = true;
-	while (cont) {
+	while (true) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			cont = false;
-			continue;
 		case DEVMAP_DEVICE_GET_HANDLE:
 			devmap_device_get_handle(callid, &call);
@@ -1125,5 +1113,5 @@
  *
  */
-static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	/* Select interface */
Index: uspace/srv/fs/devfs/Makefile
===================================================================
--- uspace/srv/fs/devfs/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/devfs/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -32,4 +32,5 @@
 EXTRA_CFLAGS += -I$(LIBFS_PREFIX)
 BINARY = devfs
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/fs/devfs/devfs.c
===================================================================
--- uspace/srv/fs/devfs/devfs.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/devfs/devfs.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -41,5 +41,5 @@
 #include <stdio.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <errno.h>
@@ -57,87 +57,28 @@
 };
 
-fs_reg_t devfs_reg;
-
-static void devfs_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (iid)
-		async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		switch  (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			return;
-		case VFS_OUT_MOUNTED:
-			devfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			devfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			devfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			devfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			devfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			devfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			devfs_stat(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			devfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			devfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			devfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			devfs_close(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			devfs_sync(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			devfs_destroy(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char *argv[])
 {
-	printf(NAME ": HelenOS Device Filesystem\n");
+	printf("%s: HelenOS Device Filesystem\n", NAME);
 	
 	if (!devfs_init()) {
-		printf(NAME ": failed to initialize devfs\n");
+		printf("%s: failed to initialize devfs\n", NAME);
 		return -1;
 	}
 	
-	int vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
-	if (vfs_phone < EOK) {
-		printf(NAME ": Unable to connect to VFS\n");
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
+		printf("%s: Unable to connect to VFS\n", NAME);
 		return -1;
 	}
 	
-	int rc = fs_register(vfs_phone, &devfs_reg, &devfs_vfs_info,
-	    devfs_connection);
+	int rc = fs_register(vfs_sess, &devfs_vfs_info, &devfs_ops,
+	    &devfs_libfs_ops);
 	if (rc != EOK) {
-		printf(NAME ": Failed to register file system (%d)\n", rc);
+		printf("%s: Failed to register file system (%d)\n", NAME, rc);
 		return rc;
 	}
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
 	task_retval(0);
 	async_manager();
@@ -150,2 +91,3 @@
  * @}
  */
+
Index: uspace/srv/fs/devfs/devfs.h
===================================================================
--- uspace/srv/fs/devfs/devfs.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/devfs/devfs.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -36,5 +36,6 @@
 #include <libfs.h>
 
-extern fs_reg_t devfs_reg;
+extern vfs_out_ops_t devfs_ops;
+extern libfs_ops_t devfs_libfs_ops;
 
 #endif
Index: uspace/srv/fs/devfs/devfs_ops.c
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/devfs/devfs_ops.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -59,8 +59,8 @@
 typedef struct {
 	devmap_handle_t handle;
-	int phone;		/**< When < 0, the structure is incomplete. */
+	async_sess_t *sess;       /**< If NULL, the structure is incomplete. */
 	size_t refcount;
 	link_t link;
-	fibril_condvar_t cv;	/**< Broadcast when completed. */
+	fibril_condvar_t cv;      /**< Broadcast when completed. */
 } device_t;
 
@@ -232,5 +232,5 @@
 		};
 		link_t *lnk;
-
+		
 		fibril_mutex_lock(&devices_mutex);
 restart:
@@ -244,8 +244,10 @@
 			
 			dev->handle = node->handle;
-			dev->phone = -1;	/* mark as incomplete */
+			
+			/* Mark as incomplete */
+			dev->sess = NULL;
 			dev->refcount = 1;
 			fibril_condvar_initialize(&dev->cv);
-
+			
 			/*
 			 * Insert the incomplete device structure so that other
@@ -254,14 +256,15 @@
 			 */
 			hash_table_insert(&devices, key, &dev->link);
-
+			
 			/*
 			 * Drop the mutex to allow recursive devfs requests.
 			 */
 			fibril_mutex_unlock(&devices_mutex);
-
-			int phone = devmap_device_connect(node->handle, 0);
-
+			
+			async_sess_t *sess = devmap_device_connect(EXCHANGE_SERIALIZE,
+			    node->handle, 0);
+			
 			fibril_mutex_lock(&devices_mutex);
-
+			
 			/*
 			 * Notify possible waiters about this device structure
@@ -269,6 +272,6 @@
 			 */
 			fibril_condvar_broadcast(&dev->cv);
-
-			if (phone < 0) {
+			
+			if (!sess) {
 				/*
 				 * Connecting failed, need to remove the
@@ -277,14 +280,14 @@
 				hash_table_remove(&devices, key, DEVICES_KEYS);
 				fibril_mutex_unlock(&devices_mutex);
-
+				
 				return ENOENT;
 			}
 			
-			/* Set the correct phone. */
-			dev->phone = phone;
+			/* Set the correct session. */
+			dev->sess = sess;
 		} else {
 			device_t *dev = hash_table_get_instance(lnk, device_t, link);
-
-			if (dev->phone < 0) {
+			
+			if (!dev->sess) {
 				/*
 				 * Wait until the device structure is completed
@@ -398,9 +401,4 @@
 	
 	return 1;
-}
-
-static char devfs_plb_get_char(unsigned pos)
-{
-	return devfs_reg.plb_ro[pos % PLB_SIZE];
 }
 
@@ -444,5 +442,4 @@
 	.size_get = devfs_size_get,
 	.lnkcnt_get = devfs_lnkcnt_get,
-	.plb_get_char = devfs_plb_get_char,
 	.is_directory = devfs_is_directory,
 	.is_file = devfs_is_file,
@@ -459,56 +456,22 @@
 }
 
-void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	char *opts;
-	
-	/* Accept the mount options */
-	sysarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
-	    0, NULL);
-	if (retval != EOK) {
-		async_answer_0(rid, retval);
-		return;
-	}
-	
-	free(opts);
-	async_answer_3(rid, EOK, 0, 0, 0);
-}
-
-void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void devfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&devfs_libfs_ops, rid, request);
-}
-
-void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
-}
-
-void devfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+static int devfs_mounted(devmap_handle_t devmap_handle, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	*index = 0;
+	*size = 0;
+	*lnkcnt = 0;
+	return EOK;
+}
+
+static int devfs_unmounted(devmap_handle_t devmap_handle)
+{
+	return ENOTSUP;
+}
+
+static int
+devfs_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	if (index == 0) {
 		ipc_callid_t callid;
@@ -516,6 +479,5 @@
 		if (!async_data_read_receive(&callid, &size)) {
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -537,6 +499,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;
 		}
 		
@@ -552,6 +514,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;
 			}
 			
@@ -560,6 +522,5 @@
 		
 		async_answer_0(callid, ENOENT);
-		async_answer_1(rid, ENOENT, 0);
-		return;
+		return ENOENT;
 	}
 	
@@ -572,6 +533,5 @@
 		if (!async_data_read_receive(&callid, &size)) {
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
@@ -582,12 +542,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;
 	}
 	
@@ -603,10 +562,9 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->phone >= 0);
+		assert(dev->sess);
 		
 		ipc_callid_t callid;
@@ -614,16 +572,19 @@
 			fibril_mutex_unlock(&devices_mutex);
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
 		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
 		ipc_call_t answer;
-		aid_t msg = async_send_3(dev->phone, 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, devmap_handle,
+		    index, LOWER32(pos), UPPER32(pos), &answer);
 		
 		/* Forward the IPC_M_DATA_READ request to the driver */
-		async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		
+		async_exchange_end(exch);
+		
 		fibril_mutex_unlock(&devices_mutex);
 		
@@ -631,21 +592,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 devfs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	if (index == 0) {
-		async_answer_0(rid, ENOTSUP);
-		return;
-	}
+		
+		*rbytes = IPC_GET_ARG1(answer);
+		return rc;
+	}
+	
+	return ENOENT;
+}
+
+static int
+devfs_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	if (index == 0)
+		return ENOTSUP;
 	
 	devmap_handle_type_t type = devmap_handle_probe(index);
@@ -653,6 +611,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, ENOTSUP);
-		return;
+		return ENOTSUP;
 	}
 	
@@ -667,10 +624,9 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->phone >= 0);
+		assert(dev->sess);
 		
 		ipc_callid_t callid;
@@ -678,16 +634,18 @@
 			fibril_mutex_unlock(&devices_mutex);
 			async_answer_0(callid, EINVAL);
-			async_answer_0(rid, EINVAL);
-			return;
+			return EINVAL;
 		}
 		
 		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
 		ipc_call_t answer;
-		aid_t msg = async_send_3(dev->phone, 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, devmap_handle,
+		    index, LOWER32(pos), UPPER32(pos), &answer);
 		
 		/* Forward the IPC_M_DATA_WRITE request to the driver */
-		async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+		
+		async_exchange_end(exch);
 		
 		fibril_mutex_unlock(&devices_mutex);
@@ -696,27 +654,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 devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
-
-void devfs_close(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	if (index == 0) {
-		async_answer_0(rid, EOK);
-		return;
-	}
+		
+		*wbytes = IPC_GET_ARG1(answer);
+		*nsize = 0;
+		return rc;
+	}
+	
+	return ENOENT;
+}
+
+static int
+devfs_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size)
+{
+	return ENOTSUP;
+}
+
+static int devfs_close(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	if (index == 0)
+		return EOK;
 	
 	devmap_handle_type_t type = devmap_handle_probe(index);
@@ -724,6 +678,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
+		return EOK;
 	}
 	
@@ -737,14 +690,13 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->phone >= 0);
+		assert(dev->sess);
 		dev->refcount--;
 		
 		if (dev->refcount == 0) {
-			async_hangup(dev->phone);
+			async_hangup(dev->sess);
 			hash_table_remove(&devices, key, DEVICES_KEYS);
 		}
@@ -752,19 +704,14 @@
 		fibril_mutex_unlock(&devices_mutex);
 		
-		async_answer_0(rid, EOK);
-		return;
-	}
-	
-	async_answer_0(rid, ENOENT);
-}
-
-void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	
-	if (index == 0) {
-		async_answer_0(rid, EOK);
-		return;
-	}
+		return EOK;
+	}
+	
+	return ENOENT;
+}
+
+static int devfs_sync(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	if (index == 0)
+		return EOK;
 	
 	devmap_handle_type_t type = devmap_handle_probe(index);
@@ -772,6 +719,5 @@
 	if (type == DEV_HANDLE_NAMESPACE) {
 		/* Namespace directory */
-		async_answer_0(rid, EOK);
-		return;
+		return EOK;
 	}
 	
@@ -785,15 +731,18 @@
 		if (lnk == NULL) {
 			fibril_mutex_unlock(&devices_mutex);
-			async_answer_0(rid, ENOENT);
-			return;
+			return ENOENT;
 		}
 		
 		device_t *dev = hash_table_get_instance(lnk, device_t, link);
-		assert(dev->phone >= 0);
+		assert(dev->sess);
 		
 		/* Make a request at the driver */
+		async_exch_t *exch = async_exchange_begin(dev->sess);
+		
 		ipc_call_t answer;
-		aid_t msg = async_send_2(dev->phone, IPC_GET_IMETHOD(*request),
-		    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
+		aid_t msg = async_send_2(exch, VFS_OUT_SYNC, devmap_handle,
+		    index, &answer);
+		
+		async_exchange_end(exch);
 		
 		fibril_mutex_unlock(&devices_mutex);
@@ -803,16 +752,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 devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
-{
-	async_answer_0(rid, ENOTSUP);
-}
+		return rc;
+	}
+	
+	return  ENOENT;
+}
+
+static int devfs_destroy(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	return ENOTSUP;
+}
+
+vfs_out_ops_t devfs_ops = {
+	.mounted = devfs_mounted,
+	.unmounted = devfs_unmounted,
+	.read = devfs_read,
+	.write = devfs_write,
+	.truncate = devfs_truncate,
+	.close = devfs_close,
+	.destroy = devfs_destroy,
+	.sync = devfs_sync,
+};
 
 /**
Index: uspace/srv/fs/devfs/devfs_ops.h
===================================================================
--- uspace/srv/fs/devfs/devfs_ops.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/devfs/devfs_ops.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -34,22 +34,7 @@
 #define DEVFS_DEVFS_OPS_H_
 
-#include <ipc/common.h>
 #include <bool.h>
 
 extern bool devfs_init(void);
-
-extern void devfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void devfs_mount(ipc_callid_t, ipc_call_t *);
-extern void devfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void devfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void devfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void devfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void devfs_stat(ipc_callid_t, ipc_call_t *);
-extern void devfs_sync(ipc_callid_t, ipc_call_t *);
-extern void devfs_read(ipc_callid_t, ipc_call_t *);
-extern void devfs_write(ipc_callid_t, ipc_call_t *);
-extern void devfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void devfs_close(ipc_callid_t, ipc_call_t *);
-extern void devfs_destroy(ipc_callid_t, ipc_call_t *);
 
 #endif
Index: uspace/srv/fs/ext2fs/Makefile
===================================================================
--- uspace/srv/fs/ext2fs/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/fs/ext2fs/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# Copyright (c) 2010 Martin Sucha
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a $(LIBEXT2_PREFIX)/libext2.a
+EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX) -I$(LIBEXT2_PREFIX)
+BINARY = ext2fs
+
+SOURCES = \
+	ext2fs.c \
+	ext2fs_ops.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/ext2fs/ext2fs.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/fs/ext2fs/ext2fs.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2011 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */ 
+
+/**
+ * @file	ext2.c
+ * @brief	EXT2 file system driver for HelenOS.
+ */
+
+#include "ext2fs.h"
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <unistd.h>
+#include <task.h>
+#include <stdio.h>
+#include <libfs.h>
+#include "../../vfs/vfs.h"
+
+#define NAME	"ext2fs"
+
+vfs_info_t ext2fs_vfs_info = {
+	.name = NAME,
+};
+
+int main(int argc, char **argv)
+{
+	printf(NAME ": HelenOS EXT2 file system server\n");
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
+		printf(NAME ": failed to connect to VFS\n");
+		return -1;
+	}
+
+	int rc = ext2fs_global_init();
+	if (rc != EOK) {
+		printf(NAME ": Failed global initialization\n");
+		return 1;
+	}	
+		
+	rc = fs_register(vfs_sess, &ext2fs_vfs_info, &ext2fs_ops,
+	    &ext2fs_libfs_ops);
+	if (rc != EOK) {
+		fprintf(stdout, NAME ": Failed to register fs (%d)\n", rc);
+		return 1;
+	}
+	
+	printf(NAME ": Accepting connections\n");
+	task_retval(0);
+	async_manager();
+	/* not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/fs/ext2fs/ext2fs.h
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/fs/ext2fs/ext2fs.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */ 
+
+#ifndef EXT2FS_EXT2FS_H_
+#define EXT2FS_EXT2FS_H_
+
+#include <libext2.h>
+#include <libfs.h>
+#include <sys/types.h>
+
+#define min(a, b)		((a) < (b) ? (a) : (b))
+
+extern vfs_out_ops_t ext2fs_ops;
+extern libfs_ops_t ext2fs_libfs_ops;
+
+extern int ext2fs_global_init(void);
+extern int ext2fs_global_fini(void);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,973 @@
+/*
+ * Copyright (c) 2011 Martin Sucha
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */ 
+
+/**
+ * @file	ext2fs_ops.c
+ * @brief	Implementation of VFS operations for the EXT2 file system server.
+ */
+
+#include "ext2fs.h"
+#include "../../vfs/vfs.h"
+#include <libfs.h>
+#include <libblock.h>
+#include <libext2.h>
+#include <ipc/services.h>
+#include <ipc/devmap.h>
+#include <macros.h>
+#include <async.h>
+#include <errno.h>
+#include <str.h>
+#include <byteorder.h>
+#include <adt/hash_table.h>
+#include <adt/list.h>
+#include <assert.h>
+#include <fibril_synch.h>
+#include <sys/mman.h>
+#include <align.h>
+#include <adt/hash_table.h>
+#include <sys/typefmt.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#define EXT2FS_NODE(node)	((node) ? (ext2fs_node_t *) (node)->data : NULL)
+#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
+#define OPEN_NODES_KEYS 2
+#define OPEN_NODES_DEV_HANDLE_KEY 0
+#define OPEN_NODES_INODE_KEY 1
+#define OPEN_NODES_BUCKETS 256
+
+typedef struct ext2fs_instance {
+	link_t link;
+	devmap_handle_t devmap_handle;
+	ext2_filesystem_t *filesystem;
+	unsigned int open_nodes_count;
+} ext2fs_instance_t;
+
+typedef struct ext2fs_node {
+	ext2fs_instance_t *instance;
+	ext2_inode_ref_t *inode_ref;
+	fs_node_t *fs_node;
+	link_t link;
+	unsigned int references;
+} ext2fs_node_t;
+
+/*
+ * Forward declarations of auxiliary functions
+ */
+static int ext2fs_instance_get(devmap_handle_t, ext2fs_instance_t **);
+static int ext2fs_read_directory(ipc_callid_t, aoff64_t, size_t,
+    ext2fs_instance_t *, ext2_inode_ref_t *, size_t *);
+static int ext2fs_read_file(ipc_callid_t, aoff64_t, size_t, ext2fs_instance_t *,
+    ext2_inode_ref_t *, size_t *);
+static bool ext2fs_is_dots(const uint8_t *, size_t);
+static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
+static int ext2fs_node_put_core(ext2fs_node_t *);
+
+/*
+ * Forward declarations of EXT2 libfs operations.
+ */
+static int ext2fs_root_get(fs_node_t **, devmap_handle_t);
+static int ext2fs_match(fs_node_t **, fs_node_t *, const char *);
+static int ext2fs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
+static int ext2fs_node_open(fs_node_t *);
+static int ext2fs_node_put(fs_node_t *);
+static int ext2fs_create_node(fs_node_t **, devmap_handle_t, int);
+static int ext2fs_destroy_node(fs_node_t *);
+static int ext2fs_link(fs_node_t *, fs_node_t *, const char *);
+static int ext2fs_unlink(fs_node_t *, fs_node_t *, const char *);
+static int ext2fs_has_children(bool *, fs_node_t *);
+static fs_index_t ext2fs_index_get(fs_node_t *);
+static aoff64_t ext2fs_size_get(fs_node_t *);
+static unsigned ext2fs_lnkcnt_get(fs_node_t *);
+static bool ext2fs_is_directory(fs_node_t *);
+static bool ext2fs_is_file(fs_node_t *node);
+static devmap_handle_t ext2fs_device_get(fs_node_t *node);
+
+/*
+ * Static variables
+ */
+static LIST_INITIALIZE(instance_list);
+static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex);
+static hash_table_t open_nodes;
+static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
+
+/* Hash table interface for open nodes hash table */
+static hash_index_t open_nodes_hash(unsigned long key[])
+{
+	/* TODO: This is very simple and probably can be improved */
+	return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
+}
+
+static int open_nodes_compare(unsigned long key[], hash_count_t keys, 
+    link_t *item)
+{
+	ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
+	assert(keys > 0);
+	if (enode->instance->devmap_handle !=
+	    ((devmap_handle_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
+		return false;
+	}
+	if (keys == 1) {
+		return true;
+	}
+	assert(keys == 2);
+	return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]);
+}
+
+static void open_nodes_remove_cb(link_t *link)
+{
+	/* We don't use remove callback for this hash table */
+}
+
+static hash_table_operations_t open_nodes_ops = {
+	.hash = open_nodes_hash,
+	.compare = open_nodes_compare,
+	.remove_callback = open_nodes_remove_cb,
+};
+
+/**
+ * 
+ */
+int ext2fs_global_init(void)
+{
+	if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
+	    OPEN_NODES_KEYS, &open_nodes_ops)) {
+		return ENOMEM;
+	}
+	return EOK;
+}
+
+int ext2fs_global_fini(void)
+{
+	hash_table_destroy(&open_nodes);
+	return EOK;
+}
+
+
+/*
+ * EXT2 libfs operations.
+ */
+
+/**
+ * Find an instance of filesystem for the given devmap_handle
+ */
+int ext2fs_instance_get(devmap_handle_t devmap_handle, ext2fs_instance_t **inst)
+{
+	EXT2FS_DBG("(%" PRIun ", -)", devmap_handle);
+	ext2fs_instance_t *tmp;
+	
+	fibril_mutex_lock(&instance_list_mutex);
+
+	if (list_empty(&instance_list)) {
+		EXT2FS_DBG("list empty");
+		fibril_mutex_unlock(&instance_list_mutex);
+		return EINVAL;
+	}
+
+	list_foreach(instance_list, link) {
+		tmp = list_get_instance(link, ext2fs_instance_t, link);
+		
+		if (tmp->devmap_handle == devmap_handle) {
+			*inst = tmp;
+			fibril_mutex_unlock(&instance_list_mutex);
+			return EOK;
+		}
+	}
+	
+	EXT2FS_DBG("not found");
+	
+	fibril_mutex_unlock(&instance_list_mutex);
+	return EINVAL;
+}
+
+
+
+int ext2fs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
+{
+	EXT2FS_DBG("(-, %" PRIun ")", devmap_handle);
+	return ext2fs_node_get(rfn, devmap_handle, EXT2_INODE_ROOT_INDEX);
+}
+
+int ext2fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+	EXT2FS_DBG("(-,-,%s)", component);
+	ext2fs_node_t *eparent = EXT2FS_NODE(pfn);
+	ext2_filesystem_t *fs;
+	ext2_directory_iterator_t it;
+	int rc;
+	size_t name_size;
+	size_t component_size;
+	bool found = false;
+	uint32_t inode;
+	
+	fs = eparent->instance->filesystem;
+	
+	if (!ext2_inode_is_type(fs->superblock, eparent->inode_ref->inode,
+	    EXT2_INODE_MODE_DIRECTORY)) {
+		return ENOTDIR;
+	}
+	
+	rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref, 0);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Find length of component in bytes
+	 * TODO: check for library function call that does this
+	 */
+	component_size = 0;
+	while (*(component+component_size) != 0) {
+		component_size++;
+	}
+	
+	while (it.current != NULL) {
+		inode = ext2_directory_entry_ll_get_inode(it.current);
+		
+		/* ignore empty directory entries */
+		if (inode != 0) {
+			name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
+				it.current);
+
+			if (name_size == component_size && bcmp(component, &it.current->name,
+				    name_size) == 0) {
+				rc = ext2fs_node_get_core(rfn, eparent->instance,
+					inode);
+				if (rc != EOK) {
+					ext2_directory_iterator_fini(&it);
+					return rc;
+				}
+				found = true;
+				break;
+			}
+		}
+		
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK) {
+			ext2_directory_iterator_fini(&it);
+			return rc;
+		}
+	}
+	
+	ext2_directory_iterator_fini(&it);
+	
+	if (!found) {
+		return ENOENT;
+	}
+	
+	return EOK;
+}
+
+/** Instantiate a EXT2 in-core node. */
+int ext2fs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
+{
+	EXT2FS_DBG("(-,%" PRIun ",%u)", devmap_handle, index);
+	
+	ext2fs_instance_t *inst = NULL;
+	int rc;
+	
+	rc = ext2fs_instance_get(devmap_handle, &inst);
+	if (rc != EOK) {
+		return rc;
+	}
+	
+	return ext2fs_node_get_core(rfn, inst, index);
+}
+
+int ext2fs_node_get_core(fs_node_t **rfn, ext2fs_instance_t *inst,
+		fs_index_t index)
+{
+	int rc;
+	fs_node_t *node = NULL;
+	ext2fs_node_t *enode = NULL;
+	
+	ext2_inode_ref_t *inode_ref = NULL;
+
+	fibril_mutex_lock(&open_nodes_lock);
+	
+	/* Check if the node is not already open */
+	unsigned long key[] = {
+		[OPEN_NODES_DEV_HANDLE_KEY] = inst->devmap_handle,
+		[OPEN_NODES_INODE_KEY] = index,
+	};
+	link_t *already_open = hash_table_find(&open_nodes, key);
+
+	if (already_open) {
+		enode = hash_table_get_instance(already_open, ext2fs_node_t, link);
+		*rfn = enode->fs_node;
+		enode->references++;
+
+		fibril_mutex_unlock(&open_nodes_lock);
+		return EOK;
+	}
+
+	enode = malloc(sizeof(ext2fs_node_t));
+	if (enode == NULL) {
+		fibril_mutex_unlock(&open_nodes_lock);
+		return ENOMEM;
+	}
+
+	node = malloc(sizeof(fs_node_t));
+	if (node == NULL) {
+		free(enode);
+		fibril_mutex_unlock(&open_nodes_lock);
+		return ENOMEM;
+	}	
+	fs_node_initialize(node);
+
+	rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
+	if (rc != EOK) {
+		free(enode);
+		free(node);
+		fibril_mutex_unlock(&open_nodes_lock);
+		return rc;
+	}
+	
+	enode->inode_ref = inode_ref;
+	enode->instance = inst;
+	enode->references = 1;
+	enode->fs_node = node;
+	link_initialize(&enode->link);
+	
+	node->data = enode;
+	*rfn = node;
+	
+	hash_table_insert(&open_nodes, key, &enode->link);
+	inst->open_nodes_count++;
+	
+	EXT2FS_DBG("inode: %u", inode_ref->index);
+	
+	EXT2FS_DBG("EOK");
+
+	fibril_mutex_unlock(&open_nodes_lock);
+	return EOK;
+}
+
+int ext2fs_node_open(fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	/*
+	 * Opening a file is stateless, nothing
+	 * to be done here.
+	 */
+	return EOK;
+}
+
+int ext2fs_node_put(fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	int rc;
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	
+	fibril_mutex_lock(&open_nodes_lock);
+
+	assert(enode->references > 0);
+	enode->references--;
+	if (enode->references == 0) {
+		rc = ext2fs_node_put_core(enode);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&open_nodes_lock);
+			return rc;
+		}
+	}
+
+	fibril_mutex_unlock(&open_nodes_lock);
+	
+	return EOK;
+}
+
+int ext2fs_node_put_core(ext2fs_node_t *enode)
+{
+	int rc;
+
+	unsigned long key[] = {
+		[OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->devmap_handle,
+		[OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
+	};
+	hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
+	assert(enode->instance->open_nodes_count > 0);
+	enode->instance->open_nodes_count--;
+
+	rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
+	if (rc != EOK) {
+		EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
+		return rc;
+	}
+
+	free(enode->fs_node);
+	free(enode);
+	return EOK;
+}
+
+int ext2fs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
+{
+	EXT2FS_DBG("");
+	// TODO
+	return ENOTSUP;
+}
+
+int ext2fs_destroy_node(fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	// TODO
+	return ENOTSUP;
+}
+
+int ext2fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	EXT2FS_DBG("");
+	// TODO
+	return ENOTSUP;
+}
+
+int ext2fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+	EXT2FS_DBG("");
+	// TODO
+	return ENOTSUP;
+}
+
+int ext2fs_has_children(bool *has_children, fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	ext2_directory_iterator_t it;
+	ext2_filesystem_t *fs;
+	int rc;
+	bool found = false;
+	size_t name_size;
+
+	fs = enode->instance->filesystem;
+
+	if (!ext2_inode_is_type(fs->superblock, enode->inode_ref->inode,
+	    EXT2_INODE_MODE_DIRECTORY)) {
+		*has_children = false;
+		EXT2FS_DBG("EOK - false");
+		return EOK;
+	}
+	
+	rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref, 0);
+	if (rc != EOK) {
+		EXT2FS_DBG("error %u", rc);
+		return rc;
+	}
+	
+	/* Find a non-empty directory entry */
+	while (it.current != NULL) {
+		if (it.current->inode != 0) {
+			name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
+				it.current);
+			if (!ext2fs_is_dots(&it.current->name, name_size)) {
+				found = true;
+				break;
+			}
+		}
+		
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK) {
+			ext2_directory_iterator_fini(&it);
+			EXT2FS_DBG("error %u", rc);
+			return rc;
+		}
+	}
+	
+	rc = ext2_directory_iterator_fini(&it);
+	if (rc != EOK) {
+		EXT2FS_DBG("error %u", rc);
+		return rc;
+	}
+
+	*has_children = found;
+	EXT2FS_DBG("EOK");
+	
+	return EOK;
+}
+
+
+fs_index_t ext2fs_index_get(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	EXT2FS_DBG("%u", enode->inode_ref->index);
+	return enode->inode_ref->index;
+}
+
+aoff64_t ext2fs_size_get(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	aoff64_t size = ext2_inode_get_size(enode->instance->filesystem->superblock,
+	    enode->inode_ref->inode);
+	EXT2FS_DBG("%" PRIu64, size);
+	return size;
+}
+
+unsigned ext2fs_lnkcnt_get(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	unsigned count = ext2_inode_get_usage_count(enode->inode_ref->inode);
+	EXT2FS_DBG("%u", count);
+	return count;
+}
+
+bool ext2fs_is_directory(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	bool is_dir = ext2_inode_is_type(enode->instance->filesystem->superblock,
+	    enode->inode_ref->inode, EXT2_INODE_MODE_DIRECTORY);
+	EXT2FS_DBG("%s", is_dir ? "true" : "false");
+	EXT2FS_DBG("%u", enode->inode_ref->index);
+	return is_dir;
+}
+
+bool ext2fs_is_file(fs_node_t *fn)
+{
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	bool is_file = ext2_inode_is_type(enode->instance->filesystem->superblock,
+	    enode->inode_ref->inode, EXT2_INODE_MODE_FILE);
+	EXT2FS_DBG("%s", is_file ? "true" : "false");
+	return is_file;
+}
+
+devmap_handle_t ext2fs_device_get(fs_node_t *fn)
+{
+	EXT2FS_DBG("");
+	ext2fs_node_t *enode = EXT2FS_NODE(fn);
+	return enode->instance->devmap_handle;
+}
+
+/** libfs operations */
+libfs_ops_t ext2fs_libfs_ops = {
+	.root_get = ext2fs_root_get,
+	.match = ext2fs_match,
+	.node_get = ext2fs_node_get,
+	.node_open = ext2fs_node_open,
+	.node_put = ext2fs_node_put,
+	.create = ext2fs_create_node,
+	.destroy = ext2fs_destroy_node,
+	.link = ext2fs_link,
+	.unlink = ext2fs_unlink,
+	.has_children = ext2fs_has_children,
+	.index_get = ext2fs_index_get,
+	.size_get = ext2fs_size_get,
+	.lnkcnt_get = ext2fs_lnkcnt_get,
+	.is_directory = ext2fs_is_directory,
+	.is_file = ext2fs_is_file,
+	.device_get = ext2fs_device_get
+};
+
+/*
+ * VFS operations.
+ */
+
+static int ext2fs_mounted(devmap_handle_t devmap_handle, const char *opts,
+   fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
+	EXT2FS_DBG("");
+	int rc;
+	ext2_filesystem_t *fs;
+	ext2fs_instance_t *inst;
+	bool read_only;
+	
+	/* Allocate libext2 filesystem structure */
+	fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
+	if (fs == NULL)
+		return ENOMEM;
+	
+	/* Allocate instance structure */
+	inst = (ext2fs_instance_t *) malloc(sizeof(ext2fs_instance_t));
+	if (inst == NULL) {
+		free(fs);
+		return ENOMEM;
+	}
+	
+	/* Initialize the filesystem  */
+	rc = ext2_filesystem_init(fs, devmap_handle);
+	if (rc != EOK) {
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Do some sanity checking */
+	rc = ext2_filesystem_check_sanity(fs);
+	if (rc != EOK) {
+		ext2_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Check flags */
+	rc = ext2_filesystem_check_flags(fs, &read_only);
+	if (rc != EOK) {
+		ext2_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	
+	/* Initialize instance */
+	link_initialize(&inst->link);
+	inst->devmap_handle = devmap_handle;
+	inst->filesystem = fs;
+	inst->open_nodes_count = 0;
+	
+	/* Read root node */
+	fs_node_t *root_node;
+	rc = ext2fs_node_get_core(&root_node, inst, EXT2_INODE_ROOT_INDEX);
+	if (rc != EOK) {
+		ext2_filesystem_fini(fs);
+		free(fs);
+		free(inst);
+		return rc;
+	}
+	ext2fs_node_t *enode = EXT2FS_NODE(root_node);
+		
+	/* Add instance to the list */
+	fibril_mutex_lock(&instance_list_mutex);
+	list_append(&inst->link, &instance_list);
+	fibril_mutex_unlock(&instance_list_mutex);
+	
+	*index = EXT2_INODE_ROOT_INDEX;
+	*size = 0;
+	*lnkcnt = ext2_inode_get_usage_count(enode->inode_ref->inode);
+	
+	ext2fs_node_put(root_node);
+
+	return EOK;
+}
+
+static int ext2fs_unmounted(devmap_handle_t devmap_handle)
+{
+	EXT2FS_DBG("");
+	ext2fs_instance_t *inst;
+	int rc;
+	
+	rc = ext2fs_instance_get(devmap_handle, &inst);
+	
+	if (rc != EOK)
+		return rc;
+	
+	fibril_mutex_lock(&open_nodes_lock);
+
+	EXT2FS_DBG("open_nodes_count = %d", inst->open_nodes_count)
+	if (inst->open_nodes_count != 0) {
+		fibril_mutex_unlock(&open_nodes_lock);
+		return EBUSY;
+	}
+	
+	/* Remove the instance from the list */
+	fibril_mutex_lock(&instance_list_mutex);
+	list_remove(&inst->link);
+	fibril_mutex_unlock(&instance_list_mutex);
+
+	fibril_mutex_unlock(&open_nodes_lock);
+	
+	ext2_filesystem_fini(inst->filesystem);
+	
+	return EOK;
+}
+
+static int
+ext2fs_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
+	EXT2FS_DBG("");
+	
+	ext2fs_instance_t *inst;
+	ext2_inode_ref_t *inode_ref;
+	int rc;
+	
+	/*
+	 * Receive the read request.
+	 */
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	rc = ext2fs_instance_get(devmap_handle, &inst);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
+	    EXT2_INODE_MODE_FILE)) {
+		rc = ext2fs_read_file(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else if (ext2_inode_is_type(inst->filesystem->superblock,
+	    inode_ref->inode, EXT2_INODE_MODE_DIRECTORY)) {
+		rc = ext2fs_read_directory(callid, pos, size, inst, inode_ref,
+		    rbytes);
+	} else {
+		/* Other inode types not supported */
+		async_answer_0(callid, ENOTSUP);
+		rc = ENOTSUP;
+	}
+	
+	ext2_filesystem_put_inode_ref(inode_ref);
+	
+	return rc;
+}
+
+/**
+ * Determine whether given directory entry name is . or ..
+ */
+bool ext2fs_is_dots(const uint8_t *name, size_t name_size) {
+	if (name_size == 1 && name[0] == '.') {
+		return true;
+	}
+	
+	if (name_size == 2 && name[0] == '.' && name[1] == '.') {
+		return true;
+	}
+	
+	return false;
+}
+
+int ext2fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
+{
+	ext2_directory_iterator_t it;
+	aoff64_t next;
+	uint8_t *buf;
+	size_t name_size;
+	int rc;
+	bool found = false;
+	
+	rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref, pos);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/* Find next interesting directory entry.
+	 * We want to skip . and .. entries
+	 * as these are not used in HelenOS
+	 */
+	while (it.current != NULL) {
+		if (it.current->inode == 0) {
+			goto skip;
+		}
+		
+		name_size = ext2_directory_entry_ll_get_name_length(
+		    inst->filesystem->superblock, it.current);
+		
+		/* skip . and .. */
+		if (ext2fs_is_dots(&it.current->name, name_size)) {
+			goto skip;
+		}
+		
+		/* The on-disk entry does not contain \0 at the end
+		 * end of entry name, so we copy it to new buffer
+		 * and add the \0 at the end
+		 */
+		buf = malloc(name_size+1);
+		if (buf == NULL) {
+			ext2_directory_iterator_fini(&it);
+			async_answer_0(callid, ENOMEM);
+			return ENOMEM;
+		}
+		memcpy(buf, &it.current->name, name_size);
+		*(buf + name_size) = 0;
+		found = true;
+		(void) async_data_read_finalize(callid, buf, name_size + 1);
+		free(buf);
+		break;
+		
+skip:
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK) {
+			ext2_directory_iterator_fini(&it);
+			async_answer_0(callid, rc);
+			return rc;
+		}
+	}
+	
+	if (found) {
+		rc = ext2_directory_iterator_next(&it);
+		if (rc != EOK)
+			return rc;
+		next = it.current_offset;
+	}
+	
+	rc = ext2_directory_iterator_fini(&it);
+	if (rc != EOK)
+		return rc;
+	
+	if (found) {
+		*rbytes = next - pos;
+		return EOK;
+	} else {
+		async_answer_0(callid, ENOENT);
+		return ENOENT;
+	}
+}
+
+int ext2fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size,
+    ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref, size_t *rbytes)
+{
+	int rc;
+	uint32_t block_size;
+	aoff64_t file_block;
+	uint64_t file_size;
+	uint32_t fs_block;
+	size_t offset_in_block;
+	size_t bytes;
+	block_t *block;
+	uint8_t *buffer;
+	
+	file_size = ext2_inode_get_size(inst->filesystem->superblock,
+		inode_ref->inode);
+	
+	if (pos >= file_size) {
+		/* Read 0 bytes successfully */
+		async_data_read_finalize(callid, NULL, 0);
+		*rbytes = 0;
+		return EOK;
+	}
+	
+	/* For now, we only read data from one block at a time */
+	block_size = ext2_superblock_get_block_size(inst->filesystem->superblock);
+	file_block = pos / block_size;
+	offset_in_block = pos % block_size;
+	bytes = min(block_size - offset_in_block, size);
+	
+	/* Handle end of file */
+	if (pos + bytes > file_size) {
+		bytes = file_size - pos;
+	}
+	
+	/* Get the real block number */
+	rc = ext2_filesystem_get_inode_data_block_index(inst->filesystem,
+		inode_ref->inode, file_block, &fs_block);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	/* Check for sparse file
+	 * If ext2_filesystem_get_inode_data_block_index returned
+	 * fs_block == 0, it means that the given block is not allocated for the 
+	 * file and we need to return a buffer of zeros
+	 */
+	if (fs_block == 0) {
+		buffer = malloc(bytes);
+		if (buffer == NULL) {
+			async_answer_0(callid, ENOMEM);
+			return ENOMEM;
+		}
+		
+		memset(buffer, 0, bytes);
+		
+		async_data_read_finalize(callid, buffer, bytes);
+		*rbytes = bytes;
+		
+		free(buffer);
+		
+		return EOK;
+	}
+	
+	/* Usual case - we need to read a block from device */
+	rc = block_get(&block, inst->devmap_handle, fs_block, BLOCK_FLAGS_NONE);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	assert(offset_in_block + bytes <= block_size);
+	async_data_read_finalize(callid, block->data + offset_in_block, bytes);
+	
+	rc = block_put(block);
+	if (rc != EOK)
+		return rc;
+	
+	*rbytes = bytes;
+	return EOK;
+}
+
+static int
+ext2fs_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int
+ext2fs_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int ext2fs_close(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return EOK;
+}
+
+static int ext2fs_destroy(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+static int ext2fs_sync(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	EXT2FS_DBG("");
+	return ENOTSUP;
+}
+
+vfs_out_ops_t ext2fs_ops = {
+	.mounted = ext2fs_mounted,
+	.unmounted = ext2fs_unmounted,
+	.read = ext2fs_read,
+	.write = ext2fs_write,
+	.truncate = ext2fs_truncate,
+	.close = ext2fs_close,
+	.destroy = ext2fs_destroy,
+	.sync = ext2fs_sync,
+};
+
+/**
+ * @}
+ */
+
Index: uspace/srv/fs/fat/Makefile
===================================================================
--- uspace/srv/fs/fat/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/fat/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -32,4 +32,5 @@
 EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX)
 BINARY = fat
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/fs/fat/fat.c
===================================================================
--- uspace/srv/fs/fat/fat.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/fat/fat.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -40,5 +40,5 @@
 #include "fat.h"
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <errno.h>
@@ -57,108 +57,20 @@
 };
 
-fs_reg_t fat_reg;
-
-/**
- * This connection fibril processes VFS requests from VFS.
- *
- * In order to support simultaneous VFS requests, our design is as follows.
- * The connection fibril accepts VFS requests from VFS. If there is only one
- * instance of the fibril, VFS will need to serialize all VFS requests it sends
- * to FAT. To overcome this bottleneck, VFS can send FAT the IPC_M_CONNECT_ME_TO
- * call. In that case, a new connection fibril will be created, which in turn
- * will accept the call. Thus, a new phone will be opened for VFS.
- *
- * There are few issues with this arrangement. First, VFS can run out of
- * available phones. In that case, VFS can close some other phones or use one
- * phone for more serialized requests. Similarily, FAT can refuse to duplicate
- * the connection. VFS should then just make use of already existing phones and
- * route its requests through them. To avoid paying the fibril creation price 
- * upon each request, FAT might want to keep the connections open after the
- * request has been completed.
- */
-static void fat_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (iid) {
-		/*
-		 * This only happens for connections opened by
-		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
-		 * created by IPC_M_CONNECT_TO_ME.
-		 */
-		async_answer_0(iid, EOK);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	while (1) {
-		ipc_callid_t callid;
-		ipc_call_t call;
-	
-		callid = async_get_call(&call);
-		switch  (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			return;
-		case VFS_OUT_MOUNTED:
-			fat_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			fat_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			fat_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			fat_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			fat_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			fat_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			fat_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			fat_truncate(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			fat_stat(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			fat_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			fat_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			fat_open_node(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			fat_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
-	int vfs_phone;
-	int rc;
-
 	printf(NAME ": HelenOS FAT file system server\n");
-
-	rc = fat_idx_init();
+	
+	int rc = fat_idx_init();
 	if (rc != EOK)
 		goto err;
-
-	vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
-	if (vfs_phone < EOK) {
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
 		printf(NAME ": failed to connect to VFS\n");
 		return -1;
 	}
 	
-	rc = fs_register(vfs_phone, &fat_reg, &fat_vfs_info, fat_connection);
+	rc = fs_register(vfs_sess, &fat_vfs_info, &fat_ops, &fat_libfs_ops);
 	if (rc != EOK) {
 		fat_idx_fini();
@@ -169,7 +81,8 @@
 	task_retval(0);
 	async_manager();
-	/* not reached */
+	
+	/* Not reached */
 	return 0;
-
+	
 err:
 	printf(NAME ": Failed to register file system (%d)\n", rc);
@@ -179,3 +92,3 @@
 /**
  * @}
- */ 
+ */
Index: uspace/srv/fs/fat/fat.h
===================================================================
--- uspace/srv/fs/fat/fat.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/fat/fat.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -227,20 +227,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 **, devmap_handle_t);
Index: uspace/srv/fs/fat/fat_idx.c
===================================================================
--- uspace/srv/fs/fat/fat_idx.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/fat/fat_idx.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -59,13 +59,13 @@
 typedef struct {
 	link_t		link;
-	devmap_handle_t	devmap_handle;
+	devmap_handle_t devmap_handle;
 
 	/** Next unassigned index. */
-	fs_index_t	next;
+	fs_index_t next;
 	/** Number of remaining unassigned indices. */
-	uint64_t	remaining;
+	uint64_t remaining;
 
 	/** Sorted list of intervals of freed indices. */
-	link_t		freed_head;
+	list_t freed_list;
 } unused_t;
 
@@ -74,5 +74,5 @@
 
 /** List of unused structures. */
-static LIST_INITIALIZE(unused_head);
+static LIST_INITIALIZE(unused_list);
 
 static void unused_initialize(unused_t *u, devmap_handle_t devmap_handle)
@@ -82,5 +82,5 @@
 	u->next = 0;
 	u->remaining = ((uint64_t)((fs_index_t)-1)) + 1;
-	list_initialize(&u->freed_head);
+	list_initialize(&u->freed_list);
 }
 
@@ -88,13 +88,14 @@
 {
 	unused_t *u;
-	link_t *l;
 
 	if (lock)
 		fibril_mutex_lock(&unused_lock);
-	for (l = unused_head.next; l != &unused_head; l = l->next) {
+
+	list_foreach(unused_list, l) {
 		u = list_get_instance(l, unused_t, link);
 		if (u->devmap_handle == devmap_handle) 
 			return u;
 	}
+	
 	if (lock)
 		fibril_mutex_unlock(&unused_lock);
@@ -249,5 +250,5 @@
 		return false;	
 
-	if (list_empty(&u->freed_head)) {
+	if (list_empty(&u->freed_list)) {
 		if (u->remaining) { 
 			/*
@@ -262,6 +263,6 @@
 	} else {
 		/* There are some freed indices which we can reuse. */
-		freed_t *f = list_get_instance(u->freed_head.next, freed_t,
-		    link);
+		freed_t *f = list_get_instance(list_first(&u->freed_list),
+		    freed_t, link);
 		*index = f->first;
 		if (f->first++ == f->last) {
@@ -320,10 +321,10 @@
 		link_t *lnk;
 		freed_t *n;
-		for (lnk = u->freed_head.next; lnk != &u->freed_head;
+		for (lnk = u->freed_list.head.next; lnk != &u->freed_list.head;
 		    lnk = lnk->next) {
 			freed_t *f = list_get_instance(lnk, freed_t, link);
 			if (f->first == index + 1) {
 				f->first--;
-				if (lnk->prev != &u->freed_head)
+				if (lnk->prev != &u->freed_list.head)
 					try_coalesce_intervals(lnk->prev, lnk,
 					    lnk);
@@ -333,5 +334,5 @@
 			if (f->last == index - 1) {
 				f->last++;
-				if (lnk->next != &u->freed_head)
+				if (lnk->next != &u->freed_list.head)
 					try_coalesce_intervals(lnk, lnk->next,
 					    lnk);
@@ -359,5 +360,5 @@
 		n->first = index;
 		n->last = index;
-		list_append(&n->link, &u->freed_head);
+		list_append(&n->link, &u->freed_list);
 	}
 	fibril_mutex_unlock(&unused_lock);
@@ -558,5 +559,5 @@
 	fibril_mutex_lock(&unused_lock);
 	if (!unused_find(devmap_handle, false)) {
-		list_append(&u->link, &unused_head);
+		list_append(&u->link, &unused_list);
 	} else {
 		free(u);
@@ -594,7 +595,7 @@
 	fibril_mutex_unlock(&unused_lock);
 
-	while (!list_empty(&u->freed_head)) {
+	while (!list_empty(&u->freed_list)) {
 		freed_t *f;
-		f = list_get_instance(u->freed_head.next, freed_t, link);
+		f = list_get_instance(list_first(&u->freed_list), freed_t, link);
 		list_remove(&f->link);
 		free(f);
Index: uspace/srv/fs/fat/fat_ops.c
===================================================================
--- uspace/srv/fs/fat/fat_ops.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/fat/fat_ops.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -70,5 +70,5 @@
 
 /** List of cached free FAT nodes. */
-static LIST_INITIALIZE(ffn_head);
+static LIST_INITIALIZE(ffn_list);
 
 /*
@@ -88,5 +88,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);
@@ -150,5 +149,4 @@
 static int fat_node_fini_by_devmap_handle(devmap_handle_t devmap_handle)
 {
-	link_t *lnk;
 	fat_node_t *nodep;
 	int rc;
@@ -162,5 +160,5 @@
 restart:
 	fibril_mutex_lock(&ffn_mutex);
-	for (lnk = ffn_head.next; lnk != &ffn_head; lnk = lnk->next) {
+	list_foreach(ffn_list, lnk) {
 		nodep = list_get_instance(lnk, fat_node_t, ffn_link);
 		if (!fibril_mutex_trylock(&nodep->lock)) {
@@ -199,5 +197,5 @@
 		free(nodep);
 
-		/* Need to restart because we changed the ffn_head list. */
+		/* Need to restart because we changed ffn_list. */
 		goto restart;
 	}
@@ -214,8 +212,9 @@
 
 	fibril_mutex_lock(&ffn_mutex);
-	if (!list_empty(&ffn_head)) {
+	if (!list_empty(&ffn_list)) {
 		/* Try to use a cached free node structure. */
 		fat_idx_t *idxp_tmp;
-		nodep = list_get_instance(ffn_head.next, fat_node_t, ffn_link);
+		nodep = list_get_instance(list_first(&ffn_list), fat_node_t,
+		    ffn_link);
 		if (!fibril_mutex_trylock(&nodep->lock))
 			goto skip_cache;
@@ -464,5 +463,5 @@
 		if (nodep->idx) {
 			fibril_mutex_lock(&ffn_mutex);
-			list_append(&nodep->ffn_link, &ffn_head);
+			list_append(&nodep->ffn_link, &ffn_list);
 			fibril_mutex_unlock(&ffn_mutex);
 		} else {
@@ -823,9 +822,4 @@
 }
 
-char fat_plb_get_char(unsigned pos)
-{
-	return fat_reg.plb_ro[pos % PLB_SIZE];
-}
-
 bool fat_is_directory(fs_node_t *fn)
 {
@@ -858,5 +852,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,
@@ -865,21 +858,14 @@
 
 /*
- * VFS operations.
+ * FAT VFS_OUT operations.
  */
 
-void fat_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+static int
+fat_mounted(devmap_handle_t devmap_handle, 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. */
@@ -889,12 +875,8 @@
 		cmode = CACHE_MODE_WB;
 
-	free(opts);
-
 	/* initialize libblock */
-	rc = block_init(devmap_handle, BS_SIZE);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	rc = block_init(EXCHANGE_SERIALIZE, devmap_handle, BS_SIZE);
+	if (rc != EOK)
+		return rc;
 
 	/* prepare the boot block */
@@ -902,6 +884,5 @@
 	if (rc != EOK) {
 		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -911,6 +892,5 @@
 	if (BPS(bs) != BS_SIZE) {
 		block_fini(devmap_handle);
-		async_answer_0(rid, ENOTSUP);
-		return;
+		return ENOTSUP;
 	}
 
@@ -919,6 +899,5 @@
 	if (rc != EOK) {
 		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -928,6 +907,5 @@
 		(void) block_cache_fini(devmap_handle);
 		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -936,6 +914,5 @@
 		(void) block_cache_fini(devmap_handle);
 		block_fini(devmap_handle);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 	}
 
@@ -946,6 +923,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 
@@ -957,6 +933,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	fat_node_initialize(rootp);
@@ -969,6 +944,5 @@
 		block_fini(devmap_handle);
 		fat_idx_fini_by_devmap_handle(devmap_handle);
-		async_answer_0(rid, ENOMEM);
-		return;
+		return ENOMEM;
 	}
 	assert(ridxp->index == 0);
@@ -1004,15 +978,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)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	*index = ridxp->index;
+	*size = rootp->size;
+	*linkcnt = rootp->lnkcnt;
+
+	return EOK;
+}
+
+static int fat_unmounted(devmap_handle_t devmap_handle)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1020,8 +992,6 @@
 
 	rc = fat_root_get(&fn, devmap_handle);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
 	nodep = FAT_NODE(fn);
 
@@ -1032,6 +1002,5 @@
 	if (nodep->refcnt != 2) {
 		(void) fat_node_put(fn);
-		async_answer_0(rid, EBUSY);
-		return;
+		return EBUSY;
 	}
 
@@ -1052,23 +1021,11 @@
 	block_fini(devmap_handle);
 
-	async_answer_0(rid, EOK);
-}
-
-void fat_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&fat_libfs_ops, rid, request);
-}
-
-void fat_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	return EOK;
+}
+
+static int
+fat_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1079,12 +1036,8 @@
 
 	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1094,6 +1047,5 @@
 		fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -1118,6 +1070,5 @@
 				fat_node_put(fn);
 				async_answer_0(callid, rc);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 			(void) async_data_read_finalize(callid,
@@ -1126,6 +1077,5 @@
 			if (rc != EOK) {
 				fat_node_put(fn);
-				async_answer_0(rid, rc);
-				return;
+				return rc;
 			}
 		}
@@ -1155,6 +1105,5 @@
 		(void) fat_node_put(fn);
 		async_answer_0(callid, rc);
-		async_answer_0(rid, rc);
-		return;
+		return rc;
 
 miss:
@@ -1164,6 +1113,6 @@
 		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;
 
 hit:
@@ -1177,17 +1126,16 @@
 
 	rc = fat_node_put(fn);
-	async_answer_1(rid, rc, (sysarg_t)bytes);
-}
-
-void fat_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+	*rbytes = bytes;
+	return rc;
+}
+
+static int
+fat_write(devmap_handle_t devmap_handle, 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;
@@ -1196,12 +1144,8 @@
 
 	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1211,6 +1155,5 @@
 		(void) fat_node_put(fn);
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -1240,6 +1183,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);
@@ -1247,6 +1189,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,
@@ -1256,6 +1197,5 @@
 		if (rc != EOK) {
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		if (pos + bytes > nodep->size) {
@@ -1263,8 +1203,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 {
 		/*
@@ -1282,6 +1222,5 @@
 			(void) fat_node_put(fn);
 			async_answer_0(callid, rc);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/* zero fill any gaps */
@@ -1291,6 +1230,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, devmap_handle, lcl, NULL,
@@ -1300,6 +1238,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,
@@ -1310,6 +1247,5 @@
 			(void) fat_free_clusters(bs, devmap_handle, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
+			return rc;
 		}
 		/*
@@ -1321,21 +1257,17 @@
 			(void) fat_free_clusters(bs, devmap_handle, mcl);
 			(void) fat_node_put(fn);
-			async_answer_0(rid, rc);
-			return;
-		}
-		nodep->size = size = pos + bytes;
+			return rc;
+		}
+		*nsize = nodep->size = pos + bytes;
+		rc = fat_node_put(fn);
 		nodep->dirty = true;		/* need to sync node */
-		rc = fat_node_put(fn);
-		async_answer_2(rid, rc, bytes, size);
-		return;
-	}
-}
-
-void fat_truncate(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t size =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
+		*wbytes = bytes;
+		return rc;
+	}
+}
+
+static int
+fat_truncate(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t size)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1344,12 +1276,8 @@
 
 	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 	nodep = FAT_NODE(fn);
 
@@ -1395,17 +1323,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)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
+	return rc;
+}
+
+static int fat_close(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	return EOK;
+}
+
+static int fat_destroy(devmap_handle_t devmap_handle, fs_index_t index)
+{
 	fs_node_t *fn;
 	fat_node_t *nodep;
@@ -1413,12 +1338,8 @@
 
 	rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 
 	nodep = FAT_NODE(fn);
@@ -1430,32 +1351,15 @@
 
 	rc = fat_destroy_node(fn);
-	async_answer_0(rid, rc);
-}
-
-void fat_open_node(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_open_node(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_stat(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_stat(&fat_libfs_ops, fat_reg.fs_handle, rid, request);
-}
-
-void fat_sync(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-
+	return rc;
+}
+
+static int fat_sync(devmap_handle_t devmap_handle, fs_index_t index)
+{
 	fs_node_t *fn;
 	int rc = fat_node_get(&fn, devmap_handle, index);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-	if (!fn) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
+	if (rc != EOK)
+		return rc;
+	if (!fn)
+		return ENOENT;
 
 	fat_node_t *nodep = FAT_NODE(fn);
@@ -1465,6 +1369,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/tmpfs/Makefile
===================================================================
--- uspace/srv/fs/tmpfs/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/tmpfs/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -32,4 +32,5 @@
 EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX)
 BINARY = tmpfs
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/fs/tmpfs/tmpfs.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/tmpfs/tmpfs.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -30,5 +30,5 @@
 /** @addtogroup fs
  * @{
- */ 
+ */
 
 /**
@@ -43,5 +43,5 @@
 #include "tmpfs.h"
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <errno.h>
@@ -61,117 +61,32 @@
 };
 
-fs_reg_t tmpfs_reg;
-
-/**
- * This connection fibril processes VFS requests from VFS.
- *
- * In order to support simultaneous VFS requests, our design is as follows.
- * The connection fibril accepts VFS requests from VFS. If there is only one
- * instance of the fibril, VFS will need to serialize all VFS requests it sends
- * to FAT. To overcome this bottleneck, VFS can send TMPFS the
- * IPC_M_CONNECT_ME_TO call. In that case, a new connection fibril will be
- * created, which in turn will accept the call. Thus, a new phone will be
- * opened for VFS.
- *
- * There are few issues with this arrangement. First, VFS can run out of
- * available phones. In that case, VFS can close some other phones or use one
- * phone for more serialized requests. Similarily, TMPFS can refuse to duplicate
- * the connection. VFS should then just make use of already existing phones and
- * route its requests through them. To avoid paying the fibril creation price 
- * upon each request, TMPFS might want to keep the connections open after the
- * request has been completed.
- */
-static void tmpfs_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	if (iid) {
-		/*
-		 * This only happens for connections opened by
-		 * IPC_M_CONNECT_ME_TO calls as opposed to callback connections
-		 * created by IPC_M_CONNECT_TO_ME.
-		 */
-		async_answer_0(iid, EOK);
-	}
-	
-	dprintf(NAME ": connection opened\n");
-	while (1) {
-		ipc_callid_t callid;
-		ipc_call_t call;
-	
-		callid = async_get_call(&call);
-		switch  (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			return;
-		case VFS_OUT_MOUNTED:
-			tmpfs_mounted(callid, &call);
-			break;
-		case VFS_OUT_MOUNT:
-			tmpfs_mount(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNTED:
-			tmpfs_unmounted(callid, &call);
-			break;
-		case VFS_OUT_UNMOUNT:
-			tmpfs_unmount(callid, &call);
-			break;
-		case VFS_OUT_LOOKUP:
-			tmpfs_lookup(callid, &call);
-			break;
-		case VFS_OUT_READ:
-			tmpfs_read(callid, &call);
-			break;
-		case VFS_OUT_WRITE:
-			tmpfs_write(callid, &call);
-			break;
-		case VFS_OUT_TRUNCATE:
-			tmpfs_truncate(callid, &call);
-			break;
-		case VFS_OUT_CLOSE:
-			tmpfs_close(callid, &call);
-			break;
-		case VFS_OUT_DESTROY:
-			tmpfs_destroy(callid, &call);
-			break;
-		case VFS_OUT_OPEN_NODE:
-			tmpfs_open_node(callid, &call);
-			break;
-		case VFS_OUT_STAT:
-			tmpfs_stat(callid, &call);
-			break;
-		case VFS_OUT_SYNC:
-			tmpfs_sync(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
 int main(int argc, char **argv)
 {
 	printf(NAME ": HelenOS TMPFS file system server\n");
-
+	
 	if (!tmpfs_init()) {
 		printf(NAME ": failed to initialize TMPFS\n");
 		return -1;
 	}
-
-	int vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
-	if (vfs_phone < EOK) {
+	
+	async_sess_t *vfs_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+	    SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
 		printf(NAME ": Unable to connect to VFS\n");
 		return -1;
 	}
-
-	int rc = fs_register(vfs_phone, &tmpfs_reg, &tmpfs_vfs_info,
-	    tmpfs_connection);
+	
+	int rc = fs_register(vfs_sess, &tmpfs_vfs_info, &tmpfs_ops,
+	    &tmpfs_libfs_ops);
 	if (rc != EOK) {
 		printf(NAME ": Failed to register file system (%d)\n", rc);
 		return rc;
 	}
-
+	
 	printf(NAME ": Accepting connections\n");
 	task_retval(0);
 	async_manager();
-	/* not reached */
+	
+	/* Not reached */
 	return 0;
 }
@@ -179,3 +94,3 @@
 /**
  * @}
- */ 
+ */
Index: uspace/srv/fs/tmpfs/tmpfs.h
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/tmpfs/tmpfs.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -67,27 +67,11 @@
 	size_t size;		/**< File size if type is TMPFS_FILE. */
 	void *data;		/**< File content's if type is TMPFS_FILE. */
-	link_t cs_head;		/**< Head of child's siblings list. */
+	list_t cs_list;		/**< Child's siblings list. */
 } tmpfs_node_t;
 
-extern fs_reg_t tmpfs_reg;
-
+extern vfs_out_ops_t tmpfs_ops;
 extern libfs_ops_t tmpfs_libfs_ops;
 
 extern bool tmpfs_init(void);
-
-extern void tmpfs_mounted(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_mount(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_unmounted(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_unmount(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_lookup(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_read(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_write(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_truncate(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_stat(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_close(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_destroy(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_open_node(ipc_callid_t, ipc_call_t *);
-extern void tmpfs_sync(ipc_callid_t, ipc_call_t *);
-
 extern bool tmpfs_restore(devmap_handle_t);
 
Index: uspace/srv/fs/tmpfs/tmpfs_dump.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/tmpfs/tmpfs_dump.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -167,5 +167,5 @@
 	int rc;
 
-	rc = block_init(dev, TMPFS_COMM_SIZE);
+	rc = block_init(EXCHANGE_SERIALIZE, dev, TMPFS_COMM_SIZE);
 	if (rc != EOK)
 		return false; 
Index: uspace/srv/fs/tmpfs/tmpfs_ops.c
===================================================================
--- uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/fs/tmpfs/tmpfs_ops.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -85,5 +85,5 @@
 static int tmpfs_has_children(bool *has_children, fs_node_t *fn)
 {
-	*has_children = !list_empty(&TMPFS_NODE(fn)->cs_head);
+	*has_children = !list_empty(&TMPFS_NODE(fn)->cs_list);
 	return EOK;
 }
@@ -102,9 +102,4 @@
 {
 	return TMPFS_NODE(fn)->lnkcnt;
-}
-
-static char tmpfs_plb_get_char(unsigned pos)
-{
-	return tmpfs_reg.plb_ro[pos % PLB_SIZE];
 }
 
@@ -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,
@@ -180,7 +174,7 @@
 	    nh_link);
 
-	while (!list_empty(&nodep->cs_head)) {
-		tmpfs_dentry_t *dentryp = list_get_instance(nodep->cs_head.next,
-		    tmpfs_dentry_t, link);
+	while (!list_empty(&nodep->cs_list)) {
+		tmpfs_dentry_t *dentryp = list_get_instance(
+		    list_first(&nodep->cs_list), tmpfs_dentry_t, link);
 
 		assert(nodep->type == TMPFS_DIRECTORY);
@@ -214,5 +208,5 @@
 	nodep->data = NULL;
 	link_initialize(&nodep->nh_link);
-	list_initialize(&nodep->cs_head);
+	list_initialize(&nodep->cs_list);
 }
 
@@ -262,8 +256,6 @@
 {
 	tmpfs_node_t *parentp = TMPFS_NODE(pfn);
-	link_t *lnk;
-
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+
+	list_foreach(parentp->cs_list, lnk) {
 		tmpfs_dentry_t *dentryp;
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
@@ -353,5 +345,5 @@
 	
 	assert(!nodep->lnkcnt);
-	assert(list_empty(&nodep->cs_head));
+	assert(list_empty(&nodep->cs_list));
 
 	unsigned long key[] = {
@@ -373,11 +365,9 @@
 	tmpfs_node_t *childp = TMPFS_NODE(cfn);
 	tmpfs_dentry_t *dentryp;
-	link_t *lnk;
 
 	assert(parentp->type == TMPFS_DIRECTORY);
 
 	/* Check for duplicit entries. */
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+	list_foreach(parentp->cs_list, lnk) {
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);	
 		if (!str_cmp(dentryp->name, nm))
@@ -401,5 +391,5 @@
 	dentryp->node = childp;
 	childp->lnkcnt++;
-	list_append(&dentryp->link, &parentp->cs_head);
+	list_append(&dentryp->link, &parentp->cs_list);
 
 	return EOK;
@@ -411,11 +401,9 @@
 	tmpfs_node_t *childp = NULL;
 	tmpfs_dentry_t *dentryp;
-	link_t *lnk;
 
 	if (!parentp)
 		return EBUSY;
 	
-	for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
-	    lnk = lnk->next) {
+	list_foreach(parentp->cs_list, lnk) {
 		dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
 		if (!str_cmp(dentryp->name, nm)) {
@@ -423,5 +411,5 @@
 			assert(FS_NODE(childp) == cfn);
 			break;
-		}	
+		}
 	}
 
@@ -429,5 +417,5 @@
 		return ENOENT;
 		
-	if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_head))
+	if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_list))
 		return ENOTEMPTY;
 
@@ -439,33 +427,25 @@
 }
 
-void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+/*
+ * Implementation of the VFS_OUT interface.
+ */
+
+static int
+tmpfs_mounted(devmap_handle_t devmap_handle, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
+{
 	fs_node_t *rootfn;
 	int rc;
 	
-	/* Accept the mount options. */
-	char *opts;
-	rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
-	if (rc != EOK) {
-		async_answer_0(rid, rc);
-		return;
-	}
-
 	/* Check if this device is not already mounted. */
 	rc = tmpfs_root_get(&rootfn, devmap_handle);
 	if ((rc == EOK) && (rootfn)) {
 		(void) tmpfs_node_put(rootfn);
-		free(opts);
-		async_answer_0(rid, EEXIST);
-		return;
+		return EEXIST;
 	}
 
 	/* Initialize TMPFS instance. */
-	if (!tmpfs_instance_init(devmap_handle)) {
-		free(opts);
-		async_answer_0(rid, ENOMEM);
-		return;
-	}
+	if (!tmpfs_instance_init(devmap_handle))
+		return ENOMEM;
 
 	rc = tmpfs_root_get(&rootfn, devmap_handle);
@@ -473,46 +453,24 @@
 	tmpfs_node_t *rootp = TMPFS_NODE(rootfn);
 	if (str_cmp(opts, "restore") == 0) {
-		if (tmpfs_restore(devmap_handle))
-			async_answer_3(rid, EOK, rootp->index, rootp->size,
-			    rootp->lnkcnt);
-		else
-			async_answer_0(rid, ELIMIT);
-	} else {
-		async_answer_3(rid, EOK, rootp->index, rootp->size,
-		    rootp->lnkcnt);
-	}
-	free(opts);
-}
-
-void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_mount(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-
+		if (!tmpfs_restore(devmap_handle))
+			return ELIMIT;
+	}
+
+	*index = rootp->index;
+	*size = rootp->size;
+	*lnkcnt = rootp->lnkcnt;
+
+	return EOK;
+}
+
+static int tmpfs_unmounted(devmap_handle_t devmap_handle)
+{
 	tmpfs_instance_done(devmap_handle);
-	async_answer_0(rid, EOK);
-}
-
-void tmpfs_unmount(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_unmount(&tmpfs_libfs_ops, rid, request);
-}
-
-void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
-{
-	libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
-}
-
-void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+	return EOK;
+}
+
+static int tmpfs_read(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *rbytes)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -524,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);
@@ -538,6 +494,5 @@
 	if (!async_data_read_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -550,5 +505,4 @@
 		tmpfs_dentry_t *dentryp;
 		link_t *lnk;
-		aoff64_t i;
 		
 		assert(nodep->type == TMPFS_DIRECTORY);
@@ -559,13 +513,9 @@
 		 * hash table.
 		 */
-		for (i = 0, lnk = nodep->cs_head.next;
-		    (i < pos) && (lnk != &nodep->cs_head);
-		    i++, lnk = lnk->next)
-			;
-
-		if (lnk == &nodep->cs_head) {
+		lnk = list_nth(&nodep->cs_list, pos);
+		
+		if (lnk == NULL) {
 			async_answer_0(callid, ENOENT);
-			async_answer_1(rid, ENOENT, 0);
-			return;
+			return ENOENT;
 		}
 
@@ -577,17 +527,12 @@
 	}
 
-	/*
-	 * Answer the VFS_READ call.
-	 */
-	async_answer_1(rid, EOK, bytes);
-}
-
-void tmpfs_write(ipc_callid_t rid, ipc_call_t *request)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t pos =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+	*rbytes = bytes;
+	return EOK;
+}
+
+static int
+tmpfs_write(devmap_handle_t devmap_handle, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -599,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);
@@ -613,6 +556,5 @@
 	if (!async_data_write_receive(&callid, &size)) {
 		async_answer_0(callid, EINVAL);	
-		async_answer_0(rid, EINVAL);
-		return;
+		return EINVAL;
 	}
 
@@ -622,7 +564,7 @@
 	if (pos + size <= nodep->size) {
 		/* The file size is not changing. */
-		(void) async_data_write_finalize(callid, nodep->data + pos, size);
-		async_answer_2(rid, EOK, size, nodep->size);
-		return;
+		(void) async_data_write_finalize(callid, nodep->data + pos,
+		    size);
+		goto out;
 	}
 	size_t delta = (pos + size) - nodep->size;
@@ -637,6 +579,6 @@
 	if (!newdata) {
 		async_answer_0(callid, ENOMEM);
-		async_answer_2(rid, EOK, 0, nodep->size);
-		return;
+		size = 0;
+		goto out;
 	}
 	/* Clear any newly allocated memory in order to emulate gaps. */
@@ -645,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)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
-	aoff64_t size =
-	    (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
-	
+
+out:
+	*wbytes = size;
+	*nsize = nodep->size;
+	return EOK;
+}
+
+static int tmpfs_truncate(devmap_handle_t devmap_handle, fs_index_t index,
+    aoff64_t size)
+{
 	/*
 	 * Lookup the respective TMPFS node.
@@ -663,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) {
@@ -693,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)
-{
-	devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
-	fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
-	int rc;
-
+	return EOK;
+}
+
+static int tmpfs_close(devmap_handle_t devmap_handle, fs_index_t index)
+{
+	return EOK;
+}
+
+static int tmpfs_destroy(devmap_handle_t devmap_handle, fs_index_t index)
+{
 	link_t *hlp;
 	unsigned long key[] = {
@@ -713,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(devmap_handle_t devmap_handle, fs_index_t index)
 {
 	/*
@@ -739,8 +655,20 @@
 	 * thus the sync operation is a no-op.
 	 */
-	async_answer_0(rid, EOK);
-}
+	return EOK;
+}
+
+vfs_out_ops_t tmpfs_ops = {
+	.mounted = tmpfs_mounted,
+	.unmounted = tmpfs_unmounted,
+	.read = tmpfs_read,
+	.write = tmpfs_write,
+	.truncate = tmpfs_truncate,
+	.close = tmpfs_close,
+	.destroy = tmpfs_destroy,
+	.sync = tmpfs_sync,
+};
 
 /**
  * @}
  */
+
Index: uspace/srv/hid/adb_mouse/Makefile
===================================================================
--- uspace/srv/hid/adb_mouse/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#
-# Copyright (c) 2010 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-EXTRA_CFLAGS = -Iinclude
-BINARY = adb_ms
-
-SOURCES = \
-	adb_mouse.c \
-	adb_dev.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/adb_mouse/adb_dev.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_dev.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,103 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @{
- */ 
-/** @file
- * @brief
- */
-
-#include <ipc/adb.h>
-#include <async.h>
-#include <vfs/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "adb_mouse.h"
-#include "adb_dev.h"
-
-static void adb_dev_events(ipc_callid_t iid, ipc_call_t *icall);
-
-static int dev_phone;
-
-int adb_dev_init(void)
-{
-	const char *input = "/dev/adb/mouse";
-	int input_fd;
-
-	printf(NAME ": open %s\n", input);
-
-	input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s (%d)\n", input, input_fd);
-		return false;
-	}
-
-	dev_phone = fd_phone(input_fd);
-	if (dev_phone < 0) {
-		printf(NAME ": Failed to connect to device\n");
-		return false;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(dev_phone, 0, 0, 0, adb_dev_events) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return false;
-	}
-	
-	return 0;
-}
-
-static void adb_dev_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case IPC_FIRST_USER_METHOD:
-			mouse_handle_data(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/adb_mouse/adb_dev.h
===================================================================
--- uspace/srv/hid/adb_mouse/adb_dev.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef ADBDEV_H_
-#define ADBDEV_H_
-
-#include <sys/types.h>
-
-extern int adb_dev_init(void);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: uspace/srv/hid/adb_mouse/adb_mouse.c
===================================================================
--- uspace/srv/hid/adb_mouse/adb_mouse.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,172 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup mouse
- * @brief ADB Apple classic mouse driver.
- *
- * This driver handles a mouse connected to Apple Desktop Bus speaking
- * the Apple classic protocol. It connects to an ADB driver.
- *
- * @{
- */
-/** @file
- */
-
-#include <ipc/mouse.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <async.h>
-#include <errno.h>
-#include <devmap.h>
-
-#include "adb_mouse.h"
-#include "adb_dev.h"
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall);
-static void mouse_ev_btn(int button, int press);
-static void mouse_ev_move(int dx, int dy);
-
-static int client_phone = -1;
-static bool b1_pressed, b2_pressed;
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": Chardev mouse driver\n");
-
-	/* Initialize device. */
-	if (adb_dev_init() != 0)
-		return -1;
-
-	b1_pressed = false;
-	b2_pressed = false; 
-
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
-	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
-		return -1;
-	}
-
-	char dev_path[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(dev_path, DEVMAP_NAME_MAXLEN, "%s/mouse", NAMESPACE);
-
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(dev_path, &devmap_handle) != EOK) {
-		printf(NAME ": Unable to register device %s\n", dev_path);
-		return -1;
-	}
-
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached. */
-	return 0;
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			if (client_phone != -1) {
-				async_hangup(client_phone);
-				client_phone = -1;
-			}
-
-			async_answer_0(callid, EOK);
-			return;
-		case IPC_M_CONNECT_TO_ME:
-			if (client_phone != -1) {
-				retval = ELIMIT;
-				break;
-			}
-			client_phone = IPC_GET_ARG5(call);
-			retval = 0;
-			break;
-		default:
-			retval = EINVAL;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-void mouse_handle_data(uint16_t data)
-{
-	bool b1, b2;
-	uint16_t udx, udy;
-	int dx, dy;
-
-	/* Extract fields. */
-	b1 = ((data >> 15) & 1) == 0;
-	udy = (data >> 8) & 0x7f;
-	b2 = ((data >> 7) & 1) == 0;
-	udx = data & 0x7f;
-
-	/* Decode 7-bit two's complement signed values. */
-	dx = (udx & 0x40) ? (udx - 0x80) : udx;
-	dy = (udy & 0x40) ? (udy - 0x80) : udy;
-
-	if (b1 != b1_pressed) {
-		mouse_ev_btn(1, b1);
-		b1_pressed = b1;
-	}
-
-	if (b2 != b2_pressed) {
-		mouse_ev_btn(2, b2);
-		b1_pressed = b1;
-	}
-
-	if (dx != 0 || dy != 0)
-		mouse_ev_move(dx, dy);
-}
-
-static void mouse_ev_btn(int button, int press)
-{
-	if (client_phone != -1) {
-		async_msg_2(client_phone, MEVENT_BUTTON, button, press);
-	}
-}
-
-static void mouse_ev_move(int dx, int dy)
-{
-	if (client_phone != -1)
-		async_msg_2(client_phone, MEVENT_MOVE, dx, dy);
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/adb_mouse/adb_mouse.h
===================================================================
--- uspace/srv/hid/adb_mouse/adb_mouse.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef ADB_MOUSE_H_
-#define ADB_MOUSE_H_
-
-#include <sys/types.h>
-
-#define NAME       "adb_ms"
-#define NAMESPACE  "hid_in"
-
-extern void mouse_handle_data(uint16_t);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/hid/char_mouse/Makefile
===================================================================
--- uspace/srv/hid/char_mouse/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,39 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-EXTRA_CFLAGS = -Iinclude
-BINARY = char_ms
-
-SOURCES = \
-	proto/ps2.c \
-	char_mouse.c \
-	chardev.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/char_mouse/char_mouse.c
===================================================================
--- uspace/srv/hid/char_mouse/char_mouse.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,151 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup mouse
- * @brief Chardev mouse driver.
- *
- * This is a common driver for mice attached to simple character devices
- * (PS/2 mice, serial mice).
- *
- * @{
- */
-/** @file
- */
-
-#include <ipc/mouse.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <async.h>
-#include <errno.h>
-#include <devmap.h>
-
-#include <char_mouse.h>
-#include <mouse_port.h>
-#include <mouse_proto.h>
-
-#define NAME       "mouse"
-#define NAMESPACE  "hid_in"
-
-int client_phone = -1;
-
-void mouse_handle_byte(int byte)
-{
-/*	printf("mouse byte: 0x%x\n", byte);*/
-	mouse_proto_parse_byte(byte);
-}
-
-void mouse_ev_btn(int button, int press)
-{
-/*	printf("ev_btn: button %d, press %d\n", button, press);*/
-	if (client_phone != -1) {
-		async_msg_2(client_phone, MEVENT_BUTTON, button, press);
-	}
-}
-
-void mouse_ev_move(int dx, int dy)
-{
-/*	printf("ev_move: dx %d, dy %d\n", dx, dy);*/
-	if (client_phone != -1)
-		async_msg_2(client_phone, MEVENT_MOVE, dx, dy);
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			if (client_phone != -1) {
-				async_hangup(client_phone);
-				client_phone = -1;
-			}
-
-			async_answer_0(callid, EOK);
-			return;
-		case IPC_M_CONNECT_TO_ME:
-			if (client_phone != -1) {
-				retval = ELIMIT;
-				break;
-			}
-			client_phone = IPC_GET_ARG5(call);
-			retval = 0;
-			break;
-		default:
-			retval = EINVAL;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": Chardev mouse driver\n");
-
-	/* Initialize port. */
-	if (mouse_port_init() != 0)
-		return -1;
-
-	/* Initialize protocol driver. */
-	if (mouse_proto_init() != 0)
-		return -1;
-
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
-	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
-		return -1;
-	}
-
-	char dev_path[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(dev_path, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
-
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(dev_path, &devmap_handle) != EOK) {
-		printf(NAME ": Unable to register device %s\n", dev_path);
-		return -1;
-	}
-
-	printf(NAME ": Accepting connections\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached. */
-	return 0;
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/char_mouse/chardev.c
===================================================================
--- uspace/srv/hid/char_mouse/chardev.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,118 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @{
- */ 
-/** @file
- * @brief
- */
-
-#include <ipc/char.h>
-#include <async.h>
-#include <vfs/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <char_mouse.h>
-#include <mouse_port.h>
-
-static void chardev_events(ipc_callid_t iid, ipc_call_t *icall);
-
-static int dev_phone;
-
-#define NAME "char_mouse"
-
-int mouse_port_init(void)
-{
-	const char *input = "/dev/char/ps2b";
-	int input_fd;
-
-	printf(NAME ": open %s\n", input);
-
-	input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s (%d)\n", input, input_fd);
-		return false;
-	}
-
-	dev_phone = fd_phone(input_fd);
-	if (dev_phone < 0) {
-		printf(NAME ": Failed to connect to device\n");
-		return false;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(dev_phone, 0, 0, 0, chardev_events) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return false;
-	}
-
-	return 0;
-}
-
-void mouse_port_yield(void)
-{
-}
-
-void mouse_port_reclaim(void)
-{
-}
-
-void mouse_port_write(uint8_t data)
-{
-	async_msg_1(dev_phone, CHAR_WRITE_BYTE, data);
-}
-
-static void chardev_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case IPC_FIRST_USER_METHOD:
-			mouse_handle_byte(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/char_mouse/include/char_mouse.h
===================================================================
--- uspace/srv/hid/char_mouse/include/char_mouse.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef CHAR_MOUSE_H_
-#define CHAR_MOUSE_H_
-
-extern void mouse_handle_byte(int);
-extern void mouse_ev_btn(int button, int press);
-extern void mouse_ev_move(int dx, int dy);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/hid/char_mouse/include/mouse_port.h
===================================================================
--- uspace/srv/hid/char_mouse/include/mouse_port.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_PORT_H_
-#define MOUSE_PORT_H_
-
-#include <sys/types.h>
-
-extern int mouse_port_init(void);
-extern void mouse_port_yield(void);
-extern void mouse_port_reclaim(void);
-extern void mouse_port_write(uint8_t);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: uspace/srv/hid/char_mouse/include/mouse_proto.h
===================================================================
--- uspace/srv/hid/char_mouse/include/mouse_proto.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @brief
- * @{
- */
-/** @file
- */
-
-#ifndef MOUSE_PROTO_H_
-#define MOUSE_PROTO_H_
-
-extern void mouse_proto_parse_byte(int);
-extern int mouse_proto_init(void);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/hid/char_mouse/proto/ps2.c
===================================================================
--- uspace/srv/hid/char_mouse/proto/ps2.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Copyright (c) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup mouse
- * @{
- */
-/**
- * @file
- * @brief PS/2 mouse protocol driver.
- */
-
-#include <stdio.h>
-#include <mouse_port.h>
-#include <char_mouse.h>
-#include <mouse_proto.h>
-
-#define BUFSIZE 3
-
-#define PS2_MOUSE_OUT_INIT  0xf4
-#define PS2_MOUSE_ACK       0xfa
-
-typedef struct {
-	union {
-		unsigned char data[BUFSIZE];
-		struct {
-			unsigned leftbtn : 1;
-			unsigned rightbtn : 1;
-			unsigned middlebtn : 1;
-			unsigned isone : 1; /* Always one */
-			unsigned xsign : 1;
-			unsigned ysign : 1;
-			unsigned xovfl : 1;
-			unsigned yovfl : 1;
-			unsigned char x;
-			unsigned char y;
-		} val;
-	} u;
-} ps2packet_t;
-
-static ps2packet_t buf;
-static int bufpos = 0;
-static int leftbtn = 0;
-static int rightbtn = 0;
-static int middlebtn = 0;
-
-int mouse_proto_init(void)
-{
-	mouse_port_write(PS2_MOUSE_OUT_INIT);
-	return 0;
-}
-
-/** Convert 9-bit 2-complement signed number to integer */
-static int bit9toint(int sign, unsigned char data)
-{
-	int tmp;
-
-	if (!sign)
-		return data;
-
-	tmp = ((unsigned char)~data) + 1;
-	return -tmp;
-}
-
-/** Process mouse data */
-void mouse_proto_parse_byte(int data)
-{
-	int x, y;
-
-	/* Check that we have not lost synchronization */
-	if (bufpos == 0 && !(data & 0x8))
-		return; /* Synchro lost, ignore byte */
-
-	buf.u.data[bufpos++] = data;
-	if (bufpos == BUFSIZE) {
-		bufpos = 0;
-
-		if (buf.u.val.leftbtn ^ leftbtn) {
-			leftbtn = buf.u.val.leftbtn;
-			mouse_ev_btn(1, leftbtn);
-		}
-
-		if (buf.u.val.rightbtn ^ rightbtn) {
-			rightbtn = buf.u.val.rightbtn;
-			mouse_ev_btn(2, rightbtn);
-		}
-
-		if (buf.u.val.middlebtn ^ middlebtn) {
-			middlebtn = buf.u.val.middlebtn;
-			mouse_ev_btn(3, middlebtn);
-		}
-
-		x =   bit9toint(buf.u.val.xsign, buf.u.val.x);
-		y = - bit9toint(buf.u.val.ysign, buf.u.val.y);
-
-		if (x != 0 || y != 0) {
-			mouse_ev_move(x, y);
-		}
-	}
-
-	return;
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/console/console.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -34,14 +35,16 @@
 
 #include <libc.h>
-#include <ipc/kbd.h>
+#include <ipc/input.h>
 #include <io/keycode.h>
-#include <ipc/mouse.h>
 #include <ipc/fb.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
+#include <ns_obsolete.h>
 #include <errno.h>
+#include <str_error.h>
 #include <ipc/console.h>
 #include <unistd.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <adt/fifo.h>
 #include <sys/mman.h>
@@ -61,13 +64,9 @@
 #include "keybuffer.h"
 
-
 #define NAME       "console"
 #define NAMESPACE  "term"
 
-/** Phone to the keyboard driver. */
-static int kbd_phone;
-
-/** Phone to the mouse driver. */
-static int mouse_phone;
+/** Session with the input server. */
+static async_sess_t *input_sess;
 
 /** Information about framebuffer */
@@ -109,57 +108,85 @@
 static FIBRIL_CONDVAR_INITIALIZE(input_cv);
 
+static FIBRIL_MUTEX_INITIALIZE(big_console_lock);
+
+static void console_serialize_start(void)
+{
+	fibril_mutex_lock(&big_console_lock);
+}
+
+static void console_serialize_end(void)
+{
+	fibril_mutex_unlock(&big_console_lock);
+}
+
 static void curs_visibility(bool visible)
 {
-	async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 
+	async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 
 }
 
 static void curs_hide_sync(void)
 {
-	async_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 
+	async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 
 }
 
 static void curs_goto(sysarg_t x, sysarg_t y)
 {
-	async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
+	async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
 }
 
 static void screen_clear(void)
 {
-	async_msg_0(fb_info.phone, FB_CLEAR);
+	async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
 }
 
 static void screen_yield(void)
 {
-	async_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
+	async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD);
 }
 
 static void screen_reclaim(void)
 {
-	async_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
-}
-
-static void kbd_yield(void)
-{
-	async_req_0_0(kbd_phone, KBD_YIELD);
-}
-
-static void kbd_reclaim(void)
-{
-	async_req_0_0(kbd_phone, KBD_RECLAIM);
+	async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
+}
+
+static void input_yield(void)
+{
+	async_exch_t *exch = async_exchange_begin(input_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with input device.\n",
+		    NAME);
+		return;
+	}
+	
+	async_req_0_0(exch, INPUT_YIELD);
+	async_exchange_end(exch);
+}
+
+static void input_reclaim(void)
+{
+	async_exch_t *exch = async_exchange_begin(input_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with input device.\n",
+		    NAME);
+		return;
+	}
+	
+	async_req_0_0(exch, INPUT_RECLAIM);
+	async_exchange_end(exch);
 }
 
 static void set_style(uint8_t style)
 {
-	async_msg_1(fb_info.phone, FB_SET_STYLE, style);
+	async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style);
 }
 
 static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags)
 {
-	async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
+	async_obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
 }
 
 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
 {
-	async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 
+	async_obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 
 }
 
@@ -216,5 +243,5 @@
 		}
 		
-		async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
+		async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
 		    x0, y0, width, height);
 	}
@@ -257,5 +284,5 @@
 static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row)
 {
-	async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
+	async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
 }
 
@@ -306,5 +333,5 @@
 		
 		if (cons == active_console)
-			async_msg_1(fb_info.phone, FB_SCROLL, 1);
+			async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1);
 	}
 	
@@ -323,12 +350,12 @@
 	
 	if (cons == kernel_console) {
-		async_serialize_start();
+		console_serialize_start();
 		curs_hide_sync();
 		gcons_in_kernel();
 		screen_yield();
-		kbd_yield();
-		async_serialize_end();
-		
-		if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
+		input_yield();
+		console_serialize_end();
+		
+		if (console_kcon()) {
 			prev_console = active_console;
 			active_console = kernel_console;
@@ -338,9 +365,9 @@
 	
 	if (cons != kernel_console) {
-		async_serialize_start();
+		console_serialize_start();
 		
 		if (active_console == kernel_console) {
 			screen_reclaim();
-			kbd_reclaim();
+			input_reclaim();
 			gcons_redraw_console();
 		}
@@ -365,5 +392,5 @@
 			
 			/* This call can preempt, but we are already at the end */
-			rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
+			rc = async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
 			    0, 0, cons->scr.size_x,
 			    cons->scr.size_y);
@@ -393,10 +420,10 @@
 		curs_visibility(cons->scr.is_cursor_visible);
 		
-		async_serialize_end();
-	}
-}
-
-/** Handler for keyboard */
-static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
+		console_serialize_end();
+	}
+}
+
+/** Handler for input events */
+static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	/* Ignore parameters, the connection is already opened */
@@ -406,12 +433,15 @@
 		
 		int retval;
-		console_event_t ev;
+		kbd_event_t ev;
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			async_hangup(input_sess);
+			return;
+		}
 		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case KBD_EVENT:
-			/* Got event from keyboard driver. */
+		case INPUT_EVENT_KEY:
+			/* Got key press/release event */
 			retval = 0;
 			ev.type = IPC_GET_ARG1(call);
@@ -434,26 +464,12 @@
 			fibril_mutex_unlock(&input_mutex);
 			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-/** Handler for mouse events */
-static void mouse_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		int retval;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case MEVENT_BUTTON:
+		case INPUT_EVENT_MOVE:
+			/* Got pointer move event */
+			gcons_mouse_move((int) IPC_GET_ARG1(call),
+			    (int) IPC_GET_ARG2(call));
+			retval = 0;
+			break;
+		case INPUT_EVENT_BUTTON:
+			/* Got pointer button press/release event */
 			if (IPC_GET_ARG1(call) == 1) {
 				int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call));
@@ -463,9 +479,4 @@
 			retval = 0;
 			break;
-		case MEVENT_MOVE:
-			gcons_mouse_move((int) IPC_GET_ARG1(call),
-			    (int) IPC_GET_ARG2(call));
-			retval = 0;
-			break;
 		default:
 			retval = ENOENT;
@@ -487,5 +498,5 @@
 	}
 	
-	async_serialize_start();
+	console_serialize_start();
 	
 	size_t off = 0;
@@ -495,5 +506,5 @@
 	}
 	
-	async_serialize_end();
+	console_serialize_end();
 	
 	gcons_notify_char(cons->index);
@@ -521,5 +532,5 @@
 	
 	size_t pos = 0;
-	console_event_t ev;
+	kbd_event_t ev;
 	fibril_mutex_lock(&input_mutex);
 	
@@ -546,5 +557,5 @@
 static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
 {
-	console_event_t ev;
+	kbd_event_t ev;
 	
 	fibril_mutex_lock(&input_mutex);
@@ -562,5 +573,5 @@
 
 /** Default thread for new connections */
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	console_t *cons = NULL;
@@ -590,5 +601,5 @@
 	int rc;
 	
-	async_serialize_start();
+	console_serialize_start();
 	if (cons->refcount == 0)
 		gcons_notify_connect(cons->index);
@@ -600,7 +611,7 @@
 	
 	while (true) {
-		async_serialize_end();
+		console_serialize_end();
 		callid = async_get_call(&call);
-		async_serialize_start();
+		console_serialize_start();
 		
 		arg1 = 0;
@@ -608,24 +619,27 @@
 		arg3 = 0;
 		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		if (!IPC_GET_IMETHOD(call)) {
 			cons->refcount--;
 			if (cons->refcount == 0)
 				gcons_notify_disconnect(cons->index);
+			console_serialize_end();
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case VFS_OUT_READ:
-			async_serialize_end();
+			console_serialize_end();
 			cons_read(cons, callid, &call);
-			async_serialize_start();
+			console_serialize_start();
 			continue;
 		case VFS_OUT_WRITE:
-			async_serialize_end();
+			console_serialize_end();
 			cons_write(cons, callid, &call);
-			async_serialize_start();
+			console_serialize_start();
 			continue;
 		case VFS_OUT_SYNC:
 			fb_pending_flush();
 			if (cons == active_console) {
-				async_req_0_0(fb_info.phone, FB_FLUSH);
+				async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
 				curs_goto(cons->scr.position_x, cons->scr.position_y);
 			}
@@ -634,5 +648,5 @@
 			/* Send message to fb */
 			if (cons == active_console)
-				async_msg_0(fb_info.phone, FB_CLEAR);
+				async_obsolete_msg_0(fb_info.phone, FB_CLEAR);
 			
 			screenbuffer_clear(&cons->scr);
@@ -693,11 +707,8 @@
 			break;
 		case CONSOLE_GET_EVENT:
-			async_serialize_end();
+			console_serialize_end();
 			cons_get_event(cons, callid, &call);
-			async_serialize_start();
+			console_serialize_start();
 			continue;
-		case CONSOLE_KCON_ENABLE:
-			change_console(kernel_console);
-			break;
 		}
 		async_answer_3(callid, EOK, arg1, arg2, arg3);
@@ -710,55 +721,54 @@
 }
 
-static bool console_init(char *input)
-{
-	/* Connect to input device */
-	int input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s\n", input);
+static async_sess_t *connect_input(const char *dev_path)
+{
+	async_sess_t *sess;
+	async_exch_t *exch;
+	devmap_handle_t handle;
+	
+	int rc = devmap_device_get_handle(dev_path, &handle, 0);
+	if (rc == EOK) {
+		sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+		if (sess == NULL) {
+			printf("%s: Failed to connect to input server\n", NAME);
+			return NULL;
+		}
+	} else {
+		return NULL;
+	}
+	
+	exch = async_exchange_begin(sess);
+	if (exch == NULL) {
+		printf("%s: Failed to create callback from input server.\n", NAME);
+		return NULL;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL);
+
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_hangup(sess);
+		printf("%s: Failed to create callback from input server (%s).\n",
+		    NAME, str_error(rc));
+		return NULL;
+	}
+	
+	return sess;
+}
+
+static bool console_srv_init(char *input_dev)
+{
+	/* Connect to input server */
+	input_sess = connect_input(input_dev);
+	if (input_sess == NULL)
 		return false;
-	}
-	
-	kbd_phone = fd_phone(input_fd);
-	if (kbd_phone < 0) {
-		printf(NAME ": Failed to connect to input device\n");
+	
+	/* Connect to framebuffer driver */
+	fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0);
+	if (fb_info.phone < 0) {
+		printf("%s: Failed to connect to video service\n", NAME);
 		return false;
-	}
-	
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, keyboard_events)
-	    != 0) {
-		printf(NAME ": Failed to create callback from input device\n");
-		return false;
-	}
-	
-	/* Connect to mouse device */
-	mouse_phone = -1;
-	int mouse_fd = open("/dev/hid_in/mouse", O_RDONLY);
-	
-	if (mouse_fd < 0) {
-		printf(NAME ": Notice - failed opening %s\n", "/dev/hid_in/mouse");
-		goto skip_mouse;
-	}
-	
-	mouse_phone = fd_phone(mouse_fd);
-	if (mouse_phone < 0) {
-		printf(NAME ": Failed to connect to mouse device\n");
-		goto skip_mouse;
-	}
-	
-	if (async_connect_to_me(mouse_phone, SERVICE_CONSOLE, 0, 0, mouse_events)
-	    != 0) {
-		printf(NAME ": Failed to create callback from mouse device\n");
-		mouse_phone = -1;
-		goto skip_mouse;
-	}
-	
-skip_mouse:
-	
-	/* Connect to framebuffer driver */
-	fb_info.phone = service_connect_blocking(SERVICE_VIDEO, 0, 0);
-	if (fb_info.phone < 0) {
-		printf(NAME ": Failed to connect to video service\n");
-		return -1;
 	}
 	
@@ -766,5 +776,5 @@
 	int rc = devmap_driver_register(NAME, client_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
+		printf("%s: Unable to register driver (%d)\n", NAME, rc);
 		return false;
 	}
@@ -774,7 +784,7 @@
 	
 	/* Synchronize, the gcons could put something in queue */
-	async_req_0_0(fb_info.phone, FB_FLUSH);
-	async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
-	async_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
+	async_obsolete_req_0_0(fb_info.phone, FB_FLUSH);
+	async_obsolete_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
+	async_obsolete_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap);
 	
 	/* Set up shared memory buffer. */
@@ -787,5 +797,5 @@
 	
 	if (interbuffer) {
-		if (async_share_out_start(fb_info.phone, interbuffer,
+		if (async_obsolete_share_out_start(fb_info.phone, interbuffer,
 		    AS_AREA_READ) != EOK) {
 			as_area_destroy(interbuffer);
@@ -802,5 +812,5 @@
 			if (screenbuffer_init(&consoles[i].scr,
 			    fb_info.cols, fb_info.rows) == NULL) {
-				printf(NAME ": Unable to allocate screen buffer %zu\n", i);
+				printf("%s: Unable to allocate screen buffer %zu\n", NAME, i);
 				return false;
 			}
@@ -814,5 +824,5 @@
 			
 			if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) {
-				printf(NAME ": Unable to register device %s\n", vc);
+				printf("%s: Unable to register device %s\n", NAME, vc);
 				return false;
 			}
@@ -820,9 +830,6 @@
 	}
 	
-	/* Disable kernel output to the console */
-	__SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
-	
 	/* Initialize the screen */
-	async_serialize_start();
+	console_serialize_start();
 	gcons_redraw_console();
 	set_style(STYLE_NORMAL);
@@ -830,10 +837,10 @@
 	curs_goto(0, 0);
 	curs_visibility(active_console->scr.is_cursor_visible);
-	async_serialize_end();
+	console_serialize_end();
 	
 	/* Receive kernel notifications */
 	async_set_interrupt_received(interrupt_received);
 	if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
-		printf(NAME ": Error registering kconsole notifications\n");
+		printf("%s: Error registering kconsole notifications\n", NAME);
 	
 	return true;
@@ -842,5 +849,5 @@
 static void usage(void)
 {
-	printf("Usage: console <input>\n");
+	printf("Usage: console <input_dev>\n");
 }
 
@@ -854,5 +861,5 @@
 	printf(NAME ": HelenOS Console service\n");
 	
-	if (!console_init(argv[1]))
+	if (!console_srv_init(argv[1]))
 		return -1;
 	
Index: uspace/srv/hid/console/gcons.c
===================================================================
--- uspace/srv/hid/console/gcons.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/console/gcons.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -35,4 +35,5 @@
 #include <ipc/fb.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <stdio.h>
 #include <sys/mman.h>
@@ -115,5 +116,5 @@
 static void vp_switch(int vp)
 {
-	async_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
+	async_obsolete_msg_1(fbphone, FB_VIEWPORT_SWITCH, vp);
 }
 
@@ -121,5 +122,5 @@
 static int vp_create(sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height)
 {
-	return async_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
+	return async_obsolete_req_2_0(fbphone, FB_VIEWPORT_CREATE, (x << 16) | y,
 	    (width << 16) | height);
 }
@@ -127,10 +128,10 @@
 static void clear(void)
 {
-	async_msg_0(fbphone, FB_CLEAR);
+	async_obsolete_msg_0(fbphone, FB_CLEAR);
 }
 
 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor)
 {
-	async_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
+	async_obsolete_msg_2(fbphone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
 }
 
@@ -138,5 +139,5 @@
 static void tran_putch(wchar_t ch, sysarg_t col, sysarg_t row)
 {
-	async_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
+	async_obsolete_msg_3(fbphone, FB_PUTCHAR, ch, col, row);
 }
 
@@ -149,5 +150,5 @@
 	
 	if (ic_pixmaps[state] != -1)
-		async_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index],
+		async_obsolete_msg_2(fbphone, FB_VP_DRAW_PIXMAP, cstatus_vp[index],
 		    ic_pixmaps[state]);
 	
@@ -167,6 +168,8 @@
 void gcons_change_console(size_t index)
 {
-	if (!use_gcons)
-		return;
+	if (!use_gcons) {
+		active_console = index;
+		return;
+	}
 	
 	if (active_console == KERNEL_CONSOLE) {
@@ -177,5 +180,5 @@
 		
 		if (animation != -1)
-			async_msg_1(fbphone, FB_ANIM_START, animation);
+			async_obsolete_msg_1(fbphone, FB_ANIM_START, animation);
 	} else {
 		if (console_state[active_console] == CONS_DISCONNECTED_SEL)
@@ -258,5 +261,5 @@
 {
 	if (animation != -1)
-		async_msg_1(fbphone, FB_ANIM_STOP, animation);
+		async_obsolete_msg_1(fbphone, FB_ANIM_STOP, animation);
 	
 	active_console = KERNEL_CONSOLE;
@@ -294,5 +297,5 @@
 	
 	if (active_console != KERNEL_CONSOLE)
-		async_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
+		async_obsolete_msg_2(fbphone, FB_POINTER_MOVE, mouse_x, mouse_y);
 }
 
@@ -374,18 +377,18 @@
 	
 	/* Send area */
-	int rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
+	int rc = async_obsolete_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
 	if (rc)
 		goto exit;
 	
-	rc = async_share_out_start(fbphone, shm, PROTO_READ);
+	rc = async_obsolete_share_out_start(fbphone, shm, PROTO_READ);
 	if (rc)
 		goto drop;
 	
 	/* Draw logo */
-	async_msg_2(fbphone, FB_DRAW_PPM, x, y);
+	async_obsolete_msg_2(fbphone, FB_DRAW_PPM, x, y);
 	
 drop:
 	/* Drop area */
-	async_msg_0(fbphone, FB_DROP_SHM);
+	async_obsolete_msg_0(fbphone, FB_DROP_SHM);
 	
 exit:
@@ -436,14 +439,14 @@
 	
 	/* Send area */
-	int rc = async_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
+	int rc = async_obsolete_req_1_0(fbphone, FB_PREPARE_SHM, (sysarg_t) shm);
 	if (rc)
 		goto exit;
 	
-	rc = async_share_out_start(fbphone, shm, PROTO_READ);
+	rc = async_obsolete_share_out_start(fbphone, shm, PROTO_READ);
 	if (rc)
 		goto drop;
 	
 	/* Obtain pixmap */
-	rc = async_req_0_0(fbphone, FB_SHM2PIXMAP);
+	rc = async_obsolete_req_0_0(fbphone, FB_SHM2PIXMAP);
 	if (rc < 0)
 		goto drop;
@@ -453,5 +456,5 @@
 drop:
 	/* Drop area */
-	async_msg_0(fbphone, FB_DROP_SHM);
+	async_obsolete_msg_0(fbphone, FB_DROP_SHM);
 	
 exit:
@@ -464,5 +467,5 @@
 static void make_anim(void)
 {
-	int an = async_req_1_0(fbphone, FB_ANIM_CREATE,
+	int an = async_obsolete_req_1_0(fbphone, FB_ANIM_CREATE,
 	    cstatus_vp[KERNEL_CONSOLE]);
 	if (an < 0)
@@ -471,19 +474,19 @@
 	int pm = make_pixmap(_binary_gfx_anim_1_ppm_start,
 	    (size_t) &_binary_gfx_anim_1_ppm_size);
-	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 	
 	pm = make_pixmap(_binary_gfx_anim_2_ppm_start,
 	    (size_t) &_binary_gfx_anim_2_ppm_size);
-	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 	
 	pm = make_pixmap(_binary_gfx_anim_3_ppm_start,
 	    (size_t) &_binary_gfx_anim_3_ppm_size);
-	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
 	
 	pm = make_pixmap(_binary_gfx_anim_4_ppm_start,
 	    (size_t) &_binary_gfx_anim_4_ppm_size);
-	async_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
-	
-	async_msg_1(fbphone, FB_ANIM_START, an);
+	async_obsolete_msg_2(fbphone, FB_ANIM_ADDPIXMAP, an, pm);
+	
+	async_obsolete_msg_1(fbphone, FB_ANIM_START, an);
 	
 	animation = an;
@@ -495,5 +498,5 @@
 	fbphone = phone;
 	
-	int rc = async_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
+	int rc = async_obsolete_req_0_2(phone, FB_GET_RESOLUTION, &xres, &yres);
 	if (rc)
 		return;
Index: uspace/srv/hid/console/keybuffer.c
===================================================================
--- uspace/srv/hid/console/keybuffer.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/console/keybuffer.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -90,5 +90,5 @@
  *
  */
-void keybuffer_push(keybuffer_t *keybuffer, const console_event_t *ev)
+void keybuffer_push(keybuffer_t *keybuffer, const kbd_event_t *ev)
 {
 	futex_down(&keybuffer_futex);
@@ -110,5 +110,5 @@
  *
  */
-bool keybuffer_pop(keybuffer_t *keybuffer, console_event_t *edst)
+bool keybuffer_pop(keybuffer_t *keybuffer, kbd_event_t *edst)
 {
 	futex_down(&keybuffer_futex);
Index: uspace/srv/hid/console/keybuffer.h
===================================================================
--- uspace/srv/hid/console/keybuffer.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/console/keybuffer.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -46,5 +46,5 @@
 
 typedef struct {
-	console_event_t fifo[KEYBUFFER_SIZE];
+	kbd_event_t fifo[KEYBUFFER_SIZE];
 	size_t head;
 	size_t tail;
@@ -56,6 +56,6 @@
 extern size_t keybuffer_available(keybuffer_t *);
 extern bool keybuffer_empty(keybuffer_t *);
-extern void keybuffer_push(keybuffer_t *, const console_event_t *);
-extern bool keybuffer_pop(keybuffer_t *, console_event_t *);
+extern void keybuffer_push(keybuffer_t *, const kbd_event_t *);
+extern bool keybuffer_pop(keybuffer_t *, kbd_event_t *);
 
 #endif
Index: uspace/srv/hid/fb/Makefile
===================================================================
--- uspace/srv/hid/fb/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/fb/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -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/ega.c
===================================================================
--- uspace/srv/hid/fb/ega.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/fb/ega.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -52,7 +52,9 @@
 #include <io/screenbuffer.h>
 #include <sys/types.h>
-
 #include "ega.h"
 #include "main.h"
+
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
 
 #define MAX_SAVED_SCREENS  256
@@ -254,5 +256,6 @@
 }
 
-static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void ega_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	size_t intersize = 0;
@@ -291,6 +294,5 @@
 		int retval;
 		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		if (!IPC_GET_IMETHOD(call)) {
 			client_connected = 0;
 			async_answer_0(callid, EOK);
@@ -298,4 +300,7 @@
 			/* Exit thread */
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case IPC_M_SHARE_OUT:
 			/* We accept one area for data interchange */
Index: uspace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/fb/fb.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -59,12 +59,13 @@
 #include <byteorder.h>
 #include <io/screenbuffer.h>
-
 #include "font-8x16.h"
 #include "fb.h"
 #include "main.h"
 #include "ppm.h"
-
 #include "pointer.xbm"
 #include "pointer_mask.xbm"
+
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
 
 #define DEFAULT_BGCOLOR  0xf0f0f0
@@ -1575,5 +1576,6 @@
  *
  */
-static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	unsigned int vp = 0;
@@ -1620,6 +1622,5 @@
 			continue;
 		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		if (!IPC_GET_IMETHOD(call)) {
 			client_connected = false;
 			
@@ -1630,5 +1631,7 @@
 			/* Exit thread */
 			return;
+		}
 		
+		switch (IPC_GET_IMETHOD(call)) {
 		case FB_PUTCHAR:
 			ch = IPC_GET_ARG1(call);
Index: uspace/srv/hid/fb/main.c
===================================================================
--- uspace/srv/hid/fb/main.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/fb/main.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -28,5 +28,5 @@
 
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <sysinfo.h>
 #include <async.h>
@@ -40,5 +40,4 @@
 #include "msim.h"
 #include "ski.h"
-#include "sgcn.h"
 #include "niagara.h"
 #include "main.h"
@@ -92,10 +91,4 @@
 	}
 #endif
-#ifdef SGCN_ENABLED
-	if ((!initialized) && (fb_kind == 4)) {
-		if (sgcn_init() == 0)
-			initialized = true;
-	}
-#endif
 #ifdef NIAGARA_ENABLED
 	if ((!initialized) && (fb_kind == 5)) {
Index: uspace/srv/hid/fb/niagara.c
===================================================================
--- uspace/srv/hid/fb/niagara.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/fb/niagara.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -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 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/fb/niagara.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -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: uspace/srv/hid/fb/serial_console.c
===================================================================
--- uspace/srv/hid/fb/serial_console.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/fb/serial_console.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -52,4 +52,7 @@
 #include "serial_console.h"
 
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
+
 #define MAX_CONTROL 20
 
@@ -312,5 +315,5 @@
  * Main function of the thread serving client connections.
  */
-void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+void serial_client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	keyfield_t *interbuf = NULL;
@@ -344,6 +347,5 @@
 		int retval;
 		
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		if (!IPC_GET_IMETHOD(call)) {
 			client_connected = 0;
 			async_answer_0(callid, EOK);
@@ -351,4 +353,7 @@
 			/* Exit thread */
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case IPC_M_SHARE_OUT:
 			/* We accept one area for data interchange */
Index: uspace/srv/hid/fb/serial_console.h
===================================================================
--- uspace/srv/hid/fb/serial_console.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/fb/serial_console.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -52,5 +52,5 @@
 extern void serial_set_scroll_region(sysarg_t);
 extern void serial_console_init(putc_function_t, sysarg_t, sysarg_t);
-extern void serial_client_connection(ipc_callid_t, ipc_call_t *);
+extern void serial_client_connection(ipc_callid_t, ipc_call_t *, void *arg);
 
 #endif
Index: uspace/srv/hid/fb/sgcn.c
===================================================================
--- uspace/srv/hid/fb/sgcn.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(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: uspace/srv/hid/fb/sgcn.h
===================================================================
--- uspace/srv/hid/fb/sgcn.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(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 a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+EXTRA_CFLAGS = -Iinclude
+BINARY = input
+
+SOURCES = \
+	generic/gsp.c \
+	generic/input.c \
+	generic/layout.c \
+	generic/stroke.c \
+	layout/cz.c \
+	layout/us_qwerty.c \
+	layout/us_dvorak.c \
+	port/adb.c \
+	port/adb_mouse.c \
+	port/chardev.c \
+	port/chardev_mouse.c \
+	port/gxemul.c \
+	port/msim.c \
+	port/niagara.c \
+	port/ns16550.c \
+	port/pl050.c \
+	port/ski.c \
+	proto/adb.c \
+	proto/mousedev.c \
+	proto/ps2.c \
+	ctl/apple.c \
+	ctl/gxe_fb.c \
+	ctl/kbdev.c \
+	ctl/pc.c \
+	ctl/stty.c \
+	ctl/sun.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/input/ctl/apple.c
===================================================================
--- uspace/srv/hid/input/ctl/apple.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/ctl/apple.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Apple ADB keyboard controller driver.
+ */
+
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+
+static void apple_ctl_parse(sysarg_t);
+static int apple_ctl_init(kbd_dev_t *);
+static void apple_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t apple_ctl = {
+	.parse = apple_ctl_parse,
+	.init = apple_ctl_init,
+	.set_ind = apple_ctl_set_ind
+};
+
+#define KBD_KEY_RELEASE		0x80
+
+static kbd_dev_t *kbd_dev;
+
+static int scanmap[];
+
+static int apple_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	return 0;
+}
+
+static void apple_ctl_parse(sysarg_t scancode)
+{
+	kbd_event_type_t type;
+	unsigned int key;
+
+	if (scancode >= 0x100)
+		return;
+
+	if (scancode & KBD_KEY_RELEASE) {
+		scancode &= ~KBD_KEY_RELEASE;
+		type = KEY_RELEASE;
+	} else {
+		type = KEY_PRESS;
+	}
+
+	key = scanmap[scancode];
+	if (key != 0)
+		kbd_push_event(kbd_dev, type, key);
+}
+
+static void apple_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	(void) mods;
+}
+
+static int scanmap[] = {
+	[0x00] = KC_A,
+	[0x01] = KC_S,
+	[0x02] = KC_D,
+	[0x03] = KC_F,
+	[0x04] = KC_H,
+	[0x05] = KC_G,
+	[0x06] = KC_Z,
+	[0x07] = KC_X,
+	[0x08] = KC_C,
+	[0x09] = KC_V,
+	[0x0a] = KC_BACKSLASH,
+	[0x0b] = KC_B,
+	[0x0c] = KC_Q,
+	[0x0d] = KC_W,
+	[0x0e] = KC_E,
+	[0x0f] = KC_R,
+	[0x10] = KC_Y,
+	[0x11] = KC_T,
+	[0x12] = KC_1,
+	[0x13] = KC_2,
+	[0x14] = KC_3,
+	[0x15] = KC_4,
+	[0x16] = KC_6,
+	[0x17] = KC_5,
+	[0x18] = KC_EQUALS,
+	[0x19] = KC_9,
+	[0x1a] = KC_7,
+	[0x1b] = KC_MINUS,
+	[0x1c] = KC_8,
+	[0x1d] = KC_0,
+	[0x1e] = KC_RBRACKET,
+	[0x1f] = KC_O,
+	[0x20] = KC_U,
+	[0x21] = KC_LBRACKET,
+	[0x22] = KC_I,
+	[0x23] = KC_P,
+	[0x24] = KC_ENTER,
+	[0x25] = KC_L,
+	[0x26] = KC_J,
+	[0x27] = KC_QUOTE,
+	[0x28] = KC_K,
+	[0x29] = KC_SEMICOLON,
+	[0x2a] = KC_BACKSLASH,
+	[0x2b] = KC_COMMA,
+	[0x2c] = KC_SLASH,
+	[0x2d] = KC_N,
+	[0x2e] = KC_M,
+	[0x2f] = KC_PERIOD,
+	[0x30] = KC_TAB,
+	[0x31] = KC_SPACE,
+	[0x32] = KC_BACKTICK,
+	[0x33] = KC_BACKSPACE,
+	[0x34] = 0,
+	[0x35] = KC_ESCAPE,
+	[0x36] = KC_LCTRL,
+	[0x37] = 0,
+	[0x38] = KC_LSHIFT,
+	[0x39] = KC_CAPS_LOCK,
+	[0x3a] = KC_LALT,
+	[0x3b] = KC_LEFT,
+	[0x3c] = KC_RIGHT,
+	[0x3d] = KC_DOWN,
+	[0x3e] = KC_UP,
+	[0x3f] = 0,
+	[0x40] = 0,
+	[0x41] = KC_NPERIOD,
+	[0x42] = 0,
+	[0x43] = KC_NTIMES,
+	[0x44] = 0,
+	[0x45] = KC_NPLUS,
+	[0x46] = 0,
+	[0x47] = KC_NUM_LOCK,
+	[0x48] = 0,
+	[0x49] = 0,
+	[0x4a] = 0,
+	[0x4b] = KC_NSLASH,
+	[0x4c] = KC_NENTER,
+	[0x4d] = 0,
+	[0x4e] = KC_NMINUS,
+	[0x4f] = 0,
+	[0x50] = 0,
+	[0x51] = 0,
+	[0x52] = KC_N0,
+	[0x53] = KC_N1,
+	[0x54] = KC_N2,
+	[0x55] = KC_N3,
+	[0x56] = KC_N4,
+	[0x57] = KC_N5,
+	[0x58] = KC_N6,
+	[0x59] = KC_N7,
+	[0x5a] = 0,
+	[0x5b] = KC_N8,
+	[0x5c] = KC_N9,
+	[0x5d] = 0,
+	[0x5e] = 0,
+	[0x5f] = 0,
+	[0x60] = KC_F5,
+	[0x61] = KC_F6,
+	[0x62] = KC_F7,
+	[0x63] = KC_F3,
+	[0x64] = KC_F8,
+	[0x65] = KC_F9,
+	[0x66] = 0,
+	[0x67] = KC_F11,
+	[0x68] = 0,
+	[0x69] = 0,
+	[0x6a] = 0,
+	[0x6b] = KC_SCROLL_LOCK,
+	[0x6c] = 0,
+	[0x6d] = KC_F10,
+	[0x6e] = 0,
+	[0x6f] = KC_F12,
+	[0x70] = 0,
+	[0x71] = 0,
+	[0x72] = KC_INSERT,
+	[0x73] = KC_HOME,
+	[0x74] = KC_PAGE_UP,
+	[0x75] = KC_DELETE,
+	[0x76] = KC_F4,
+	[0x77] = KC_END,
+	[0x78] = KC_F2,
+	[0x79] = KC_PAGE_DOWN,
+	[0x7a] = KC_F1,
+	[0x7b] = KC_RSHIFT,
+	[0x7c] = KC_RALT,
+	[0x7d] = KC_RCTRL,
+	[0x7e] = 0,
+	[0x7f] = 0
+};
+
+/** @}
+ */
Index: uspace/srv/hid/input/ctl/gxe_fb.c
===================================================================
--- uspace/srv/hid/input/ctl/gxe_fb.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/ctl/gxe_fb.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief	GXEmul framebuffer-mode keyboard controller driver.
+ */
+
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+#include <gsp.h>
+#include <stroke.h>
+
+static void gxe_fb_ctl_parse(sysarg_t);
+static int gxe_fb_ctl_init(kbd_dev_t *);
+static void gxe_fb_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t gxe_fb_ctl = {
+	.parse = gxe_fb_ctl_parse,
+	.init = gxe_fb_ctl_init,
+	.set_ind = gxe_fb_ctl_set_ind
+};
+
+static kbd_dev_t *kbd_dev;
+
+/** Scancode parser */
+static gsp_t sp;
+
+/** Current parser state */
+static int ds;
+
+#include <stdio.h>
+
+static int seq_defs[] = {
+	/* Not shifted */
+
+	0,	KC_BACKTICK,	0x60, GSP_END,
+
+	0,	KC_1,		0x31, GSP_END,
+	0,	KC_2,		0x32, GSP_END,
+	0,	KC_3,		0x33, GSP_END,
+	0,	KC_4,		0x34, GSP_END,
+	0,	KC_5,		0x35, GSP_END,
+	0,	KC_6,		0x36, GSP_END,
+	0,	KC_7,		0x37, GSP_END,
+	0,	KC_8,		0x38, GSP_END,
+	0,	KC_9,		0x39, GSP_END,
+	0,	KC_0,		0x30, GSP_END,
+
+	0,	KC_MINUS,	0x2d, GSP_END,
+	0,	KC_EQUALS,	0x3d, GSP_END,
+	0,	KC_BACKSPACE,	0x08, GSP_END,
+
+	0,	KC_TAB,		0x09, GSP_END,
+
+	0,	KC_Q,		0x71, GSP_END,
+	0,	KC_W,		0x77, GSP_END,
+	0,	KC_E,		0x65, GSP_END,
+	0,	KC_R,		0x72, GSP_END,
+	0,	KC_T,		0x74, GSP_END,
+	0,	KC_Y,		0x79, GSP_END,
+	0,	KC_U,		0x75, GSP_END,
+	0,	KC_I,		0x69, GSP_END,
+	0,	KC_O,		0x6f, GSP_END,
+	0,	KC_P,		0x70, GSP_END,
+
+	0,	KC_LBRACKET,	0x5b, GSP_END,
+	0,	KC_RBRACKET,	0x5d, GSP_END,
+
+	0,	KC_A,		0x61, GSP_END,
+	0,	KC_S,		0x73, GSP_END,
+	0,	KC_D,		0x64, GSP_END,
+	0,	KC_F,		0x66, GSP_END,
+	0,	KC_G,		0x67, GSP_END,
+	0,	KC_H,		0x68, GSP_END,
+	0,	KC_J,		0x6a, GSP_END,
+	0,	KC_K,		0x6b, GSP_END,
+	0,	KC_L,		0x6c, GSP_END,
+
+	0,	KC_SEMICOLON,	0x3b, GSP_END,
+	0,	KC_QUOTE,	0x27, GSP_END,
+	0,	KC_BACKSLASH,	0x5c, GSP_END,
+
+	0,	KC_Z,		0x7a, GSP_END,
+	0,	KC_X,		0x78, GSP_END,
+	0,	KC_C,		0x63, GSP_END,
+	0,	KC_V,		0x76, GSP_END,
+	0,	KC_B,		0x62, GSP_END,
+	0,	KC_N,		0x6e, GSP_END,
+	0,	KC_M,		0x6d, GSP_END,
+
+	0,	KC_COMMA,	0x2c, GSP_END,
+	0,	KC_PERIOD,	0x2e, GSP_END,
+	0,	KC_SLASH,	0x2f, GSP_END,
+
+	/* Shifted */
+
+	KM_SHIFT,	KC_BACKTICK,	0x7e, GSP_END,
+
+	KM_SHIFT,	KC_1,		0x21, GSP_END,
+	KM_SHIFT,	KC_2,		0x40, GSP_END,
+	KM_SHIFT,	KC_3,		0x23, GSP_END,
+	KM_SHIFT,	KC_4,		0x24, GSP_END,
+	KM_SHIFT,	KC_5,		0x25, GSP_END,
+	KM_SHIFT,	KC_6,		0x5e, GSP_END,
+	KM_SHIFT,	KC_7,		0x26, GSP_END,
+	KM_SHIFT,	KC_8,		0x2a, GSP_END,
+	KM_SHIFT,	KC_9,		0x28, GSP_END,
+	KM_SHIFT,	KC_0,		0x29, GSP_END,
+
+	KM_SHIFT,	KC_MINUS,	0x5f, GSP_END,
+	KM_SHIFT,	KC_EQUALS,	0x2b, GSP_END,
+
+	KM_SHIFT,	KC_Q,		0x51, GSP_END,
+	KM_SHIFT,	KC_W,		0x57, GSP_END,
+	KM_SHIFT,	KC_E,		0x45, GSP_END,
+	KM_SHIFT,	KC_R,		0x52, GSP_END,
+	KM_SHIFT,	KC_T,		0x54, GSP_END,
+	KM_SHIFT,	KC_Y,		0x59, GSP_END,
+	KM_SHIFT,	KC_U,		0x55, GSP_END,
+	KM_SHIFT,	KC_I,		0x49, GSP_END,
+	KM_SHIFT,	KC_O,		0x4f, GSP_END,
+	KM_SHIFT,	KC_P,		0x50, GSP_END,
+
+	KM_SHIFT,	KC_LBRACKET,	0x7b, GSP_END,
+	KM_SHIFT,	KC_RBRACKET,	0x7d, GSP_END,
+
+	KM_SHIFT,	KC_A,		0x41, GSP_END,
+	KM_SHIFT,	KC_S,		0x53, GSP_END,
+	KM_SHIFT,	KC_D,		0x44, GSP_END,
+	KM_SHIFT,	KC_F,		0x46, GSP_END,
+	KM_SHIFT,	KC_G,		0x47, GSP_END,
+	KM_SHIFT,	KC_H,		0x48, GSP_END,
+	KM_SHIFT,	KC_J,		0x4a, GSP_END,
+	KM_SHIFT,	KC_K,		0x4b, GSP_END,
+	KM_SHIFT,	KC_L,		0x4c, GSP_END,
+
+	KM_SHIFT,	KC_SEMICOLON,	0x3a, GSP_END,
+	KM_SHIFT,	KC_QUOTE,	0x22, GSP_END,
+	KM_SHIFT,	KC_BACKSLASH,	0x7c, GSP_END,
+
+	KM_SHIFT,	KC_Z,		0x5a, GSP_END,
+	KM_SHIFT,	KC_X,		0x58, GSP_END,
+	KM_SHIFT,	KC_C,		0x43, GSP_END,
+	KM_SHIFT,	KC_V,		0x56, GSP_END,
+	KM_SHIFT,	KC_B,		0x42, GSP_END,
+	KM_SHIFT,	KC_N,		0x4e, GSP_END,
+	KM_SHIFT,	KC_M,		0x4d, GSP_END,
+
+	KM_SHIFT,	KC_COMMA,	0x3c, GSP_END,
+	KM_SHIFT,	KC_PERIOD,	0x3e, GSP_END,
+	KM_SHIFT,	KC_SLASH,	0x3f, GSP_END,
+
+	/* ... */
+
+	0,	KC_SPACE,	0x20, GSP_END,
+	0,	KC_ENTER,	0x0a, GSP_END,
+	0,	KC_ENTER,	0x0d, GSP_END,
+
+	0,	KC_ESCAPE,	0x1b, 0x1b, GSP_END,
+
+	0,	KC_F1,		0x1b, 0x5b, 0x4f, 0x50, GSP_END,
+	0,	KC_F2,		0x1b, 0x5b, 0x4f, 0x51, GSP_END,
+	0,	KC_F3,		0x1b, 0x5b, 0x4f, 0x52, GSP_END,
+	0,	KC_F4,		0x1b, 0x5b, 0x4f, 0x53, GSP_END,
+	0,	KC_F5,		0x1b, 0x5b, 0x31, 0x35, GSP_END,
+	0,	KC_F6,		0x1b, 0x5b, 0x31, 0x37, GSP_END,
+	0,	KC_F7,		0x1b, 0x5b, 0x31, 0x38, GSP_END,
+	0,	KC_F8,		0x1b, 0x5b, 0x31, 0x39, GSP_END,
+	0,	KC_F9,		0x1b, 0x5b, 0x32, 0x38, GSP_END,
+	0,	KC_F10,		0x1b, 0x5b, 0x32, 0x39, GSP_END,
+	0,	KC_F11,		0x1b, 0x5b, 0x32, 0x33, GSP_END,
+	0,	KC_F12,		0x1b, 0x5b, 0x32, 0x34, GSP_END,
+
+	0,	KC_INSERT,	0x1b, 0x5b, 0x32, 0x7e, GSP_END,
+	0,	KC_HOME,	0x1b, 0x5b, 0x48, GSP_END,
+	0,	KC_PAGE_UP,	0x1b, 0x5b, 0x35, 0x7e, GSP_END,
+	0,	KC_DELETE,	0x1b, 0x5b, 0x33, 0x7e, GSP_END,
+	0,	KC_END,		0x1b, 0x5b, 0x46, GSP_END,
+	0,	KC_PAGE_DOWN,	0x1b, 0x5b, 0x36, 0x7e, GSP_END,
+
+	0,	KC_UP,		0x1b, 0x5b, 0x41, GSP_END,
+	0,	KC_LEFT,	0x1b, 0x5b, 0x44, GSP_END,
+	0,	KC_DOWN,	0x1b, 0x5b, 0x42, GSP_END,
+	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
+
+	0,	0
+};
+
+static int gxe_fb_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	ds = 0;
+
+	gsp_init(&sp);
+	return gsp_insert_defs(&sp, seq_defs);
+}
+
+static void gxe_fb_ctl_parse(sysarg_t scancode)
+{
+	unsigned mods, key;
+
+	ds = gsp_step(&sp, ds, scancode, &mods, &key);
+	if (key != 0) {
+		stroke_sim(kbd_dev, mods, key);
+	}
+}
+
+static void gxe_fb_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	(void) mods;
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/ctl/kbdev.c
===================================================================
--- uspace/srv/hid/input/ctl/kbdev.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/ctl/kbdev.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Keyboard device connector controller driver.
+ */
+
+#include <async.h>
+#include <bool.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gsp.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <ipc/kbdev.h>
+#include <input.h>
+#include <kbd.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+#include <stdlib.h>
+#include <vfs/vfs_sess.h>
+
+
+static int kbdev_ctl_init(kbd_dev_t *);
+static void kbdev_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+static void kbdev_callback_conn(ipc_callid_t, ipc_call_t *, void *arg);
+
+kbd_ctl_ops_t kbdev_ctl = {
+	.parse = NULL,
+	.init = kbdev_ctl_init,
+	.set_ind = kbdev_ctl_set_ind
+};
+
+/** Kbdev softstate */
+typedef struct {
+	/** Link to generic keyboard device */
+	kbd_dev_t *kbd_dev;
+
+	/** Session with kbdev device */
+	async_sess_t *sess;
+
+	/** File descriptor of open kbdev device */
+	int fd;
+} kbdev_t;
+
+static kbdev_t *kbdev_new(kbd_dev_t *kdev)
+{
+	kbdev_t *kbdev;
+
+	kbdev = calloc(1, sizeof(kbdev_t));
+	if (kbdev == NULL)
+		return NULL;
+
+	kbdev->kbd_dev = kdev;
+	kbdev->fd = -1;
+
+	return kbdev;
+}
+
+static void kbdev_destroy(kbdev_t *kbdev)
+{
+	if (kbdev->sess != NULL)
+		async_hangup(kbdev->sess);
+	if (kbdev->fd >= 0)
+		close(kbdev->fd);
+	free(kbdev);
+}
+
+static int kbdev_ctl_init(kbd_dev_t *kdev)
+{
+	const char *pathname;
+	async_sess_t *sess;
+	async_exch_t *exch;
+	kbdev_t *kbdev;
+	int fd;
+	int rc;
+
+	pathname = kdev->dev_path;
+
+	fd = open(pathname, O_RDWR);
+	if (fd < 0) {
+		return -1;
+	}
+
+	sess = fd_session(EXCHANGE_SERIALIZE, fd);
+	if (sess == NULL) {
+		printf("%s: Failed starting session with '%s'\n", NAME, pathname);
+		close(fd);
+		return -1;
+	}
+
+	kbdev = kbdev_new(kdev);
+	if (kbdev == NULL) {
+		printf("%s: Failed allocating device structure for '%s'.\n",
+		    NAME, pathname);
+		return -1;
+	}
+
+	kbdev->fd = fd;
+	kbdev->sess = sess;
+
+	exch = async_exchange_begin(sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname);
+		kbdev_destroy(kbdev);
+		return -1;
+	}
+
+	rc = async_connect_to_me(exch, 0, 0, 0, kbdev_callback_conn, kbdev);
+	if (rc != EOK) {
+		printf("%s: Failed creating callback connection from '%s'.\n",
+		    NAME, pathname);
+		async_exchange_end(exch);
+		kbdev_destroy(kbdev);
+		return -1;
+	}
+
+	async_exchange_end(exch);
+
+	kdev->ctl_private = (void *) kbdev;
+	return 0;
+}
+
+static void kbdev_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	async_sess_t *sess;
+	async_exch_t *exch;
+
+	sess = ((kbdev_t *) kdev->ctl_private)->sess;
+
+	exch = async_exchange_begin(sess);
+	if (!exch)
+		return;
+
+	async_msg_1(exch, KBDEV_SET_IND, mods);
+	async_exchange_end(exch);
+}
+
+static void kbdev_callback_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	kbdev_t *kbdev;
+	int retval;
+	int type, key;
+
+	/* Kbdev device structure */
+	kbdev = arg;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid;
+
+		callid = async_get_call(&call);
+		if (!IPC_GET_IMETHOD(call)) {
+			/* XXX Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case KBDEV_EVENT:
+			/* Got event from keyboard device */
+			retval = 0;
+			type = IPC_GET_ARG1(call);
+			key = IPC_GET_ARG2(call);
+			kbd_push_event(kbdev->kbd_dev, type, key);
+			break;
+		default:
+			retval = ENOTSUP;
+			break;
+		}
+
+		async_answer_0(callid, retval);
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/ctl/pc.c
===================================================================
--- uspace/srv/hid/input/ctl/pc.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/ctl/pc.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief PC keyboard controller driver.
+ */
+
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+#include <gsp.h>
+
+static void pc_ctl_parse(sysarg_t);
+static int pc_ctl_init(kbd_dev_t *);
+static void pc_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t pc_ctl = {
+	.parse = pc_ctl_parse,
+	.init = pc_ctl_init,
+	.set_ind = pc_ctl_set_ind
+};
+
+enum dec_state {
+	ds_s,
+	ds_e
+};
+
+enum special_code {
+	SC_ACK = 0xfa,
+	SC_NAK = 0xfe
+};
+
+enum lock_ind_bits {
+	LI_SCROLL	= 0x01,
+	LI_NUM		= 0x02,
+	LI_CAPS		= 0x04
+};
+
+enum kbd_command {
+	KBD_CMD_SET_LEDS = 0xed
+};
+
+static enum dec_state ds;
+static kbd_dev_t *kbd_dev;
+
+static int scanmap_simple[] = {
+
+	[0x29] = KC_BACKTICK,
+
+	[0x02] = KC_1,
+	[0x03] = KC_2,
+	[0x04] = KC_3,
+	[0x05] = KC_4,
+	[0x06] = KC_5,
+	[0x07] = KC_6,
+	[0x08] = KC_7,
+	[0x09] = KC_8,
+	[0x0a] = KC_9,
+	[0x0b] = KC_0,
+
+	[0x0c] = KC_MINUS,
+	[0x0d] = KC_EQUALS,
+	[0x0e] = KC_BACKSPACE,
+
+	[0x0f] = KC_TAB,
+
+	[0x10] = KC_Q,
+	[0x11] = KC_W,
+	[0x12] = KC_E,
+	[0x13] = KC_R,
+	[0x14] = KC_T,
+	[0x15] = KC_Y,
+	[0x16] = KC_U,
+	[0x17] = KC_I,
+	[0x18] = KC_O,
+	[0x19] = KC_P,
+
+	[0x1a] = KC_LBRACKET,
+	[0x1b] = KC_RBRACKET,
+
+	[0x3a] = KC_CAPS_LOCK,
+
+	[0x1e] = KC_A,
+	[0x1f] = KC_S,
+	[0x20] = KC_D,
+	[0x21] = KC_F,
+	[0x22] = KC_G,
+	[0x23] = KC_H,
+	[0x24] = KC_J,
+	[0x25] = KC_K,
+	[0x26] = KC_L,
+
+	[0x27] = KC_SEMICOLON,
+	[0x28] = KC_QUOTE,
+	[0x2b] = KC_BACKSLASH,
+
+	[0x2a] = KC_LSHIFT,
+
+	[0x2c] = KC_Z,
+	[0x2d] = KC_X,
+	[0x2e] = KC_C,
+	[0x2f] = KC_V,
+	[0x30] = KC_B,
+	[0x31] = KC_N,
+	[0x32] = KC_M,
+
+	[0x33] = KC_COMMA,
+	[0x34] = KC_PERIOD,
+	[0x35] = KC_SLASH,
+
+	[0x36] = KC_RSHIFT,
+
+	[0x1d] = KC_LCTRL,
+	[0x38] = KC_LALT,
+	[0x39] = KC_SPACE,
+
+	[0x01] = KC_ESCAPE,
+
+	[0x3b] = KC_F1,
+	[0x3c] = KC_F2,
+	[0x3d] = KC_F3,
+	[0x3e] = KC_F4,
+	[0x3f] = KC_F5,
+	[0x40] = KC_F6,
+	[0x41] = KC_F7,
+
+	[0x42] = KC_F8,
+	[0x43] = KC_F9,
+	[0x44] = KC_F10,
+
+	[0x57] = KC_F11,
+	[0x58] = KC_F12,
+
+	[0x46] = KC_SCROLL_LOCK,
+
+	[0x1c] = KC_ENTER,
+
+	[0x45] = KC_NUM_LOCK,
+	[0x37] = KC_NTIMES,
+	[0x4a] = KC_NMINUS,
+	[0x4e] = KC_NPLUS,
+	[0x47] = KC_N7,
+	[0x48] = KC_N8,
+	[0x49] = KC_N9,
+	[0x4b] = KC_N4,
+	[0x4c] = KC_N5,
+	[0x4d] = KC_N6,
+	[0x4f] = KC_N1,
+	[0x50] = KC_N2,
+	[0x51] = KC_N3,
+	[0x52] = KC_N0,
+	[0x53] = KC_NPERIOD
+};
+
+static int scanmap_e0[] = {
+	[0x38] = KC_RALT,
+	[0x1d] = KC_RSHIFT,
+
+	[0x37] = KC_PRTSCR,
+
+	[0x52] = KC_INSERT,
+	[0x47] = KC_HOME,
+	[0x49] = KC_PAGE_UP,
+
+	[0x53] = KC_DELETE,
+	[0x4f] = KC_END,
+	[0x51] = KC_PAGE_DOWN,
+
+	[0x48] = KC_UP,
+	[0x4b] = KC_LEFT,
+	[0x50] = KC_DOWN,
+	[0x4d] = KC_RIGHT,
+
+	[0x35] = KC_NSLASH,
+	[0x1c] = KC_NENTER
+};
+
+static int pc_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	ds = ds_s;
+	return 0;
+}
+
+static void pc_ctl_parse(sysarg_t scancode)
+{
+	kbd_event_type_t type;
+	unsigned int key;
+	int *map;
+	size_t map_length;
+
+	/*
+	 * ACK/NAK are returned as response to us sending a command.
+	 * We are not interested in them.
+	 */
+	if (scancode == SC_ACK || scancode == SC_NAK)
+		return;
+
+	if (scancode == 0xe0) {
+		ds = ds_e;
+		return;
+	}
+
+	switch (ds) {
+	case ds_s:
+		map = scanmap_simple;
+		map_length = sizeof(scanmap_simple) / sizeof(int);
+		break;
+	case ds_e:
+		map = scanmap_e0;
+		map_length = sizeof(scanmap_e0) / sizeof(int);
+		break;
+	default:
+		map = NULL;
+		map_length = 0;
+	}
+
+	ds = ds_s;
+
+	if (scancode & 0x80) {
+		scancode &= ~0x80;
+		type = KEY_RELEASE;
+	} else {
+		type = KEY_PRESS;
+	}
+
+	if ((size_t) scancode >= map_length)
+		return;
+
+	key = map[scancode];
+	if (key != 0)
+		kbd_push_event(kbd_dev, type, key);
+}
+
+static void pc_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	uint8_t b;
+
+	b = 0;
+	if ((mods & KM_CAPS_LOCK) != 0)
+		b = b | LI_CAPS;
+	if ((mods & KM_NUM_LOCK) != 0)
+		b = b | LI_NUM;
+	if ((mods & KM_SCROLL_LOCK) != 0)
+		b = b | LI_SCROLL;
+
+	(*kbd_dev->port_ops->write)(KBD_CMD_SET_LEDS);
+	(*kbd_dev->port_ops->write)(b);
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/ctl/stty.c
===================================================================
--- uspace/srv/hid/input/ctl/stty.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/ctl/stty.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Serial TTY-like keyboard controller driver.
+ *
+ * Keyboard emulation on a serial terminal.
+ */
+
+#include <kbd.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+#include <gsp.h>
+#include <stroke.h>
+
+static void stty_ctl_parse(sysarg_t);
+static int stty_ctl_init(kbd_dev_t *);
+static void stty_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t stty_ctl = {
+	.parse = stty_ctl_parse,
+	.init = stty_ctl_init,
+	.set_ind = stty_ctl_set_ind
+};
+
+static kbd_dev_t *kbd_dev;
+
+/** Scancode parser */
+static gsp_t sp;
+
+/** Current parser state */
+static int ds;
+
+#include <stdio.h>
+
+/**
+ * Sequnece definitions are primarily for Xterm. Additionally we define
+ * sequences that are unique to Gnome terminal -- most are the same but
+ * some differ.
+ */
+static int seq_defs[] = {
+	/* Not shifted */
+
+	0,	KC_BACKTICK,	0x60, GSP_END,
+
+	0,	KC_1,		0x31, GSP_END,
+	0,	KC_2,		0x32, GSP_END,
+	0,	KC_3,		0x33, GSP_END,
+	0,	KC_4,		0x34, GSP_END,
+	0,	KC_5,		0x35, GSP_END,
+	0,	KC_6,		0x36, GSP_END,
+	0,	KC_7,		0x37, GSP_END,
+	0,	KC_8,		0x38, GSP_END,
+	0,	KC_9,		0x39, GSP_END,
+	0,	KC_0,		0x30, GSP_END,
+
+	0,	KC_MINUS,	0x2d, GSP_END,
+	0,	KC_EQUALS,	0x3d, GSP_END,
+
+	0,	KC_BACKSPACE,	0x08, GSP_END,
+
+	0,	KC_TAB,		0x09, GSP_END,
+
+	0,	KC_Q,		0x71, GSP_END,
+	0,	KC_W,		0x77, GSP_END,
+	0,	KC_E,		0x65, GSP_END,
+	0,	KC_R,		0x72, GSP_END,
+	0,	KC_T,		0x74, GSP_END,
+	0,	KC_Y,		0x79, GSP_END,
+	0,	KC_U,		0x75, GSP_END,
+	0,	KC_I,		0x69, GSP_END,
+	0,	KC_O,		0x6f, GSP_END,
+	0,	KC_P,		0x70, GSP_END,
+
+	0,	KC_LBRACKET,	0x5b, GSP_END,
+	0,	KC_RBRACKET,	0x5d, GSP_END,
+
+	0,	KC_A,		0x61, GSP_END,
+	0,	KC_S,		0x73, GSP_END,
+	0,	KC_D,		0x64, GSP_END,
+	0,	KC_F,		0x66, GSP_END,
+	0,	KC_G,		0x67, GSP_END,
+	0,	KC_H,		0x68, GSP_END,
+	0,	KC_J,		0x6a, GSP_END,
+	0,	KC_K,		0x6b, GSP_END,
+	0,	KC_L,		0x6c, GSP_END,
+
+	0,	KC_SEMICOLON,	0x3b, GSP_END,
+	0,	KC_QUOTE,	0x27, GSP_END,
+	0,	KC_BACKSLASH,	0x5c, GSP_END,
+
+	0,	KC_Z,		0x7a, GSP_END,
+	0,	KC_X,		0x78, GSP_END,
+	0,	KC_C,		0x63, GSP_END,
+	0,	KC_V,		0x76, GSP_END,
+	0,	KC_B,		0x62, GSP_END,
+	0,	KC_N,		0x6e, GSP_END,
+	0,	KC_M,		0x6d, GSP_END,
+
+	0,	KC_COMMA,	0x2c, GSP_END,
+	0,	KC_PERIOD,	0x2e, GSP_END,
+	0,	KC_SLASH,	0x2f, GSP_END,
+
+	/* Shifted */
+
+	KM_SHIFT,	KC_BACKTICK,	0x7e, GSP_END,
+
+	KM_SHIFT,	KC_1,		0x21, GSP_END,
+	KM_SHIFT,	KC_2,		0x40, GSP_END,
+	KM_SHIFT,	KC_3,		0x23, GSP_END,
+	KM_SHIFT,	KC_4,		0x24, GSP_END,
+	KM_SHIFT,	KC_5,		0x25, GSP_END,
+	KM_SHIFT,	KC_6,		0x5e, GSP_END,
+	KM_SHIFT,	KC_7,		0x26, GSP_END,
+	KM_SHIFT,	KC_8,		0x2a, GSP_END,
+	KM_SHIFT,	KC_9,		0x28, GSP_END,
+	KM_SHIFT,	KC_0,		0x29, GSP_END,
+
+	KM_SHIFT,	KC_MINUS,	0x5f, GSP_END,
+	KM_SHIFT,	KC_EQUALS,	0x2b, GSP_END,
+
+	KM_SHIFT,	KC_Q,		0x51, GSP_END,
+	KM_SHIFT,	KC_W,		0x57, GSP_END,
+	KM_SHIFT,	KC_E,		0x45, GSP_END,
+	KM_SHIFT,	KC_R,		0x52, GSP_END,
+	KM_SHIFT,	KC_T,		0x54, GSP_END,
+	KM_SHIFT,	KC_Y,		0x59, GSP_END,
+	KM_SHIFT,	KC_U,		0x55, GSP_END,
+	KM_SHIFT,	KC_I,		0x49, GSP_END,
+	KM_SHIFT,	KC_O,		0x4f, GSP_END,
+	KM_SHIFT,	KC_P,		0x50, GSP_END,
+
+	KM_SHIFT,	KC_LBRACKET,	0x7b, GSP_END,
+	KM_SHIFT,	KC_RBRACKET,	0x7d, GSP_END,
+
+	KM_SHIFT,	KC_A,		0x41, GSP_END,
+	KM_SHIFT,	KC_S,		0x53, GSP_END,
+	KM_SHIFT,	KC_D,		0x44, GSP_END,
+	KM_SHIFT,	KC_F,		0x46, GSP_END,
+	KM_SHIFT,	KC_G,		0x47, GSP_END,
+	KM_SHIFT,	KC_H,		0x48, GSP_END,
+	KM_SHIFT,	KC_J,		0x4a, GSP_END,
+	KM_SHIFT,	KC_K,		0x4b, GSP_END,
+	KM_SHIFT,	KC_L,		0x4c, GSP_END,
+
+	KM_SHIFT,	KC_SEMICOLON,	0x3a, GSP_END,
+	KM_SHIFT,	KC_QUOTE,	0x22, GSP_END,
+	KM_SHIFT,	KC_BACKSLASH,	0x7c, GSP_END,
+
+	KM_SHIFT,	KC_Z,		0x5a, GSP_END,
+	KM_SHIFT,	KC_X,		0x58, GSP_END,
+	KM_SHIFT,	KC_C,		0x43, GSP_END,
+	KM_SHIFT,	KC_V,		0x56, GSP_END,
+	KM_SHIFT,	KC_B,		0x42, GSP_END,
+	KM_SHIFT,	KC_N,		0x4e, GSP_END,
+	KM_SHIFT,	KC_M,		0x4d, GSP_END,
+
+	KM_SHIFT,	KC_COMMA,	0x3c, GSP_END,
+	KM_SHIFT,	KC_PERIOD,	0x3e, GSP_END,
+	KM_SHIFT,	KC_SLASH,	0x3f, GSP_END,
+
+	/* ... */
+
+	0,	KC_SPACE,	0x20, GSP_END,
+	0,	KC_ENTER,	0x0a, GSP_END,
+	0,	KC_ENTER,	0x0d, GSP_END,
+
+	0,	KC_ESCAPE,	0x1b, 0x1b, GSP_END,
+
+	0,	KC_F1,		0x1b, 0x4f, 0x50, GSP_END,
+	0,	KC_F2,		0x1b, 0x4f, 0x51, GSP_END,
+	0,	KC_F3,		0x1b, 0x4f, 0x52, GSP_END,
+	0,	KC_F4,		0x1b, 0x4f, 0x53, GSP_END,
+	0,	KC_F5,		0x1b, 0x5b, 0x31, 0x35, 0x7e, GSP_END,
+	0,	KC_F6,		0x1b, 0x5b, 0x31, 0x37, 0x7e, GSP_END,
+	0,	KC_F7,		0x1b, 0x5b, 0x31, 0x38, 0x7e, GSP_END,
+	0,	KC_F8,		0x1b, 0x5b, 0x31, 0x39, 0x7e, GSP_END,
+	0,	KC_F9,		0x1b, 0x5b, 0x32, 0x30, 0x7e, GSP_END,
+	0,	KC_F10,		0x1b, 0x5b, 0x32, 0x31, 0x7e, GSP_END,
+	0,	KC_F11,		0x1b, 0x5b, 0x32, 0x33, 0x7e, GSP_END,
+	0,	KC_F12,		0x1b, 0x5b, 0x32, 0x34, 0x7e, GSP_END,
+
+	0,	KC_INSERT,	0x1b, 0x5b, 0x32, 0x7e, GSP_END,
+	0,	KC_HOME,	0x1b, 0x5b, 0x48, GSP_END,
+	0,	KC_PAGE_UP,	0x1b, 0x5b, 0x35, 0x7e, GSP_END,
+	0,	KC_DELETE,	0x1b, 0x5b, 0x33, 0x7e, GSP_END,
+	0,	KC_END,		0x1b, 0x5b, 0x46, GSP_END,
+	0,	KC_PAGE_DOWN,	0x1b, 0x5b, 0x36, 0x7e, GSP_END,
+
+	0,	KC_UP,		0x1b, 0x5b, 0x41, GSP_END,
+	0,	KC_LEFT,	0x1b, 0x5b, 0x44, GSP_END,
+	0,	KC_DOWN,	0x1b, 0x5b, 0x42, GSP_END,
+	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
+
+	/*
+	 * Sequences specific to Gnome terminal
+	 */
+	0,	KC_BACKSPACE,	0x7f, GSP_END, /* ASCII DEL */
+	0,	KC_HOME,	0x1b, 0x4f, 0x48, GSP_END,
+	0,	KC_END,		0x1b, 0x4f, 0x46, GSP_END,
+
+	0,	0
+};
+
+static int stty_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	ds = 0;
+
+	gsp_init(&sp);
+	return gsp_insert_defs(&sp, seq_defs);
+}
+
+static void stty_ctl_parse(sysarg_t scancode)
+{
+	unsigned mods, key;
+
+	ds = gsp_step(&sp, ds, scancode, &mods, &key);
+	if (key != 0) {
+		stroke_sim(kbd_dev, mods, key);
+	}
+}
+
+static void stty_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	(void) mods;
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/ctl/sun.c
===================================================================
--- uspace/srv/hid/input/ctl/sun.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/ctl/sun.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2006 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_ctl
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Sun keyboard controller driver.
+ */
+
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <kbd_ctl.h>
+#include <kbd_port.h>
+
+static void sun_ctl_parse(sysarg_t);
+static int sun_ctl_init(kbd_dev_t *);
+static void sun_ctl_set_ind(kbd_dev_t *, unsigned int);
+
+kbd_ctl_ops_t sun_ctl = {
+	.parse = sun_ctl_parse,
+	.init = sun_ctl_init,
+	.set_ind = sun_ctl_set_ind
+};
+
+static kbd_dev_t *kbd_dev;
+
+#define KBD_KEY_RELEASE		0x80
+#define KBD_ALL_KEYS_UP		0x7f
+
+static int scanmap_simple[];
+
+static int sun_ctl_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	return 0;
+}
+
+static void sun_ctl_parse(sysarg_t scancode)
+{
+	kbd_event_type_t type;
+	unsigned int key;
+
+	if (scancode >= 0x100)
+		return;
+
+	if (scancode == KBD_ALL_KEYS_UP)
+		return;
+
+	if (scancode & KBD_KEY_RELEASE) {
+		scancode &= ~KBD_KEY_RELEASE;
+		type = KEY_RELEASE;
+	} else {
+		type = KEY_PRESS;
+	}
+
+	key = scanmap_simple[scancode];
+	if (key != 0)
+		kbd_push_event(kbd_dev, type, key);
+}
+
+static void sun_ctl_set_ind(kbd_dev_t *kdev, unsigned mods)
+{
+	(void) mods;
+}
+
+/** Primary meaning of scancodes. */
+static int scanmap_simple[] = {
+	[0x00] = 0,
+	[0x01] = 0,
+	[0x02] = 0,
+	[0x03] = 0,
+	[0x04] = 0,
+	[0x05] = KC_F1,
+	[0x06] = KC_F2,
+	[0x07] = KC_F10,
+	[0x08] = KC_F3,
+	[0x09] = KC_F11,
+	[0x0a] = KC_F4,
+	[0x0b] = KC_F12,
+	[0x0c] = KC_F5,
+	[0x0d] = KC_RALT,
+	[0x0e] = KC_F6,
+	[0x0f] = 0,
+	[0x10] = KC_F7,
+	[0x11] = KC_F8,
+	[0x12] = KC_F9,
+	[0x13] = KC_LALT,
+	[0x14] = KC_UP,
+	[0x15] = KC_PAUSE,
+	[0x16] = 0,
+	[0x17] = KC_SCROLL_LOCK,
+	[0x18] = KC_LEFT,
+	[0x19] = 0,
+	[0x1a] = 0,
+	[0x1b] = KC_DOWN,
+	[0x1c] = KC_RIGHT,
+	[0x1d] = KC_ESCAPE,
+	[0x1e] = KC_1,
+	[0x1f] = KC_2,
+	[0x20] = KC_3,
+	[0x21] = KC_4,
+	[0x22] = KC_5,
+	[0x23] = KC_6,
+	[0x24] = KC_7,
+	[0x25] = KC_8,
+	[0x26] = KC_9,
+	[0x27] = KC_0,
+	[0x28] = KC_MINUS,
+	[0x29] = KC_EQUALS,
+	[0x2a] = KC_BACKTICK,
+	[0x2b] = KC_BACKSPACE,
+	[0x2c] = KC_INSERT,
+	[0x2d] = 0,
+	[0x2e] = KC_NSLASH,
+	[0x2f] = KC_NTIMES,
+	[0x30] = 0,
+	[0x31] = 0,
+	[0x32] = KC_NPERIOD,
+	[0x33] = 0,
+	[0x34] = KC_HOME,
+	[0x35] = KC_TAB,
+	[0x36] = KC_Q,
+	[0x37] = KC_W,
+	[0x38] = KC_E,
+	[0x39] = KC_R,
+	[0x3a] = KC_T,
+	[0x3b] = KC_Y,
+	[0x3c] = KC_U,
+	[0x3d] = KC_I,
+	[0x3e] = KC_O,
+	[0x3f] = KC_P,
+	[0x40] = KC_LBRACKET,
+	[0x41] = KC_RBRACKET,
+	[0x42] = KC_DELETE,
+	[0x43] = 0,
+	[0x44] = KC_N7,
+	[0x45] = KC_N8,
+	[0x46] = KC_N9,
+	[0x47] = KC_NMINUS,
+	[0x48] = 0,
+	[0x49] = 0,
+	[0x4a] = KC_END,
+	[0x4b] = 0,
+	[0x4c] = KC_LCTRL,
+	[0x4d] = KC_A,
+	[0x4e] = KC_S,
+	[0x4f] = KC_D,
+	[0x50] = KC_F,
+	[0x51] = KC_G,
+	[0x52] = KC_H,
+	[0x53] = KC_J,
+	[0x54] = KC_K,
+	[0x55] = KC_L,
+	[0x56] = KC_SEMICOLON,
+	[0x57] = KC_QUOTE,
+	[0x58] = KC_BACKSLASH,
+	[0x59] = KC_ENTER,
+	[0x5a] = KC_NENTER,
+	[0x5b] = KC_N4,
+	[0x5c] = KC_N5,
+	[0x5d] = KC_N6,
+	[0x5e] = KC_N0,
+	[0x5f] = 0,
+	[0x60] = KC_PAGE_UP,
+	[0x61] = 0,
+	[0x62] = KC_NUM_LOCK,
+	[0x63] = KC_LSHIFT,
+	[0x64] = KC_Z,
+	[0x65] = KC_X,
+	[0x66] = KC_C,
+	[0x67] = KC_V,
+	[0x68] = KC_B,
+	[0x69] = KC_N,
+	[0x6a] = KC_M,
+	[0x6b] = KC_COMMA,
+	[0x6c] = KC_PERIOD,
+	[0x6d] = KC_SLASH,
+	[0x6e] = KC_RSHIFT,
+	[0x6f] = 0,
+	[0x70] = KC_N1,
+	[0x71] = KC_N2,
+	[0x72] = KC_N3,
+	[0x73] = 0,
+	[0x74] = 0,
+	[0x75] = 0,
+	[0x76] = 0,
+	[0x77] = KC_CAPS_LOCK,
+	[0x78] = 0,
+	[0x79] = KC_SPACE,
+	[0x7a] = 0,
+	[0x7b] = KC_PAGE_DOWN,
+	[0x7c] = 0,
+	[0x7d] = KC_NPLUS,
+	[0x7e] = 0,
+	[0x7f] = 0
+};
+
+/** @}
+ */
Index: uspace/srv/hid/input/generic/gsp.c
===================================================================
--- uspace/srv/hid/input/generic/gsp.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/generic/gsp.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup kbdgen generic
+ * @ingroup  input
+ * @{
+ */ 
+/** @file
+ * @brief	Generic scancode parser.
+ *
+ * The scancode parser is a simple finite state machine. It is described
+ * using sequences of input symbols (scancodes) and the corresponding output
+ * value (mods, key pair). When the parser recognizes a sequence,
+ * it outputs the value and restarts. If a transition is undefined,
+ * the parser restarts, too.
+ *
+ * Apart from precise values, GSP_DEFAULT allows to catch general cases.
+ * I.e. if we knew that after 0x1b 0x4f there always follow two more
+ * scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END)
+ * with null output. This will force the parser to read the entire sequence,
+ * not leaving garbage on the input if it does not recognize the specific
+ * sequence.
+ */
+
+#include <gsp.h>
+#include <adt/hash_table.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define TRANS_TABLE_CHAINS 256
+
+/*
+ * Hash table operations for the transition function.
+ */
+
+static hash_index_t trans_op_hash(unsigned long key[]);
+static int trans_op_compare(unsigned long key[], hash_count_t keys,
+    link_t *item);
+static void trans_op_remove_callback(link_t *item);
+
+static hash_table_operations_t trans_ops = {
+	.hash = trans_op_hash,
+	.compare = trans_op_compare,
+	.remove_callback = trans_op_remove_callback
+};
+
+static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
+static void trans_insert(gsp_t *p, gsp_trans_t *t);
+static gsp_trans_t *trans_new(void);
+
+/** Initialise scancode parser. */
+void gsp_init(gsp_t *p)
+{
+	p->states = 1;
+	hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);
+}
+
+/** Insert a series of definitions into the parser.
+ *
+ * @param p	The parser.
+ * @param defs	Definition list. Each definition starts with two output values
+ *		(mods, key) and continues with a sequence of input values
+ *		terminated with GSP_END. The definition list is terminated
+ *		with two zeroes (0, 0) for output values.
+ */
+int gsp_insert_defs(gsp_t *p, const int *defs)
+{
+	unsigned mods, key;
+	const int *dp;
+	int rc;
+
+	dp = defs;
+
+	while (1) {
+		/* Read the output values. */
+		mods = *dp++;
+		key = *dp++;
+		if (key == 0) break;
+
+		/* Insert one sequence. */
+		rc = gsp_insert_seq(p, dp, mods, key);
+		if (rc != 0)
+			return rc;
+
+		/* Skip to the next definition. */
+		while (*dp != GSP_END)
+			++dp;
+		++dp;
+	}
+
+	return 0;
+}
+
+/** Insert one sequence into the parser.
+ *
+ * @param p	The parser.
+ * @param seq	Sequence of input values terminated with GSP_END.
+ * @param mods	Corresponsing output value.
+ * @param key	Corresponsing output value.
+ */
+int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
+{
+	int state;
+	gsp_trans_t *t;
+
+	state = 0;
+	t = NULL;
+
+	/* Input sequence must be non-empty. */
+	if (*seq == GSP_END)
+		return -1;
+
+	while (*(seq + 1) != GSP_END) {
+		t = trans_lookup(p, state, *seq);
+		if (t == NULL) {
+			/* Create new state. */
+			t = trans_new();
+			t->old_state = state;
+			t->input = *seq;
+			t->new_state = p->states++;
+
+			t->out_mods = 0;
+			t->out_key = 0;
+
+			trans_insert(p, t);
+		}
+		state = t->new_state;
+		++seq;
+	}
+
+	/* Process the last transition. */
+	t = trans_lookup(p, state, *seq);
+	if (t != NULL) {
+		exit(1);
+		return -1;	/* Conflicting definition. */
+	}
+
+	t = trans_new();
+	t->old_state = state;
+	t->input = *seq;
+	t->new_state = 0;
+
+	t->out_mods = mods;
+	t->out_key = key;
+
+	trans_insert(p, t);
+
+	return 0;
+}
+
+/** Compute one parser step.
+ *
+ * Computes the next state and output values for a given state and input.
+ * This handles everything including restarts and default branches.
+ *
+ * @param p		The parser.
+ * @param state		Old state.
+ * @param input		Input symbol (scancode).
+ * @param mods		Output value (modifier).
+ * @param key		Output value (key).
+ * @return		New state.
+ */
+int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
+{
+	gsp_trans_t *t;
+
+	t = trans_lookup(p, state, input);
+	if (t == NULL) {
+		t = trans_lookup(p, state, GSP_DEFAULT);
+	}
+
+	if (t == NULL) {
+		printf("gsp_step: not found, state=%d, input=0x%x\n",
+		    state, input);
+		*mods = 0;
+		*key = 0;
+		return 0;
+	}
+
+	*mods = t->out_mods;
+	*key = t->out_key;
+
+	return t->new_state;
+}
+
+/** Transition function lookup.
+ *
+ * Returns the value of the transition function for the given state
+ * and input. Note that the transition must be specified precisely,
+ * to obtain the default branch use input = GSP_DEFAULT.
+ *
+ * @param p		Parser.
+ * @param state		Current state.
+ * @param input		Input value.
+ * @return		The transition or @c NULL if not defined.
+ */
+static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
+{
+	link_t *item;
+	unsigned long key[2];
+
+	key[0] = state;
+	key[1] = input;
+
+	item = hash_table_find(&p->trans, key);
+	if (item == NULL) return NULL;
+
+	return hash_table_get_instance(item, gsp_trans_t, link);
+}
+
+/** Define a new transition.
+ *
+ * @param p	The parser.
+ * @param t	Transition with all fields defined.
+ */
+static void trans_insert(gsp_t *p, gsp_trans_t *t)
+{
+	unsigned long key[2];
+
+	key[0] = t->old_state;
+	key[1] = t->input;
+
+	hash_table_insert(&p->trans, key, &t->link);
+}
+
+/** Allocate transition structure. */
+static gsp_trans_t *trans_new(void)
+{
+	gsp_trans_t *t;
+
+	t = malloc(sizeof(gsp_trans_t));
+	if (t == NULL) {
+		printf("Memory allocation failed.\n");
+		exit(1);
+	}
+
+	return t;
+}
+
+/*
+ * Transition function hash table operations.
+ */
+
+static hash_index_t trans_op_hash(unsigned long key[])
+{
+	return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS;
+}
+
+static int trans_op_compare(unsigned long key[], hash_count_t keys,
+    link_t *item)
+{
+	gsp_trans_t *t;
+
+	t = hash_table_get_instance(item, gsp_trans_t, link);
+	return ((key[0] == (unsigned long) t->old_state)
+	    && (key[1] == (unsigned long) t->input));
+}
+
+static void trans_op_remove_callback(link_t *item)
+{
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/generic/input.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#include <adt/list.h>
+#include <ipc/services.h>
+#include <ipc/input.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ns.h>
+#include <ns_obsolete.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <errno.h>
+#include <adt/fifo.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <devmap.h>
+#include <input.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <kbd_ctl.h>
+#include <mouse_proto.h>
+#include <layout.h>
+#include <mouse.h>
+
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
+
+/* In microseconds */
+#define DISCOVERY_POLL_INTERVAL  (10 * 1000 * 1000)
+
+#define NUM_LAYOUTS  3
+
+static layout_ops_t *layout[NUM_LAYOUTS] = {
+	&us_qwerty_ops,
+	&us_dvorak_ops,
+	&cz_ops
+};
+
+static void kbd_devs_yield(void);
+static void kbd_devs_reclaim(void);
+
+int client_phone = -1;
+
+/** List of keyboard devices */
+static list_t kbd_devs;
+
+/** List of mouse devices */
+static list_t mouse_devs;
+
+bool irc_service = false;
+int irc_phone = -1;
+
+void kbd_push_data(kbd_dev_t *kdev, sysarg_t data)
+{
+	(*kdev->ctl_ops->parse)(data);
+}
+
+void mouse_push_data(mouse_dev_t *mdev, sysarg_t data)
+{
+	(*mdev->proto_ops->parse)(data);
+}
+
+void kbd_push_event(kbd_dev_t *kdev, int type, unsigned int key)
+{
+	kbd_event_t ev;
+	unsigned int mod_mask;
+	
+	switch (key) {
+	case KC_LCTRL: mod_mask = KM_LCTRL; break;
+	case KC_RCTRL: mod_mask = KM_RCTRL; break;
+	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
+	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
+	case KC_LALT: mod_mask = KM_LALT; break;
+	case KC_RALT: mod_mask = KM_RALT; break;
+	default: mod_mask = 0; break;
+	}
+	
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS)
+			kdev->mods = kdev->mods | mod_mask;
+		else
+			kdev->mods = kdev->mods & ~mod_mask;
+	}
+	
+	switch (key) {
+	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
+	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
+	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
+	default: mod_mask = 0; break;
+	}
+	
+	if (mod_mask != 0) {
+		if (type == KEY_PRESS) {
+			/*
+			 * Only change lock state on transition from released
+			 * to pressed. This prevents autorepeat from messing
+			 * up the lock state.
+			 */
+			kdev->mods = kdev->mods ^ (mod_mask & ~kdev->lock_keys);
+			kdev->lock_keys = kdev->lock_keys | mod_mask;
+			
+			/* Update keyboard lock indicator lights. */
+			(*kdev->ctl_ops->set_ind)(kdev, kdev->mods);
+		} else {
+			kdev->lock_keys = kdev->lock_keys & ~mod_mask;
+		}
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F1) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[0]);
+		return;
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F2) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[1]);
+		return;
+	}
+	
+	if (type == KEY_PRESS && (kdev->mods & KM_LCTRL) &&
+	    key == KC_F3) {
+		layout_destroy(kdev->active_layout);
+		kdev->active_layout = layout_create(layout[2]);
+		return;
+	}
+	
+	ev.type = type;
+	ev.key = key;
+	ev.mods = kdev->mods;
+	
+	ev.c = layout_parse_ev(kdev->active_layout, &ev);
+	async_obsolete_msg_4(client_phone, INPUT_EVENT_KEY, ev.type, ev.key,
+	    ev.mods, ev.c);
+}
+
+/** Mouse pointer has moved. */
+void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy)
+{
+	async_obsolete_msg_2(client_phone, INPUT_EVENT_MOVE, dx, dy);
+}
+
+/** Mouse button has been pressed. */
+void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press)
+{
+	async_obsolete_msg_2(client_phone, INPUT_EVENT_BUTTON, bnum, press);
+}
+
+static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	int retval;
+	
+	async_answer_0(iid, EOK);
+	
+	while (true) {
+		callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			if (client_phone != -1) {
+				async_obsolete_hangup(client_phone);
+				client_phone = -1;
+			}
+			
+			async_answer_0(callid, EOK);
+			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case IPC_M_CONNECT_TO_ME:
+			if (client_phone != -1) {
+				retval = ELIMIT;
+				break;
+			}
+			client_phone = IPC_GET_ARG5(call);
+			retval = 0;
+			break;
+		case INPUT_YIELD:
+			kbd_devs_yield();
+			retval = 0;
+			break;
+		case INPUT_RECLAIM:
+			kbd_devs_reclaim();
+			retval = 0;
+			break;
+		default:
+			retval = EINVAL;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static kbd_dev_t *kbd_dev_new(void)
+{
+	kbd_dev_t *kdev = calloc(1, sizeof(kbd_dev_t));
+	if (kdev == NULL) {
+		printf("%s: Error allocating keyboard device. "
+		    "Out of memory.\n", NAME);
+		return NULL;
+	}
+	
+	link_initialize(&kdev->kbd_devs);
+	
+	kdev->mods = KM_NUM_LOCK;
+	kdev->lock_keys = 0;
+	kdev->active_layout = layout_create(layout[0]);
+	
+	return kdev;
+}
+
+static mouse_dev_t *mouse_dev_new(void)
+{
+	mouse_dev_t *mdev = calloc(1, sizeof(mouse_dev_t));
+	if (mdev == NULL) {
+		printf("%s: Error allocating keyboard device. "
+		    "Out of memory.\n", NAME);
+		return NULL;
+	}
+	
+	link_initialize(&mdev->mouse_devs);
+	
+	return mdev;
+}
+
+/** Add new legacy keyboard device. */
+static void kbd_add_dev(kbd_port_ops_t *port, kbd_ctl_ops_t *ctl)
+{
+	kbd_dev_t *kdev = kbd_dev_new();
+	if (kdev == NULL)
+		return;
+	
+	kdev->port_ops = port;
+	kdev->ctl_ops = ctl;
+	kdev->dev_path = NULL;
+	
+	/* Initialize port driver. */
+	if ((*kdev->port_ops->init)(kdev) != 0)
+		goto fail;
+	
+	/* Initialize controller driver. */
+	if ((*kdev->ctl_ops->init)(kdev) != 0) {
+		/* XXX Uninit port */
+		goto fail;
+	}
+	
+	list_append(&kdev->kbd_devs, &kbd_devs);
+	return;
+	
+fail:
+	free(kdev);
+}
+
+/** Add new legacy mouse device. */
+static void mouse_add_dev(mouse_port_ops_t *port, mouse_proto_ops_t *proto)
+{
+	mouse_dev_t *mdev = mouse_dev_new();
+	if (mdev == NULL)
+		return;
+	
+	mdev->port_ops = port;
+	mdev->proto_ops = proto;
+	mdev->dev_path = NULL;
+	
+	/* Initialize port driver. */
+	if ((*mdev->port_ops->init)(mdev) != 0)
+		goto fail;
+	
+	/* Initialize protocol driver. */
+	if ((*mdev->proto_ops->init)(mdev) != 0) {
+		/* XXX Uninit port */
+		goto fail;
+	}
+	
+	list_append(&mdev->mouse_devs, &mouse_devs);
+	return;
+	
+fail:
+	free(mdev);
+}
+
+/** Add new kbdev device.
+ *
+ * @param dev_path Filesystem path to the device (/dev/class/...)
+ *
+ */
+static int kbd_add_kbdev(const char *dev_path)
+{
+	kbd_dev_t *kdev = kbd_dev_new();
+	if (kdev == NULL)
+		return -1;
+	
+	kdev->dev_path = dev_path;
+	kdev->port_ops = NULL;
+	kdev->ctl_ops = &kbdev_ctl;
+	
+	/* Initialize controller driver. */
+	if ((*kdev->ctl_ops->init)(kdev) != 0) {
+		goto fail;
+	}
+	
+	list_append(&kdev->kbd_devs, &kbd_devs);
+	return EOK;
+	
+fail:
+	free(kdev);
+	return -1;
+}
+
+/** Add new mousedev device.
+ *
+ * @param dev_path Filesystem path to the device (/dev/class/...)
+ *
+ */
+static int mouse_add_mousedev(const char *dev_path)
+{
+	mouse_dev_t *mdev = mouse_dev_new();
+	if (mdev == NULL)
+		return -1;
+	
+	mdev->dev_path = dev_path;
+	mdev->port_ops = NULL;
+	mdev->proto_ops = &mousedev_proto;
+	
+	/* Initialize controller driver. */
+	if ((*mdev->proto_ops->init)(mdev) != 0) {
+		goto fail;
+	}
+	
+	list_append(&mdev->mouse_devs, &mouse_devs);
+	return EOK;
+	
+fail:
+	free(mdev);
+	return -1;
+}
+
+/** Add legacy drivers/devices. */
+static void kbd_add_legacy_devs(void)
+{
+	/*
+	 * Need to add these drivers based on config unless we can probe
+	 * them automatically.
+	 */
+#if defined(UARCH_amd64)
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_gta02)
+	kbd_add_dev(&chardev_port, &stty_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_testarm) && defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_testarm) && !defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &stty_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_integratorcp)
+	kbd_add_dev(&pl050_port, &pc_ctl);
+#endif
+#if defined(UARCH_ia32)
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(MACHINE_i460GX)
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(MACHINE_ski)
+	kbd_add_dev(&ski_port, &stty_ctl);
+#endif
+#if defined(MACHINE_msim)
+	kbd_add_dev(&msim_port, &stty_ctl);
+#endif
+#if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
+#endif
+#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) && !defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &stty_ctl);
+#endif
+#if defined(UARCH_ppc32)
+	kbd_add_dev(&adb_port, &apple_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(PROCESSOR_sun4v)
+	kbd_add_dev(&niagara_port, &stty_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(MACHINE_generic)
+	kbd_add_dev(&ns16550_port, &sun_ctl);
+#endif
+	/* Silence warning on abs32le about kbd_add_dev() being unused */
+	(void) kbd_add_dev;
+}
+
+/** Add legacy drivers/devices. */
+static void mouse_add_legacy_devs(void)
+{
+	/*
+	 * Need to add these drivers based on config unless we can probe
+	 * them automatically.
+	 */
+#if defined(UARCH_amd64)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(UARCH_ia32)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(MACHINE_i460GX)
+	mouse_add_dev(&chardev_mouse_port, &ps2_proto);
+#endif
+#if defined(UARCH_ppc32)
+	mouse_add_dev(&adb_mouse_port, &adb_proto);
+#endif
+	/* Silence warning on abs32le about mouse_add_dev() being unused */
+	(void) mouse_add_dev;
+}
+
+static void kbd_devs_yield(void)
+{
+	/* For each keyboard device */
+	list_foreach(kbd_devs, kdev_link) {
+		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
+		    kbd_devs);
+		
+		/* Yield port */
+		if (kdev->port_ops != NULL)
+			(*kdev->port_ops->yield)();
+	}
+}
+
+static void kbd_devs_reclaim(void)
+{
+	/* For each keyboard device */
+	list_foreach(kbd_devs, kdev_link) {
+		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
+		    kbd_devs);
+		
+		/* Reclaim port */
+		if (kdev->port_ops != NULL)
+			(*kdev->port_ops->reclaim)();
+	}
+}
+
+/** Periodically check for new input devices.
+ *
+ * Looks under /dev/class/keyboard and /dev/class/mouse.
+ *
+ * @param arg Ignored
+ *
+ */
+static int dev_discovery_fibril(void *arg)
+{
+	char *dev_path;
+	size_t kbd_id = 1;
+	size_t mouse_id = 1;
+	int rc;
+	
+	while (true) {
+		async_usleep(DISCOVERY_POLL_INTERVAL);
+		
+		/*
+		 * Check for new keyboard device
+		 */
+		rc = asprintf(&dev_path, "/dev/class/keyboard\\%zu", kbd_id);
+		if (rc < 0)
+			continue;
+		
+		if (kbd_add_kbdev(dev_path) == EOK) {
+			printf("%s: Connected keyboard device '%s'\n",
+			    NAME, dev_path);
+			
+			/* XXX Handle device removal */
+			++kbd_id;
+		}
+		
+		free(dev_path);
+		
+		/*
+		 * Check for new mouse device
+		 */
+		rc = asprintf(&dev_path, "/dev/class/mouse\\%zu", mouse_id);
+		if (rc < 0)
+			continue;
+		
+		if (mouse_add_mousedev(dev_path) == EOK) {
+			printf("%s: Connected mouse device '%s'\n",
+			    NAME, dev_path);
+			
+			/* XXX Handle device removal */
+			++mouse_id;
+		}
+		
+		free(dev_path);
+	}
+	
+	return EOK;
+}
+
+/** Start a fibril for discovering new devices. */
+static void input_start_dev_discovery(void)
+{
+	fid_t fid = fibril_create(dev_discovery_fibril, NULL);
+	if (!fid) {
+		printf("%s: Failed to create device discovery fibril.\n",
+		    NAME);
+		return;
+	}
+	
+	fibril_add_ready(fid);
+}
+
+int main(int argc, char **argv)
+{
+	printf("%s: HelenOS input service\n", NAME);
+	
+	sysarg_t obio;
+	
+	list_initialize(&kbd_devs);
+	list_initialize(&mouse_devs);
+	
+	if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio))
+		irc_service = true;
+	
+	if (irc_service) {
+		while (irc_phone < 0)
+			irc_phone = service_obsolete_connect_blocking(SERVICE_IRC, 0, 0);
+	}
+	
+	/* Add legacy keyboard devices. */
+	kbd_add_legacy_devs();
+	
+	/* Add legacy mouse devices. */
+	mouse_add_legacy_devs();
+	
+	/* Register driver */
+	int rc = devmap_driver_register(NAME, client_connection);
+	if (rc < 0) {
+		printf("%s: Unable to register driver (%d)\n", NAME, rc);
+		return -1;
+	}
+	
+	char kbd[DEVMAP_NAME_MAXLEN + 1];
+	snprintf(kbd, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
+	
+	devmap_handle_t devmap_handle;
+	if (devmap_device_register(kbd, &devmap_handle) != EOK) {
+		printf("%s: Unable to register device %s\n", NAME, kbd);
+		return -1;
+	}
+	
+	/* Start looking for new input devices */
+	input_start_dev_discovery();
+	
+	printf("%s: Accepting connections\n", NAME);
+	async_manager();
+	
+	/* Not reached. */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/generic/layout.c
===================================================================
--- uspace/srv/hid/input/generic/layout.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/generic/layout.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @addtogroup inputgen generic
+ * @brief Keyboard layouts
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#include <errno.h>
+#include <input.h>
+#include <layout.h>
+#include <stdlib.h>
+
+/** Create a new layout instance. */
+layout_t *layout_create(layout_ops_t *ops)
+{
+	layout_t *layout;
+
+	layout = calloc(1, sizeof(layout_t));
+	if (layout == NULL) {
+		printf("%s: Out of memory.\n", NAME);
+		return NULL;
+	}
+
+	layout->ops = ops;
+	if ((*ops->create)(layout) != EOK) {
+		free(layout);
+		return NULL;
+	}
+
+	return layout;
+}
+
+/** Destroy layout instance. */
+void layout_destroy(layout_t *layout)
+{
+	(*layout->ops->destroy)(layout);
+	free(layout);
+}
+
+/** Parse keyboard event. */
+wchar_t layout_parse_ev(layout_t *layout, kbd_event_t *ev)
+{
+	return (*layout->ops->parse_ev)(layout, ev);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/generic/stroke.c
===================================================================
--- uspace/srv/hid/input/generic/stroke.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/generic/stroke.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Stroke simulator.
+ *
+ * When simulating a keyboard using a serial TTY we need to convert the
+ * recognized strokes (such as Shift-A) to sequences of key presses and
+ * releases (such as 'press Shift, press A, release A, release Shift').
+ *
+ */
+
+#include <stroke.h>
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+
+/** Correspondence between modifers and the modifier keycodes. */
+static unsigned int mods_keys[][2] = {
+	{ KM_LSHIFT, KC_LSHIFT },
+	{ 0, 0 }
+};
+
+/** Simulate keystroke using sequences of key presses and releases. */
+void stroke_sim(kbd_dev_t *kdev, unsigned mod, unsigned key)
+{
+	int i;
+
+	/* Simulate modifier presses. */
+	i = 0;
+	while (mods_keys[i][0] != 0) {
+		if (mod & mods_keys[i][0]) {
+			kbd_push_event(kdev, KEY_PRESS, mods_keys[i][1]);
+		}
+		++i;
+	}
+
+	/* Simulate key press and release. */
+	if (key != 0) {
+		kbd_push_event(kdev, KEY_PRESS, key);
+		kbd_push_event(kdev, KEY_RELEASE, key);
+	}
+
+	/* Simulate modifier releases. */
+	i = 0;
+	while (mods_keys[i][0] != 0) {
+		if (mod & mods_keys[i][0]) {
+			kbd_push_event(kdev, KEY_RELEASE, mods_keys[i][1]);
+		}
+		++i;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/gsp.h
===================================================================
--- uspace/srv/hid/input/include/gsp.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/gsp.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief	Generic scancode parser.
+ * @ingroup  input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_GSP_H_
+#define KBD_GSP_H_
+
+#include <adt/hash_table.h>
+
+enum {
+	GSP_END		= -1,	/**< Terminates a sequence. */
+	GSP_DEFAULT	= -2	/**< Wildcard, catches unhandled cases. */
+};
+
+/** Scancode parser description */
+typedef struct {
+	/** Transition table, (state, input) -> (state, output) */
+	hash_table_t trans;
+
+	/** Number of states */
+	int states;
+} gsp_t;
+
+/** Scancode parser transition. */
+typedef struct {
+	link_t link;		/**< Link to hash table in @c gsp_t */ 
+
+	/* Preconditions */
+
+	int old_state;		/**< State before transition */
+	int input;		/**< Input symbol (scancode) */
+
+	/* Effects */
+
+	int new_state;		/**< State after transition */
+
+	/* Output emitted during transition */
+
+	unsigned out_mods;	/**< Modifier to emit */
+	unsigned out_key;	/**< Keycode to emit */
+} gsp_trans_t;
+
+extern void gsp_init(gsp_t *);
+extern int gsp_insert_defs(gsp_t *, const int *);
+extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned);
+extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *);
+
+#endif
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/include/input.h
===================================================================
--- uspace/srv/hid/input/include/input.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/input.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef INPUT_H_
+#define INPUT_H_
+
+#include <bool.h>
+
+#define NAME       "input"
+#define NAMESPACE  "hid"
+
+extern bool irc_service;
+extern int irc_phone;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/kbd.h
===================================================================
--- uspace/srv/hid/input/include/kbd.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/kbd.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief HelenOS input server.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_KBD_H_
+#define KBD_KBD_H_
+
+#include <adt/list.h>
+
+struct kbd_port_ops;
+struct kbd_ctl_ops;
+struct layout;
+
+typedef struct kbd_dev {
+	/** Link to kbd_devs list */
+	link_t kbd_devs;
+
+	/** Path to the device (only for kbdev devices) */
+	const char *dev_path;
+
+	/** Port ops */
+	struct kbd_port_ops *port_ops;
+
+	/** Ctl ops */
+	struct kbd_ctl_ops *ctl_ops;
+
+	/** Controller-private data */
+	void *ctl_private;
+
+	/** Currently active modifiers. */
+	unsigned mods;
+
+	/** Currently pressed lock keys. We track these to tackle autorepeat. */
+	unsigned lock_keys;
+
+	/** Active keyboard layout */
+	struct layout *active_layout;
+} kbd_dev_t;
+
+extern void kbd_push_data(kbd_dev_t *, sysarg_t);
+extern void kbd_push_event(kbd_dev_t *, int, unsigned int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/kbd_ctl.h
===================================================================
--- uspace/srv/hid/input/include/kbd_ctl.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/kbd_ctl.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Keyboard controller driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_CTL_H_
+#define KBD_CTL_H_
+
+#include <kbd_port.h>
+
+struct kbd_dev;
+
+typedef struct kbd_ctl_ops {
+	void (*parse)(sysarg_t);
+	int (*init)(struct kbd_dev *);
+	void (*set_ind)(struct kbd_dev *, unsigned int);
+} kbd_ctl_ops_t;
+
+extern kbd_ctl_ops_t apple_ctl;
+extern kbd_ctl_ops_t gxe_fb_ctl;
+extern kbd_ctl_ops_t kbdev_ctl;
+extern kbd_ctl_ops_t pc_ctl;
+extern kbd_ctl_ops_t stty_ctl;
+extern kbd_ctl_ops_t sun_ctl;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/kbd_port.h
===================================================================
--- uspace/srv/hid/input/include/kbd_port.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/kbd_port.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Keyboard port driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_PORT_H_
+#define KBD_PORT_H_
+
+#include <sys/types.h>
+
+struct kbd_dev;
+
+typedef struct kbd_port_ops {
+	int (*init)(struct kbd_dev *);
+	void (*yield)(void);
+	void (*reclaim)(void);
+	void (*write)(uint8_t);
+} kbd_port_ops_t;
+
+extern kbd_port_ops_t adb_port;
+extern kbd_port_ops_t chardev_port;
+extern kbd_port_ops_t gxemul_port;
+extern kbd_port_ops_t msim_port;
+extern kbd_port_ops_t niagara_port;
+extern kbd_port_ops_t ns16550_port;
+extern kbd_port_ops_t pl050_port;
+extern kbd_port_ops_t ski_port;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/layout.h
===================================================================
--- uspace/srv/hid/input/include/layout.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/layout.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Keyboard layout interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_LAYOUT_H_
+#define KBD_LAYOUT_H_
+
+#include <sys/types.h>
+#include <io/console.h>
+
+/** Layout instance state */
+typedef struct layout {
+	/** Ops structure */
+	struct layout_ops *ops;
+
+	/* Layout-private data */
+	void *layout_priv;
+} layout_t;
+
+/** Layout ops */
+typedef struct layout_ops {
+	int (*create)(layout_t *);
+	void (*destroy)(layout_t *);
+	wchar_t (*parse_ev)(layout_t *, kbd_event_t *);
+} layout_ops_t;
+
+extern layout_ops_t us_qwerty_ops;
+extern layout_ops_t us_dvorak_ops;
+extern layout_ops_t cz_ops;
+
+extern layout_t *layout_create(layout_ops_t *);
+extern void layout_destroy(layout_t *);
+extern wchar_t layout_parse_ev(layout_t *, kbd_event_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/mouse.h
===================================================================
--- uspace/srv/hid/input/include/mouse.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/mouse.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Mouse device handling.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_H_
+#define MOUSE_H_
+
+#include <adt/list.h>
+
+struct mouse_port_ops;
+struct mouse_proto_ops;
+
+typedef struct mouse_dev {
+	/** Link to mouse_devs list */
+	link_t mouse_devs;
+	
+	/** Path to the device (only for mouseev devices) */
+	const char *dev_path;
+	
+	/** Port ops */
+	struct mouse_port_ops *port_ops;
+	
+	/** Protocol ops */
+	struct mouse_proto_ops *proto_ops;
+} mouse_dev_t;
+
+extern void mouse_push_data(mouse_dev_t *, sysarg_t);
+extern void mouse_push_event_move(mouse_dev_t *, int, int);
+extern void mouse_push_event_button(mouse_dev_t *, int, int);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/mouse_port.h
===================================================================
--- uspace/srv/hid/input/include/mouse_port.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/mouse_port.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Mouse port driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_PORT_H_
+#define MOUSE_PORT_H_
+
+#include <sys/types.h>
+
+struct mouse_dev;
+
+typedef struct mouse_port_ops {
+	int (*init)(struct mouse_dev *);
+	void (*yield)(void);
+	void (*reclaim)(void);
+	void (*write)(uint8_t);
+} mouse_port_ops_t;
+
+extern mouse_port_ops_t adb_mouse_port;
+extern mouse_port_ops_t chardev_mouse_port;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/mouse_proto.h
===================================================================
--- uspace/srv/hid/input/include/mouse_proto.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/mouse_proto.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief Mouse protocol driver interface.
+ * @ingroup input
+ * @{
+ */
+/** @file
+ */
+
+#ifndef MOUSE_PROTO_H_
+#define MOUSE_PROTO_H_
+
+#include <mouse_port.h>
+
+struct mouse_dev;
+
+typedef struct mouse_proto_ops {
+	void (*parse)(sysarg_t);
+	int (*init)(struct mouse_dev *);
+} mouse_proto_ops_t;
+
+extern mouse_proto_ops_t adb_proto;
+extern mouse_proto_ops_t ps2_proto;
+extern mouse_proto_ops_t mousedev_proto;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/include/stroke.h
===================================================================
--- uspace/srv/hid/input/include/stroke.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/stroke.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inputgen generic
+ * @brief	Generic scancode parser.
+ * @ingroup  input
+ * @{
+ */ 
+/** @file
+ */
+
+#ifndef KBD_STROKE_H_
+#define KBD_STROKE_H_
+
+#include <kbd.h>
+
+extern void stroke_sim(kbd_dev_t *, unsigned, unsigned);
+
+#endif
+
+/**
+ * @}
+ */ 
+
Index: uspace/srv/hid/input/include/sun.h
===================================================================
--- uspace/srv/hid/input/include/sun.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/include/sun.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2009 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbdgen generic
+ * @brief Sun keyboard virtual port driver.
+ * @ingroup kbd
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KBD_SUN_H_
+#define KBD_SUN_H_
+
+extern int ns16550_port_init(void);
+extern int z8530_port_init(void);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout/cz.c
===================================================================
--- uspace/srv/hid/input/layout/cz.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/layout/cz.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @brief Czech QWERTZ layout.
+ * @{
+ */
+
+#include <errno.h>
+#include <input.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <bool.h>
+#include <layout.h>
+#include <stdlib.h>
+
+static int cz_create(layout_t *);
+static void cz_destroy(layout_t *);
+static wchar_t cz_parse_ev(layout_t *, kbd_event_t *ev);
+
+enum m_state {
+	ms_start,
+	ms_hacek,
+	ms_carka
+};
+
+typedef struct {
+	enum m_state mstate;
+} layout_cz_t;
+
+layout_ops_t cz_ops = {
+	.create = cz_create,
+	.destroy = cz_destroy,
+	.parse_ev = cz_parse_ev
+};
+
+static wchar_t map_lcase[] = {
+	[KC_Q] = 'q',
+	[KC_W] = 'w',
+	[KC_E] = 'e',
+	[KC_R] = 'r',
+	[KC_T] = 't',
+	[KC_Y] = 'z',
+	[KC_U] = 'u',
+	[KC_I] = 'i',
+	[KC_O] = 'o',
+	[KC_P] = 'p',
+
+	[KC_A] = 'a',
+	[KC_S] = 's',
+	[KC_D] = 'd',
+	[KC_F] = 'f',
+	[KC_G] = 'g',
+	[KC_H] = 'h',
+	[KC_J] = 'j',
+	[KC_K] = 'k',
+	[KC_L] = 'l',
+
+	[KC_Z] = 'y',
+	[KC_X] = 'x',
+	[KC_C] = 'c',
+	[KC_V] = 'v',
+	[KC_B] = 'b',
+	[KC_N] = 'n',
+	[KC_M] = 'm',
+};
+
+static wchar_t map_ucase[] = {
+	[KC_Q] = 'Q',
+	[KC_W] = 'W',
+	[KC_E] = 'E',
+	[KC_R] = 'R',
+	[KC_T] = 'T',
+	[KC_Y] = 'Z',
+	[KC_U] = 'U',
+	[KC_I] = 'I',
+	[KC_O] = 'O',
+	[KC_P] = 'P',
+
+	[KC_A] = 'A',
+	[KC_S] = 'S',
+	[KC_D] = 'D',
+	[KC_F] = 'F',
+	[KC_G] = 'G',
+	[KC_H] = 'H',
+	[KC_J] = 'J',
+	[KC_K] = 'K',
+	[KC_L] = 'L',
+
+	[KC_Z] = 'Y',
+	[KC_X] = 'X',
+	[KC_C] = 'C',
+	[KC_V] = 'V',
+	[KC_B] = 'B',
+	[KC_N] = 'N',
+	[KC_M] = 'M',
+};
+
+static wchar_t map_not_shifted[] = {
+	[KC_BACKTICK] = ';',
+
+	[KC_1] = '+',
+
+	[KC_MINUS] = '=',
+
+	[KC_RBRACKET] = ')',
+
+	[KC_QUOTE] = L'§',
+
+	[KC_COMMA] = ',',
+	[KC_PERIOD] = '.',
+	[KC_SLASH] = '-',
+};
+
+static wchar_t map_shifted[] = {
+	[KC_1] = '1',
+	[KC_2] = '2',
+	[KC_3] = '3',
+	[KC_4] = '4',
+	[KC_5] = '5',
+	[KC_6] = '6',
+	[KC_7] = '7',
+	[KC_8] = '8',
+	[KC_9] = '9',
+	[KC_0] = '0',
+
+	[KC_MINUS] = '%',
+
+	[KC_LBRACKET] = '/',
+	[KC_RBRACKET] = '(',
+
+	[KC_SEMICOLON] = '"',
+	[KC_QUOTE] = '!',
+	[KC_BACKSLASH] = '\'',
+
+	[KC_COMMA] = '?',
+	[KC_PERIOD] = ':',
+	[KC_SLASH] = '_',
+};
+
+static wchar_t map_ns_nocaps[] = {
+	[KC_2] = L'ě',
+	[KC_3] = L'š',
+	[KC_4] = L'č',
+	[KC_5] = L'ř',
+	[KC_6] = L'ž',
+	[KC_7] = L'ý',
+	[KC_8] = L'á',
+	[KC_9] = L'í',
+	[KC_0] = L'é',
+
+	[KC_LBRACKET] = L'ú',
+	[KC_SEMICOLON] = L'ů'
+};
+
+static wchar_t map_ns_caps[] = {
+	[KC_2] = L'Ě',
+	[KC_3] = L'Š',
+	[KC_4] = L'Č',
+	[KC_5] = L'Ř',
+	[KC_6] = L'Ž',
+	[KC_7] = L'Ý',
+	[KC_8] = L'Á',
+	[KC_9] = L'Í',
+	[KC_0] = L'É',
+
+	[KC_LBRACKET] = L'Ú',
+	[KC_SEMICOLON] = L'Ů'
+};
+
+static wchar_t map_neutral[] = {
+	[KC_BACKSPACE] = '\b',
+	[KC_TAB] = '\t',
+	[KC_ENTER] = '\n',
+	[KC_SPACE] = ' ',
+
+	[KC_NSLASH] = '/',
+	[KC_NTIMES] = '*',
+	[KC_NMINUS] = '-',
+	[KC_NPLUS] = '+',
+	[KC_NENTER] = '\n'
+};
+
+static wchar_t map_numeric[] = {
+	[KC_N7] = '7',
+	[KC_N8] = '8',
+	[KC_N9] = '9',
+	[KC_N4] = '4',
+	[KC_N5] = '5',
+	[KC_N6] = '6',
+	[KC_N1] = '1',
+	[KC_N2] = '2',
+	[KC_N3] = '3',
+
+	[KC_N0] = '0',
+	[KC_NPERIOD] = '.'
+};
+
+static wchar_t map_hacek_lcase[] = {
+	[KC_E] = L'ě',
+	[KC_R] = L'ř',
+	[KC_T] = L'ť',
+	[KC_Y] = L'ž',
+	[KC_U] = L'ů',
+
+	[KC_S] = L'š',
+	[KC_D] = L'ď',
+
+	[KC_C] = L'č',
+	[KC_N] = L'ň'
+};
+
+static wchar_t map_hacek_ucase[] = {
+	[KC_E] = L'Ě',
+	[KC_R] = L'Ř',
+	[KC_T] = L'Ť',
+	[KC_Y] = L'Ž',
+	[KC_U] = L'Ů',
+
+	[KC_S] = L'Š',
+	[KC_D] = L'Ď',
+
+	[KC_C] = L'Č',
+	[KC_N] = L'Ň'
+};
+
+static wchar_t map_carka_lcase[] = {
+	[KC_E] = L'é',
+	[KC_U] = L'ú',
+	[KC_I] = L'í',
+	[KC_O] = L'ó',
+
+	[KC_A] = L'á',
+
+	[KC_Z] = L'ý',
+};
+
+static wchar_t map_carka_ucase[] = {
+	[KC_E] = L'É',
+	[KC_U] = L'Ú',
+	[KC_I] = L'Í',
+	[KC_O] = L'Ó',
+
+	[KC_A] = L'Á',
+
+	[KC_Z] = L'Ý',
+};
+
+static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
+{
+	if (key >= map_length)
+		return 0;
+	return map[key];
+}
+
+static wchar_t parse_ms_hacek(layout_cz_t *cz_state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	cz_state->mstate = ms_start;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t));
+
+	return c;
+}
+
+static wchar_t parse_ms_carka(layout_cz_t *cz_state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	cz_state->mstate = ms_start;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t));
+
+	return c;
+}
+
+static wchar_t parse_ms_start(layout_cz_t *cz_state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	if (ev->key == KC_EQUALS) {
+		if ((ev->mods & KM_SHIFT) != 0)
+			cz_state->mstate = ms_hacek;
+		else
+			cz_state->mstate = ms_carka;
+
+		return 0;
+	}
+
+	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) == 0) {
+		if ((ev->mods & KM_CAPS_LOCK) != 0)
+			c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t));
+		else
+			c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t));
+
+		if (c != 0)
+			return c;
+	}	
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) != 0)
+		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_NUM_LOCK) != 0)
+		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
+	else
+		c = 0;
+
+	return c;
+}
+
+static bool key_is_mod(unsigned key)
+{
+	switch (key) {
+	case KC_LSHIFT:
+	case KC_RSHIFT:
+	case KC_LALT:
+	case KC_RALT:
+	case KC_LCTRL:
+	case KC_RCTRL:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int cz_create(layout_t *state)
+{
+	layout_cz_t *cz_state;
+
+	cz_state = malloc(sizeof(layout_cz_t));
+	if (cz_state == NULL) {
+		printf("%s: Out of memory.\n", NAME);
+		return ENOMEM;
+	}
+
+	cz_state->mstate = ms_start;
+	state->layout_priv = (void *) cz_state;
+
+	return EOK;
+}
+
+static void cz_destroy(layout_t *state)
+{
+	free(state->layout_priv);
+}
+
+static wchar_t cz_parse_ev(layout_t *state, kbd_event_t *ev)
+{
+	layout_cz_t *cz_state = (layout_cz_t *) state->layout_priv;
+
+	if (ev->type != KEY_PRESS)
+		return 0;
+	
+	if (key_is_mod(ev->key))
+		return 0;
+	
+	switch (cz_state->mstate) {
+	case ms_start:
+		return parse_ms_start(cz_state, ev);
+	case ms_hacek:
+		return parse_ms_hacek(cz_state, ev);
+	case ms_carka:
+		return parse_ms_carka(cz_state, ev);
+	}
+	
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout/us_dvorak.c
===================================================================
--- uspace/srv/hid/input/layout/us_dvorak.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/layout/us_dvorak.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @brief US Dvorak Simplified Keyboard layout.
+ * @{
+ */
+
+#include <errno.h>
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <layout.h>
+
+static int us_dvorak_create(layout_t *);
+static void us_dvorak_destroy(layout_t *);
+static wchar_t us_dvorak_parse_ev(layout_t *, kbd_event_t *ev);
+
+layout_ops_t us_dvorak_ops = {
+	.create = us_dvorak_create,
+	.destroy = us_dvorak_destroy,
+	.parse_ev = us_dvorak_parse_ev
+};
+
+static wchar_t map_lcase[] = {
+	[KC_R] = 'p',
+	[KC_T] = 'y',
+	[KC_Y] = 'f',
+	[KC_U] = 'g',
+	[KC_I] = 'c',
+	[KC_O] = 'r',
+	[KC_P] = 'l',
+
+	[KC_A] = 'a',
+	[KC_S] = 'o',
+	[KC_D] = 'e',
+	[KC_F] = 'u',
+	[KC_G] = 'i',
+	[KC_H] = 'd',
+	[KC_J] = 'h',
+	[KC_K] = 't',
+	[KC_L] = 'n',
+
+	[KC_SEMICOLON] = 's',
+
+	[KC_X] = 'q',
+	[KC_C] = 'j',
+	[KC_V] = 'k',
+	[KC_B] = 'x',
+	[KC_N] = 'b',
+	[KC_M] = 'm',
+
+	[KC_COMMA] = 'w',
+	[KC_PERIOD] = 'v',
+	[KC_SLASH] = 'z',
+};
+
+static wchar_t map_ucase[] = {
+	[KC_R] = 'P',
+	[KC_T] = 'Y',
+	[KC_Y] = 'F',
+	[KC_U] = 'G',
+	[KC_I] = 'C',
+	[KC_O] = 'R',
+	[KC_P] = 'L',
+
+	[KC_A] = 'A',
+	[KC_S] = 'O',
+	[KC_D] = 'E',
+	[KC_F] = 'U',
+	[KC_G] = 'I',
+	[KC_H] = 'D',
+	[KC_J] = 'H',
+	[KC_K] = 'T',
+	[KC_L] = 'N',
+
+	[KC_SEMICOLON] = 'S',
+
+	[KC_X] = 'Q',
+	[KC_C] = 'J',
+	[KC_V] = 'K',
+	[KC_B] = 'X',
+	[KC_N] = 'B',
+	[KC_M] = 'M',
+
+	[KC_COMMA] = 'W',
+	[KC_PERIOD] = 'V',
+	[KC_SLASH] = 'Z',
+};
+
+static wchar_t map_not_shifted[] = {
+	[KC_BACKTICK] = '`',
+
+	[KC_1] = '1',
+	[KC_2] = '2',
+	[KC_3] = '3',
+	[KC_4] = '4',
+	[KC_5] = '5',
+	[KC_6] = '6',
+	[KC_7] = '7',
+	[KC_8] = '8',
+	[KC_9] = '9',
+	[KC_0] = '0',
+
+	[KC_MINUS] = '[',
+	[KC_EQUALS] = ']',
+
+	[KC_Q] = '\'',
+	[KC_W] = ',',
+	[KC_E] = '.',
+
+	[KC_LBRACKET] = '/',
+	[KC_RBRACKET] = '=',
+
+	[KC_QUOTE] = '-',
+	[KC_BACKSLASH] = '\\',
+
+	[KC_Z] = ';',
+};
+
+static wchar_t map_shifted[] = {
+	[KC_BACKTICK] = '~',
+
+	[KC_1] = '!',
+	[KC_2] = '@',
+	[KC_3] = '#',
+	[KC_4] = '$',
+	[KC_5] = '%',
+	[KC_6] = '^',
+	[KC_7] = '&',
+	[KC_8] = '*',
+	[KC_9] = '(',
+	[KC_0] = ')',
+
+	[KC_MINUS] = '{',
+	[KC_EQUALS] = '}',
+
+	[KC_Q] = '"',
+	[KC_W] = '<',
+	[KC_E] = '>',
+
+	[KC_LBRACKET] = '?',
+	[KC_RBRACKET] = '+',
+
+	[KC_QUOTE] = '_',
+	[KC_BACKSLASH] = '|',
+
+	[KC_Z] = ':',
+};
+
+static wchar_t map_neutral[] = {
+	[KC_BACKSPACE] = '\b',
+	[KC_TAB] = '\t',
+	[KC_ENTER] = '\n',
+	[KC_SPACE] = ' ',
+
+	[KC_NSLASH] = '/',
+	[KC_NTIMES] = '*',
+	[KC_NMINUS] = '-',
+	[KC_NPLUS] = '+',
+	[KC_NENTER] = '\n'
+};
+
+static wchar_t map_numeric[] = {
+	[KC_N7] = '7',
+	[KC_N8] = '8',
+	[KC_N9] = '9',
+	[KC_N4] = '4',
+	[KC_N5] = '5',
+	[KC_N6] = '6',
+	[KC_N1] = '1',
+	[KC_N2] = '2',
+	[KC_N3] = '3',
+
+	[KC_N0] = '0',
+	[KC_NPERIOD] = '.'
+};
+
+static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
+{
+	if (key >= map_length)
+		return 0;
+	return map[key];
+}
+
+static int us_dvorak_create(layout_t *state)
+{
+	return EOK;
+}
+
+static void us_dvorak_destroy(layout_t *state)
+{
+}
+
+static wchar_t us_dvorak_parse_ev(layout_t *state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
+	if (c != 0)
+		return c;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) != 0)
+		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_NUM_LOCK) != 0)
+		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
+	else
+		c = 0;
+
+	return c;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/layout/us_qwerty.c
===================================================================
--- uspace/srv/hid/input/layout/us_qwerty.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/layout/us_qwerty.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup input
+ * @brief	US QWERTY layout.
+ * @{
+ */
+
+#include <errno.h>
+#include <kbd.h>
+#include <io/console.h>
+#include <io/keycode.h>
+#include <layout.h>
+
+static int us_qwerty_create(layout_t *);
+static void us_qwerty_destroy(layout_t *);
+static wchar_t us_qwerty_parse_ev(layout_t *, kbd_event_t *ev);
+
+layout_ops_t us_qwerty_ops = {
+	.create = us_qwerty_create,
+	.destroy = us_qwerty_destroy,
+	.parse_ev = us_qwerty_parse_ev
+};
+
+static wchar_t map_lcase[] = {
+	[KC_Q] = 'q',
+	[KC_W] = 'w',
+	[KC_E] = 'e',
+	[KC_R] = 'r',
+	[KC_T] = 't',
+	[KC_Y] = 'y',
+	[KC_U] = 'u',
+	[KC_I] = 'i',
+	[KC_O] = 'o',
+	[KC_P] = 'p',
+
+	[KC_A] = 'a',
+	[KC_S] = 's',
+	[KC_D] = 'd',
+	[KC_F] = 'f',
+	[KC_G] = 'g',
+	[KC_H] = 'h',
+	[KC_J] = 'j',
+	[KC_K] = 'k',
+	[KC_L] = 'l',
+
+	[KC_Z] = 'z',
+	[KC_X] = 'x',
+	[KC_C] = 'c',
+	[KC_V] = 'v',
+	[KC_B] = 'b',
+	[KC_N] = 'n',
+	[KC_M] = 'm',
+};
+
+static wchar_t map_ucase[] = {
+	[KC_Q] = 'Q',
+	[KC_W] = 'W',
+	[KC_E] = 'E',
+	[KC_R] = 'R',
+	[KC_T] = 'T',
+	[KC_Y] = 'Y',
+	[KC_U] = 'U',
+	[KC_I] = 'I',
+	[KC_O] = 'O',
+	[KC_P] = 'P',
+
+	[KC_A] = 'A',
+	[KC_S] = 'S',
+	[KC_D] = 'D',
+	[KC_F] = 'F',
+	[KC_G] = 'G',
+	[KC_H] = 'H',
+	[KC_J] = 'J',
+	[KC_K] = 'K',
+	[KC_L] = 'L',
+
+	[KC_Z] = 'Z',
+	[KC_X] = 'X',
+	[KC_C] = 'C',
+	[KC_V] = 'V',
+	[KC_B] = 'B',
+	[KC_N] = 'N',
+	[KC_M] = 'M',
+};
+
+static wchar_t map_not_shifted[] = {
+	[KC_BACKTICK] = '`',
+
+	[KC_1] = '1',
+	[KC_2] = '2',
+	[KC_3] = '3',
+	[KC_4] = '4',
+	[KC_5] = '5',
+	[KC_6] = '6',
+	[KC_7] = '7',
+	[KC_8] = '8',
+	[KC_9] = '9',
+	[KC_0] = '0',
+
+	[KC_MINUS] = '-',
+	[KC_EQUALS] = '=',
+
+	[KC_LBRACKET] = '[',
+	[KC_RBRACKET] = ']',
+
+	[KC_SEMICOLON] = ';',
+	[KC_QUOTE] = '\'',
+	[KC_BACKSLASH] = '\\',
+
+	[KC_COMMA] = ',',
+	[KC_PERIOD] = '.',
+	[KC_SLASH] = '/',
+};
+
+static wchar_t map_shifted[] = {
+	[KC_BACKTICK] = '~',
+
+	[KC_1] = '!',
+	[KC_2] = '@',
+	[KC_3] = '#',
+	[KC_4] = '$',
+	[KC_5] = '%',
+	[KC_6] = '^',
+	[KC_7] = '&',
+	[KC_8] = '*',
+	[KC_9] = '(',
+	[KC_0] = ')',
+
+	[KC_MINUS] = '_',
+	[KC_EQUALS] = '+',
+
+	[KC_LBRACKET] = '{',
+	[KC_RBRACKET] = '}',
+
+	[KC_SEMICOLON] = ':',
+	[KC_QUOTE] = '"',
+	[KC_BACKSLASH] = '|',
+
+	[KC_COMMA] = '<',
+	[KC_PERIOD] = '>',
+	[KC_SLASH] = '?',
+};
+
+static wchar_t map_neutral[] = {
+	[KC_BACKSPACE] = '\b',
+	[KC_TAB] = '\t',
+	[KC_ENTER] = '\n',
+	[KC_SPACE] = ' ',
+
+	[KC_NSLASH] = '/',
+	[KC_NTIMES] = '*',
+	[KC_NMINUS] = '-',
+	[KC_NPLUS] = '+',
+	[KC_NENTER] = '\n'
+};
+
+static wchar_t map_numeric[] = {
+	[KC_N7] = '7',
+	[KC_N8] = '8',
+	[KC_N9] = '9',
+	[KC_N4] = '4',
+	[KC_N5] = '5',
+	[KC_N6] = '6',
+	[KC_N1] = '1',
+	[KC_N2] = '2',
+	[KC_N3] = '3',
+
+	[KC_N0] = '0',
+	[KC_NPERIOD] = '.'
+};
+
+static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
+{
+	if (key >= map_length)
+		return 0;
+	return map[key];
+}
+
+static int us_qwerty_create(layout_t *state)
+{
+	return EOK;
+}
+
+static void us_qwerty_destroy(layout_t *state)
+{
+}
+
+static wchar_t us_qwerty_parse_ev(layout_t *state, kbd_event_t *ev)
+{
+	wchar_t c;
+
+	/* Produce no characters when Ctrl or Alt is pressed. */
+	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
+		return 0;
+
+	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
+	if (c != 0)
+		return c;
+
+	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
+		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_SHIFT) != 0)
+		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
+	else
+		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
+
+	if (c != 0)
+		return c;
+
+	if ((ev->mods & KM_NUM_LOCK) != 0)
+		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
+	else
+		c = 0;
+
+	return c;
+}
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/port/adb.c
===================================================================
--- uspace/srv/hid/input/port/adb.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/adb.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup kbd
+ * @{
+ */
+/** @file
+ * @brief ADB keyboard port driver.
+ */
+
+#include <ipc/adb.h>
+#include <async.h>
+#include <input.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <vfs/vfs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <devmap.h>
+
+static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+static void adb_kbd_reg0_data(uint16_t data);
+
+static int adb_port_init(kbd_dev_t *);
+static void adb_port_yield(void);
+static void adb_port_reclaim(void);
+static void adb_port_write(uint8_t data);
+
+kbd_port_ops_t adb_port = {
+	.init = adb_port_init,
+	.yield = adb_port_yield,
+	.reclaim = adb_port_reclaim,
+	.write = adb_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+static async_sess_t *dev_sess;
+
+static int adb_port_init(kbd_dev_t *kdev)
+{
+	const char *dev = "adb/kbd";
+	devmap_handle_t handle;
+	async_exch_t *exch;
+	int rc;
+	
+	kbd_dev = kdev;
+	
+	rc = devmap_device_get_handle(dev, &handle, 0);
+	if (rc != EOK)
+		return rc;
+	
+	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+	if (dev_sess == NULL) {
+		printf("%s: Failed to connect to device\n", NAME);
+		return ENOENT;
+	}
+	
+	exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, kbd_port_events, NULL);
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+static void adb_port_yield(void)
+{
+}
+
+static void adb_port_reclaim(void)
+{
+}
+
+static void adb_port_write(uint8_t data)
+{
+	/*async_msg_1(dev_phone, CHAR_WRITE_BYTE, data);*/
+}
+
+static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		int retval;
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case ADB_REG_NOTIF:
+			adb_kbd_reg0_data(IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		async_answer_0(callid, retval);
+	}
+}
+
+static void adb_kbd_reg0_data(uint16_t data)
+{
+	uint8_t b0 = (data >> 8) & 0xff;
+	uint8_t b1 = data & 0xff;
+	
+	if (b0 != 0xff)
+		kbd_push_data(kbd_dev, b0);
+	
+	if (b1 != 0xff)
+		kbd_push_data(kbd_dev, b1);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/adb_mouse.c
===================================================================
--- uspace/srv/hid/input/port/adb_mouse.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/adb_mouse.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_port
+ * @ingroup mouse
+ * @{
+ */
+/** @file
+ * @brief ADB mouse port driver.
+ */
+
+#include <ipc/adb.h>
+#include <async.h>
+#include <input.h>
+#include <mouse_port.h>
+#include <mouse.h>
+#include <errno.h>
+#include <devmap.h>
+
+static mouse_dev_t *mouse_dev;
+static async_sess_t *dev_sess;
+
+static void mouse_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		int retval;
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case ADB_REG_NOTIF:
+			mouse_push_data(mouse_dev, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int adb_port_init(mouse_dev_t *mdev)
+{
+	const char *dev = "adb/mouse";
+	
+	mouse_dev = mdev;
+	
+	devmap_handle_t handle;
+	int rc = devmap_device_get_handle(dev, &handle, 0);
+	if (rc != EOK)
+		return rc;
+	
+	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);
+	if (dev_sess == NULL) {
+		printf("%s: Failed to connect to device\n", NAME);
+		return ENOENT;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, mouse_port_events, NULL);
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return rc;
+	}
+	
+	return EOK;
+}
+
+static void adb_port_yield(void)
+{
+}
+
+static void adb_port_reclaim(void)
+{
+}
+
+static void adb_port_write(uint8_t data)
+{
+}
+
+mouse_port_ops_t adb_mouse_port = {
+	.init = adb_port_init,
+	.yield = adb_port_yield,
+	.reclaim = adb_port_reclaim,
+	.write = adb_port_write
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/chardev.c
===================================================================
--- uspace/srv/hid/input/port/chardev.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/chardev.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup kbd
+ * @{
+ */
+/** @file
+ * @brief Chardev keyboard port driver.
+ */
+
+#include <ipc/char.h>
+#include <async.h>
+#include <input.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <devmap.h>
+#include <errno.h>
+#include <stdio.h>
+
+static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static int chardev_port_init(kbd_dev_t *);
+static void chardev_port_yield(void);
+static void chardev_port_reclaim(void);
+static void chardev_port_write(uint8_t data);
+
+kbd_port_ops_t chardev_port = {
+	.init = chardev_port_init,
+	.yield = chardev_port_yield,
+	.reclaim = chardev_port_reclaim,
+	.write = chardev_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+static async_sess_t *dev_sess;
+
+/** List of devices to try connecting to. */
+static const char *in_devs[] = {
+	"char/ps2a",
+	"char/s3c24ser"
+};
+
+static const unsigned int num_devs = sizeof(in_devs) / sizeof(in_devs[0]);
+
+static int chardev_port_init(kbd_dev_t *kdev)
+{
+	devmap_handle_t handle;
+	async_exch_t *exch;
+	unsigned int i;
+	int rc;
+	
+	kbd_dev = kdev;
+	
+	for (i = 0; i < num_devs; i++) {
+		rc = devmap_device_get_handle(in_devs[i], &handle, 0);
+		if (rc == EOK)
+			break;
+	}
+	
+	if (i >= num_devs) {
+		printf("%s: Could not find any suitable input device\n", NAME);
+		return -1;
+	}
+	
+	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle,
+	    IPC_FLAG_BLOCKING);
+	if (dev_sess == NULL) {
+		printf("%s: Failed connecting to device\n", NAME);
+		return ENOENT;
+	}
+	
+	exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, kbd_port_events, NULL);
+	async_exchange_end(exch);
+	
+	if (rc != 0) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return -1;
+	}
+	
+	return 0;
+}
+
+static void chardev_port_yield(void)
+{
+}
+
+static void chardev_port_reclaim(void)
+{
+}
+
+static void chardev_port_write(uint8_t data)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		return;
+	}
+
+	async_msg_1(exch, CHAR_WRITE_BYTE, data);
+	async_exchange_end(exch);
+}
+
+static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		int retval;
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case CHAR_NOTIF_BYTE:
+			kbd_push_data(kbd_dev, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		async_answer_0(callid, retval);
+	}
+}
+
+
+/**
+ * @}
+ */ 
Index: uspace/srv/hid/input/port/chardev_mouse.c
===================================================================
--- uspace/srv/hid/input/port/chardev_mouse.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/chardev_mouse.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_port
+ * @ingroup mouse
+ * @{
+ */
+/** @file
+ * @brief Chardev mouse port driver.
+ */
+
+#include <ipc/char.h>
+#include <stdio.h>
+#include <async.h>
+#include <errno.h>
+#include <devmap.h>
+#include <input.h>
+#include <mouse_port.h>
+#include <mouse.h>
+
+static mouse_dev_t *mouse_dev;
+static async_sess_t *dev_sess;
+
+/** List of devices to try connecting to. */
+static const char *in_devs[] = {
+	"char/ps2b",
+};
+
+static const unsigned int num_devs = sizeof(in_devs) / sizeof(in_devs[0]);
+
+static void mouse_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		int retval;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case CHAR_NOTIF_BYTE:
+			mouse_push_data(mouse_dev, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int chardev_port_init(mouse_dev_t *mdev)
+{
+	devmap_handle_t handle;
+	unsigned int i;
+	int rc;
+	
+	mouse_dev = mdev;
+	
+	for (i = 0; i < num_devs; i++) {
+		rc = devmap_device_get_handle(in_devs[i], &handle, 0);
+		if (rc == EOK)
+			break;
+	}
+	
+	if (i >= num_devs) {
+		printf("%s: Could not find any suitable input device\n", NAME);
+		return -1;
+	}
+	
+	dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle,
+	    IPC_FLAG_BLOCKING);
+	if (dev_sess == NULL) {
+		printf("%s: Failed connecting to device\n", NAME);
+		return ENOENT;
+	}
+	
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		async_hangup(dev_sess);
+		return ENOMEM;
+	}
+	
+	/* NB: The callback connection is slotted for removal */
+	rc = async_connect_to_me(exch, 0, 0, 0, mouse_port_events, NULL);
+	async_exchange_end(exch);
+	
+	if (rc != 0) {
+		printf("%s: Failed to create callback from device\n", NAME);
+		async_hangup(dev_sess);
+		return -1;
+	}
+	
+	return 0;
+}
+
+static void chardev_port_yield(void)
+{
+}
+
+static void chardev_port_reclaim(void)
+{
+}
+
+static void chardev_port_write(uint8_t data)
+{
+	async_exch_t *exch = async_exchange_begin(dev_sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with device\n", NAME);
+		return;
+	}
+
+	async_msg_1(exch, CHAR_WRITE_BYTE, data);
+	async_exchange_end(exch);
+}
+
+mouse_port_ops_t chardev_mouse_port = {
+	.init = chardev_port_init,
+	.yield = chardev_port_yield,
+	.reclaim = chardev_port_reclaim,
+	.write = chardev_port_write
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/dummy.c
===================================================================
--- uspace/srv/hid/input/port/dummy.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/dummy.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @brief	Dummy keyboard port driver.
+ * @ingroup  kbd
+ * @{
+ */ 
+/** @file
+ */
+
+#include <kbd_port.h>
+#include <kbd.h>
+
+int kbd_port_init(void)
+{
+	return 0;
+}
+
+void kbd_port_yield(void)
+{
+}
+
+void kbd_port_reclaim(void)
+{
+}
+
+void kbd_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/** @}
+*/
Index: uspace/srv/hid/input/port/gxemul.c
===================================================================
--- uspace/srv/hid/input/port/gxemul.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/gxemul.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2007 Michal Kebrt
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @{
+ * @ingroup  kbd
+ */ 
+/** @file
+ * @brief	GXEmul keyboard port driver.
+ */
+
+#include <async.h>
+#include <sysinfo.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <ddi.h>
+#include <errno.h>
+
+static int gxemul_port_init(kbd_dev_t *);
+static void gxemul_port_yield(void);
+static void gxemul_port_reclaim(void);
+static void gxemul_port_write(uint8_t data);
+
+kbd_port_ops_t gxemul_port = {
+	.init = gxemul_port_init,
+	.yield = gxemul_port_yield,
+	.reclaim = gxemul_port_reclaim,
+	.write = gxemul_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+static irq_cmd_t gxemul_cmds[] = {
+	{ 
+		.cmd = CMD_PIO_READ_8, 
+		.addr = (void *) 0, 	/* will be patched in run-time */
+		.dstarg = 2,
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t gxemul_kbd = {
+	sizeof(gxemul_cmds) / sizeof(irq_cmd_t),
+	gxemul_cmds
+};
+
+static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+/** Initializes keyboard handler. */
+static int gxemul_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	
+	sysarg_t addr;
+	if (sysinfo_get_value("kbd.address.virtual", &addr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	async_set_interrupt_received(gxemul_irq_handler);
+	gxemul_cmds[0].addr = (void *) addr;
+	register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
+	return 0;
+}
+
+static void gxemul_port_yield(void)
+{
+}
+
+static void gxemul_port_reclaim(void)
+{
+}
+
+static void gxemul_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/** Process data sent when a key is pressed.
+ *
+ * @param keybuffer Buffer of pressed keys.
+ * @param call      IPC call.
+ *
+ */
+static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/port/msim.c
===================================================================
--- uspace/srv/hid/input/port/msim.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/msim.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief Msim keyboard port driver.
+ */
+
+#include <async.h>
+#include <sysinfo.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <ddi.h>
+#include <errno.h>
+
+static int msim_port_init(kbd_dev_t *);
+static void msim_port_yield(void);
+static void msim_port_reclaim(void);
+static void msim_port_write(uint8_t data);
+
+kbd_port_ops_t msim_port = {
+	.init = msim_port_init,
+	.yield = msim_port_yield,
+	.reclaim = msim_port_reclaim,
+	.write = msim_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+static irq_cmd_t msim_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,	/* will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t msim_kbd = {
+	sizeof(msim_cmds) / sizeof(irq_cmd_t),
+	msim_cmds
+};
+
+static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+static int msim_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+
+	sysarg_t vaddr;
+	if (sysinfo_get_value("kbd.address.virtual", &vaddr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	msim_cmds[0].addr = (void *) vaddr;
+	async_set_interrupt_received(msim_irq_handler);
+	register_irq(inr, device_assign_devno(), 0, &msim_kbd);
+	
+	return 0;
+}
+
+static void msim_port_yield(void)
+{
+}
+
+static void msim_port_reclaim(void)
+{
+}
+
+static void msim_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/port/niagara.c
===================================================================
--- uspace/srv/hid/input/port/niagara.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/niagara.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2008 Pavel Rimsky
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */ 
+/** @file
+ * @brief	Niagara console keyboard port driver.
+ */
+
+#include <as.h>
+#include <ddi.h>
+#include <async.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <thread.h>
+#include <bool.h>
+#include <errno.h>
+
+static int niagara_port_init(kbd_dev_t *);
+static void niagara_port_yield(void);
+static void niagara_port_reclaim(void);
+static void niagara_port_write(uint8_t data);
+
+kbd_port_ops_t niagara_port = {
+	.init = niagara_port_init,
+	.yield = niagara_port_yield,
+	.reclaim = niagara_port_reclaim,
+	.write = niagara_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+#define POLL_INTERVAL  10000
+
+/**
+ * Virtual address mapped to the buffer shared with the kernel counterpart.
+ */
+static uintptr_t input_buffer_addr;
+
+/*
+ * Kernel counterpart of the driver pushes characters (it has read) here.
+ * Keep in sync with the definition from
+ * kernel/arch/sparc64/src/drivers/niagara.c.
+ */
+#define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
+
+typedef volatile struct {
+	uint64_t write_ptr;
+	uint64_t read_ptr;
+	char data[INPUT_BUFFER_SIZE];
+}
+	__attribute__ ((packed))
+	__attribute__ ((aligned(PAGE_SIZE)))
+	*input_buffer_t;
+
+/* virtual address of the shared buffer */
+static input_buffer_t input_buffer;
+
+static volatile bool polling_disabled = false;
+static void niagara_thread_impl(void *arg);
+
+/**
+ * Initializes the Niagara driver.
+ * Maps the shared buffer and creates the polling thread. 
+ */
+static int niagara_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	
+	sysarg_t paddr;
+	if (sysinfo_get_value("niagara.inbuf.address", &paddr) != EOK)
+		return -1;
+	
+	input_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
+	int rc = physmem_map((void *) paddr, (void *) input_buffer_addr,
+	    1, AS_AREA_READ | AS_AREA_WRITE);
+	
+	if (rc != 0) {
+		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
+		    rc);
+		return rc;
+	}
+	
+	input_buffer = (input_buffer_t) input_buffer_addr;
+	
+	thread_id_t tid;
+	rc = thread_create(niagara_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0)
+		return rc;
+	
+	return 0;
+}
+
+static void niagara_port_yield(void)
+{
+	polling_disabled = true;
+}
+
+static void niagara_port_reclaim(void)
+{
+	polling_disabled = false;
+}
+
+static void niagara_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/**
+ * Called regularly by the polling thread. Reads codes of all the
+ * pressed keys from the buffer. 
+ */
+static void niagara_key_pressed(void)
+{
+	char c;
+	
+	while (input_buffer->read_ptr != input_buffer->write_ptr) {
+		c = input_buffer->data[input_buffer->read_ptr];
+		input_buffer->read_ptr =
+		    ((input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
+		kbd_push_data(kbd_dev, c);
+	}
+}
+
+/**
+ * Thread to poll Niagara console for keypresses.
+ */
+static void niagara_thread_impl(void *arg)
+{
+	(void) arg;
+
+	while (1) {
+		if (polling_disabled == false)
+			niagara_key_pressed();
+		usleep(POLL_INTERVAL);
+	}
+}
+/** @}
+ */
Index: uspace/srv/hid/input/port/ns16550.c
===================================================================
--- uspace/srv/hid/input/port/ns16550.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/ns16550.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief NS16550 port driver.
+ */
+
+#include <ipc/irc.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <sysinfo.h>
+#include <input.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <ddi.h>
+#include <errno.h>
+
+static int ns16550_port_init(kbd_dev_t *);
+static void ns16550_port_yield(void);
+static void ns16550_port_reclaim(void);
+static void ns16550_port_write(uint8_t data);
+
+kbd_port_ops_t ns16550_port = {
+	.init = ns16550_port_init,
+	.yield = ns16550_port_yield,
+	.reclaim = ns16550_port_reclaim,
+	.write = ns16550_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+/* NS16550 registers */
+#define RBR_REG  0  /** Receiver Buffer Register. */
+#define IER_REG  1  /** Interrupt Enable Register. */
+#define IIR_REG  2  /** Interrupt Ident Register (read). */
+#define FCR_REG  2  /** FIFO control register (write). */
+#define LCR_REG  3  /** Line Control register. */
+#define MCR_REG  4  /** Modem Control Register. */
+#define LSR_REG  5  /** Line Status Register. */
+
+#define LSR_DATA_READY  0x01
+
+static irq_cmd_t ns16550_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,     /* Will be patched in run-time */
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_BTEST,
+		.value = LSR_DATA_READY,
+		.srcarg = 1,
+		.dstarg = 3
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 2,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,     /* Will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+irq_code_t ns16550_kbd = {
+	sizeof(ns16550_cmds) / sizeof(irq_cmd_t),
+	ns16550_cmds
+};
+
+static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+static uintptr_t ns16550_physical;
+static uintptr_t ns16550_kernel;
+
+static kbd_dev_t *kbd_dev;
+
+static int ns16550_port_init(kbd_dev_t *kdev)
+{
+	void *vaddr;
+	
+	kbd_dev = kdev;
+	
+	sysarg_t ns16550;
+	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
+		return -1;
+	if (!ns16550)
+		return -1;
+	
+	if (sysinfo_get_value("kbd.address.physical", &ns16550_physical) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("kbd.address.kernel", &ns16550_kernel) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG);
+	ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG);
+	
+	async_set_interrupt_received(ns16550_irq_handler);
+	register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
+	
+	return pio_enable((void *) ns16550_physical, 8, &vaddr);
+}
+
+static void ns16550_port_yield(void)
+{
+}
+
+static void ns16550_port_reclaim(void)
+{
+}
+
+static void ns16550_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
+	
+	if (irc_service)
+		async_obsolete_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
+		    IPC_GET_IMETHOD(*call));
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/pl050.c
===================================================================
--- uspace/srv/hid/input/port/pl050.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/pl050.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2009 Vineeth Pillai
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup kbd
+ * @{
+ */ 
+/** @file
+ * @brief pl050 port driver.
+ */
+
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <async.h>
+#include <unistd.h>
+#include <sysinfo.h>
+#include <kbd_port.h>
+#include <kbd.h>
+#include <ddi.h>
+#include <stdio.h>
+#include <errno.h>
+
+static int pl050_port_init(kbd_dev_t *);
+static void pl050_port_yield(void);
+static void pl050_port_reclaim(void);
+static void pl050_port_write(uint8_t data);
+
+kbd_port_ops_t pl050_port = {
+	.init = pl050_port_init,
+	.yield = pl050_port_yield,
+	.reclaim = pl050_port_reclaim,
+	.write = pl050_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+#define PL050_STAT_RXFULL  (1 << 4)
+
+static irq_cmd_t pl050_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_BTEST,
+		.value = PL050_STAT_RXFULL,
+		.srcarg = 1,
+		.dstarg = 3
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 2,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = NULL,  /* Will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t pl050_kbd = {
+	sizeof(pl050_cmds) / sizeof(irq_cmd_t),
+	pl050_cmds
+};
+
+static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+static int pl050_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	
+	sysarg_t addr;
+	if (sysinfo_get_value("kbd.address.status", &addr) != EOK)
+		return -1;
+	
+	pl050_kbd.cmds[0].addr = (void *) addr;
+	
+	if (sysinfo_get_value("kbd.address.data", &addr) != EOK)
+		return -1;
+	
+	pl050_kbd.cmds[3].addr = (void *) addr;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	async_set_interrupt_received(pl050_irq_handler);
+	register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
+	
+	return 0;
+}
+
+static void pl050_port_yield(void)
+{
+}
+
+static void pl050_port_reclaim(void)
+{
+}
+
+static void pl050_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	kbd_push_data(kbd_dev, IPC_GET_ARG2(*call));
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/port/sgcn.c
===================================================================
--- uspace/srv/hid/input/port/sgcn.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/sgcn.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2008 Pavel Rimsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief SGCN (Serengeti Console) keyboard port driver.
+ */
+
+#include <as.h>
+#include <ddi.h>
+#include <async.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sysinfo.h>
+#include <stdio.h>
+#include <thread.h>
+#include <bool.h>
+#include <errno.h>
+
+#define POLL_INTERVAL  10000
+
+/**
+ * SGCN buffer header. It is placed at the very beginning of the SGCN
+ * buffer.
+ */
+typedef struct {
+	/** hard-wired to "CON" */
+	char magic[4];
+	
+	/** we don't need this */
+	char unused[8];
+	
+	/** offset within the SGCN buffer of the input buffer start */
+	uint32_t in_begin;
+	
+	/** offset within the SGCN buffer of the input buffer end */
+	uint32_t in_end;
+	
+	/** offset within the SGCN buffer of the input buffer read pointer */
+	uint32_t in_rdptr;
+	
+	/** offset within the SGCN buffer of the input buffer write pointer */
+	uint32_t in_wrptr;
+} __attribute__ ((packed)) sgcn_buffer_header_t;
+
+/*
+ * Returns a pointer to the object of a given type which is placed at the given
+ * offset from the console buffer beginning.
+ */
+#define SGCN_BUFFER(type, offset) \
+		((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
+
+/** Returns a pointer to the console buffer header. */
+#define SGCN_BUFFER_HEADER	(SGCN_BUFFER(sgcn_buffer_header_t, 0))
+
+/**
+ * Virtual address mapped to SRAM.
+ */
+static uintptr_t sram_virt_addr;
+
+/**
+ * SGCN buffer offset within SGCN.
+ */
+static uintptr_t sram_buffer_offset;
+
+/* polling thread */
+static void sgcn_thread_impl(void *arg);
+
+static volatile bool polling_disabled = false;
+
+/**
+ * Initializes the SGCN driver.
+ * Maps the physical memory (SRAM) and creates the polling thread. 
+ */
+int kbd_port_init(void)
+{
+	sysarg_t sram_paddr;
+	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
+		return -1;
+	
+	sysarg_t sram_size;
+	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
+		sram_buffer_offset = 0;
+	
+	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
+	
+	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
+	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0) {
+		printf("SGCN: uspace driver could not map physical memory.");
+		return -1;
+	}
+	
+	thread_id_t tid;
+	int rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0)
+		return rc;
+	
+	return 0;
+}
+
+void kbd_port_yield(void)
+{
+	polling_disabled = true;
+}
+
+void kbd_port_reclaim(void)
+{
+	polling_disabled = false;
+}
+
+void kbd_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/**
+ * Handler of the "key pressed" event. Reads codes of all the pressed keys from
+ * the buffer. 
+ */
+static void sgcn_key_pressed(void)
+{
+	char c;
+	
+	uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
+	uint32_t end = SGCN_BUFFER_HEADER->in_end;
+	uint32_t size = end - begin;
+	
+	volatile char *buf_ptr = (volatile char *)
+		SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
+	volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
+	volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
+	
+	while (*in_rdptr_ptr != *in_wrptr_ptr) {
+		c = *buf_ptr;
+		*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
+		buf_ptr = (volatile char *)
+			SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
+		kbd_push_scancode(c);
+	}
+}
+
+/**
+ * Thread to poll SGCN for keypresses.
+ */
+static void sgcn_thread_impl(void *arg)
+{
+	(void) arg;
+
+	while (1) {
+		if (polling_disabled == false)
+			sgcn_key_pressed();
+		usleep(POLL_INTERVAL);
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/port/ski.c
===================================================================
--- uspace/srv/hid/input/port/ski.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/ski.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2005 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */ 
+/** @file
+ * @brief	Ski console keyboard port driver.
+ */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sys/types.h>
+#include <thread.h>
+#include <bool.h>
+
+static int ski_port_init(kbd_dev_t *);
+static void ski_port_yield(void);
+static void ski_port_reclaim(void);
+static void ski_port_write(uint8_t data);
+
+kbd_port_ops_t ski_port = {
+	.init = ski_port_init,
+	.yield = ski_port_yield,
+	.reclaim = ski_port_reclaim,
+	.write = ski_port_write
+};
+
+static kbd_dev_t *kbd_dev;
+
+#define SKI_GETCHAR		21
+
+#define POLL_INTERVAL		10000
+
+static void ski_thread_impl(void *arg);
+static int32_t ski_getchar(void);
+
+static volatile bool polling_disabled = false;
+
+/** Initialize Ski port driver. */
+static int ski_port_init(kbd_dev_t *kdev)
+{
+	thread_id_t tid;
+	int rc;
+
+	kbd_dev = kdev;
+
+	rc = thread_create(ski_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0) {
+		return rc;
+	}
+
+	return 0;
+}
+
+static void ski_port_yield(void)
+{
+	polling_disabled = true;
+}
+
+static void ski_port_reclaim(void)
+{
+	polling_disabled = false;
+}
+
+static void ski_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/** Thread to poll Ski for keypresses. */
+static void ski_thread_impl(void *arg)
+{
+	int32_t c;
+	(void) arg;
+
+	while (1) {
+		while (polling_disabled == false) {
+			c = ski_getchar();
+			if (c == 0)
+				break;
+			kbd_push_data(kbd_dev, c);
+		}
+
+		usleep(POLL_INTERVAL);
+	}
+}
+
+/** Ask Ski if a key was pressed.
+ *
+ * Use SSC (Simulator System Call) to get character from the debug console.
+ * This call is non-blocking.
+ *
+ * @return ASCII code of pressed key or 0 if no key pressed.
+ */
+static int32_t ski_getchar(void)
+{
+	uint64_t ch;
+	
+#ifdef UARCH_ia64
+	asm volatile (
+		"mov r15 = %1\n"
+		"break 0x80000;;\n"	/* modifies r8 */
+		"mov %0 = r8;;\n"		
+
+		: "=r" (ch)
+		: "i" (SKI_GETCHAR)
+		: "r15", "r8"
+	);
+#else
+	ch = 0;
+#endif
+	return (int32_t) ch;
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/port/sun.c
===================================================================
--- uspace/srv/hid/input/port/sun.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/sun.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2009 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief Sun keyboard virtual port driver.
+ */
+
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sun.h>
+#include <sysinfo.h>
+#include <errno.h>
+#include <bool.h>
+
+/** Sun keyboard virtual port driver.
+ *
+ * This is a virtual port driver which can use
+ * both ns16550_port_init and z8530_port_init
+ * according to the information passed from the
+ * kernel. This is just a temporal hack.
+ *
+ */
+int kbd_port_init(void)
+{
+	sysarg_t z8530;
+	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
+		z8530 = false;
+	
+	sysarg_t ns16550;
+	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
+		ns16550 = false;
+	
+	if (z8530) {
+		if (z8530_port_init() == 0)
+			return 0;
+	}
+	
+	if (ns16550) {
+		if (ns16550_port_init() == 0)
+			return 0;
+	}
+	
+	return -1;
+}
+
+void kbd_port_yield(void)
+{
+}
+
+void kbd_port_reclaim(void)
+{
+}
+
+void kbd_port_write(uint8_t data)
+{
+	(void) data;
+}
+
+/** @}
+*/
Index: uspace/srv/hid/input/port/z8530.c
===================================================================
--- uspace/srv/hid/input/port/z8530.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/port/z8530.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kbd_port
+ * @ingroup  kbd
+ * @{
+ */
+/** @file
+ * @brief Z8530 keyboard port driver.
+ */
+
+#include <ipc/irc.h>
+#include <async.h>
+#include <sysinfo.h>
+#include <kbd.h>
+#include <kbd_port.h>
+#include <sun.h>
+#include <sys/types.h>
+#include <ddi.h>
+#include <errno.h>
+
+#define CHAN_A_STATUS  4
+#define CHAN_A_DATA    6
+
+#define RR0_RCA  1
+
+static irq_cmd_t z8530_cmds[] = {
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,     /* Will be patched in run-time */
+		.dstarg = 1
+	},
+	{
+		.cmd = CMD_BTEST,
+		.value = RR0_RCA,
+		.srcarg = 1,
+		.dstarg = 3
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 2,
+		.srcarg = 3
+	},
+	{
+		.cmd = CMD_PIO_READ_8,
+		.addr = (void *) 0,     /* Will be patched in run-time */
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+	
+irq_code_t z8530_kbd = {
+	sizeof(z8530_cmds) / sizeof(irq_cmd_t),
+	z8530_cmds
+};
+
+static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call);
+
+int z8530_port_init(void)
+{
+	sysarg_t kaddr;
+	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	z8530_cmds[0].addr = (void *) kaddr + CHAN_A_STATUS;
+	z8530_cmds[3].addr = (void *) kaddr + CHAN_A_DATA;
+	
+	async_set_interrupt_received(z8530_irq_handler);
+	register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
+	
+	return 0;
+}
+
+static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
+{
+	int scan_code = IPC_GET_ARG2(*call);
+	kbd_push_scancode(scan_code);
+	
+	if (irc_service)
+		async_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
+		    IPC_GET_IMETHOD(*call));
+}
+
+/** @}
+ */
Index: uspace/srv/hid/input/proto/adb.c
===================================================================
--- uspace/srv/hid/input/proto/adb.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/proto/adb.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief ADB protocol driver.
+ */
+
+#include <bool.h>
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+
+static mouse_dev_t *mouse_dev;
+static bool b1_pressed;
+static bool b2_pressed;
+
+static int adb_proto_init(mouse_dev_t *mdev)
+{
+	mouse_dev = mdev;
+	b1_pressed = false;
+	b2_pressed = false;
+	
+	return 0;
+}
+
+/** Process mouse data */
+static void adb_proto_parse(sysarg_t data)
+{
+	bool b1, b2;
+	uint16_t udx, udy;
+	int dx, dy;
+	
+	/* Extract fields. */
+	b1 = ((data >> 15) & 1) == 0;
+	udy = (data >> 8) & 0x7f;
+	b2 = ((data >> 7) & 1) == 0;
+	udx = data & 0x7f;
+	
+	/* Decode 7-bit two's complement signed values. */
+	dx = (udx & 0x40) ? (udx - 0x80) : udx;
+	dy = (udy & 0x40) ? (udy - 0x80) : udy;
+	
+	if (b1 != b1_pressed) {
+		mouse_push_event_button(mouse_dev, 1, b1);
+		b1_pressed = b1;
+	}
+	
+	if (b2 != b2_pressed) {
+		mouse_push_event_button(mouse_dev, 2, b2);
+		b1_pressed = b1;
+	}
+	
+	if (dx != 0 || dy != 0)
+		mouse_push_event_move(mouse_dev, dx, dy);
+}
+
+mouse_proto_ops_t adb_proto = {
+	.parse = adb_proto_parse,
+	.init = adb_proto_init
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/proto/mousedev.c
===================================================================
--- uspace/srv/hid/input/proto/mousedev.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/proto/mousedev.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief Mouse device connector controller driver.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <vfs/vfs_sess.h>
+#include <malloc.h>
+#include <async.h>
+#include <errno.h>
+#include <ipc/mouseev.h>
+#include <input.h>
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+
+/** Mousedev softstate */
+typedef struct {
+	/** Link to generic mouse device */
+	mouse_dev_t *mouse_dev;
+	
+	/** Session to mouse device */
+	async_sess_t *sess;
+	
+	/** File descriptor of open mousedev device */
+	int fd;
+} mousedev_t;
+
+static mousedev_t *mousedev_new(mouse_dev_t *mdev)
+{
+	mousedev_t *mousedev = calloc(1, sizeof(mousedev_t));
+	if (mousedev == NULL)
+		return NULL;
+	
+	mousedev->mouse_dev = mdev;
+	mousedev->fd = -1;
+	
+	return mousedev;
+}
+
+static void mousedev_destroy(mousedev_t *mousedev)
+{
+	if (mousedev->sess != NULL)
+		async_hangup(mousedev->sess);
+	
+	if (mousedev->fd >= 0)
+		close(mousedev->fd);
+	
+	free(mousedev);
+}
+
+static void mousedev_callback_conn(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
+{
+	/* Mousedev device structure */
+	mousedev_t *mousedev = (mousedev_t *) arg;
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* XXX Handle hangup */
+			return;
+		}
+		
+		int retval;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case MOUSEEV_MOVE_EVENT:
+			mouse_push_event_move(mousedev->mouse_dev, IPC_GET_ARG1(call),
+			    IPC_GET_ARG2(call));
+			retval = EOK;
+			break;
+		case MOUSEEV_BUTTON_EVENT:
+			mouse_push_event_button(mousedev->mouse_dev, IPC_GET_ARG1(call),
+			    IPC_GET_ARG2(call));
+			retval = EOK;
+			break;
+		default:
+			retval = ENOTSUP;
+			break;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+static int mousedev_proto_init(mouse_dev_t *mdev)
+{
+	const char *pathname = mdev->dev_path;
+	
+	int fd = open(pathname, O_RDWR);
+	if (fd < 0)
+		return -1;
+	
+	async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd);
+	if (sess == NULL) {
+		printf("%s: Failed starting session with '%s'\n", NAME, pathname);
+		close(fd);
+		return -1;
+	}
+	
+	mousedev_t *mousedev = mousedev_new(mdev);
+	if (mousedev == NULL) {
+		printf("%s: Failed allocating device structure for '%s'.\n",
+		    NAME, pathname);
+		return -1;
+	}
+	
+	mousedev->fd = fd;
+	mousedev->sess = sess;
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (exch == NULL) {
+		printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname);
+		mousedev_destroy(mousedev);
+		return -1;
+	}
+	
+	int rc = async_connect_to_me(exch, 0, 0, 0, mousedev_callback_conn, mousedev);
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		printf("%s: Failed creating callback connection from '%s'.\n",
+		    NAME, pathname);
+		mousedev_destroy(mousedev);
+		return -1;
+	}
+	
+	return 0;
+}
+
+mouse_proto_ops_t mousedev_proto = {
+	.init = mousedev_proto_init
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/input/proto/ps2.c
===================================================================
--- uspace/srv/hid/input/proto/ps2.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
+++ uspace/srv/hid/input/proto/ps2.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup mouse_proto
+ * @ingroup input
+ * @{
+ */
+/**
+ * @file
+ * @brief PS/2 protocol driver.
+ */
+
+#include <mouse.h>
+#include <mouse_port.h>
+#include <mouse_proto.h>
+
+#define PS2_MOUSE_OUT_INIT  0xf4
+#define PS2_MOUSE_ACK       0xfa
+
+#define BUFSIZE 3
+
+typedef struct {
+	union {
+		unsigned char data[BUFSIZE];
+		struct {
+			unsigned int leftbtn : 1;
+			unsigned int rightbtn : 1;
+			unsigned int middlebtn : 1;
+			unsigned int isone : 1; /* Always one */
+			unsigned int xsign : 1;
+			unsigned int ysign : 1;
+			unsigned int xovfl : 1;
+			unsigned int yovfl : 1;
+			unsigned char x;
+			unsigned char y;
+		} val;
+	} u;
+} ps2packet_t;
+
+static ps2packet_t buf;
+static unsigned int bufpos;
+static unsigned int leftbtn;
+static unsigned int rightbtn;
+static unsigned int middlebtn;
+
+static mouse_dev_t *mouse_dev;
+
+static int ps2_proto_init(mouse_dev_t *mdev)
+{
+	mouse_dev = mdev;
+	bufpos = 0;
+	leftbtn = 0;
+	rightbtn = 0;
+	
+	mouse_dev->port_ops->write(PS2_MOUSE_OUT_INIT);
+	return 0;
+}
+
+/** Convert 9-bit 2-complement signed number to integer */
+static int bit9toint(int sign, unsigned char data)
+{
+	int tmp;
+	
+	if (!sign)
+		return data;
+	
+	tmp = ((unsigned char) ~data) + 1;
+	return -tmp;
+}
+
+/** Process mouse data */
+static void ps2_proto_parse(sysarg_t data)
+{
+	int x, y;
+	
+	/* Check that we have not lost synchronization */
+	if (bufpos == 0 && !(data & 0x8))
+		return; /* Synchro lost, ignore byte */
+	
+	buf.u.data[bufpos++] = data;
+	if (bufpos == BUFSIZE) {
+		bufpos = 0;
+		
+		if (buf.u.val.leftbtn ^ leftbtn) {
+			leftbtn = buf.u.val.leftbtn;
+			mouse_push_event_button(mouse_dev, 1, leftbtn);
+		}
+		
+		if (buf.u.val.rightbtn ^ rightbtn) {
+			rightbtn = buf.u.val.rightbtn;
+			mouse_push_event_button(mouse_dev, 2, rightbtn);
+		}
+		
+		if (buf.u.val.middlebtn ^ middlebtn) {
+			middlebtn = buf.u.val.middlebtn;
+			mouse_push_event_button(mouse_dev, 3, middlebtn);
+		}
+		
+		x = bit9toint(buf.u.val.xsign, buf.u.val.x);
+		y = -bit9toint(buf.u.val.ysign, buf.u.val.y);
+		
+		if (x != 0 || y != 0)
+			mouse_push_event_move(mouse_dev, x, y);
+	}
+}
+
+mouse_proto_ops_t ps2_proto = {
+	.parse = ps2_proto_parse,
+	.init = ps2_proto_init
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/hid/kbd/Makefile
===================================================================
--- uspace/srv/hid/kbd/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,167 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
-EXTRA_CFLAGS = -Iinclude
-BINARY = kbd
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-## Sources
-#
-
-SOURCES = \
-	generic/kbd.c \
-	genarch/gsp.c \
-	genarch/stroke.c \
-	layout/cz.c \
-	layout/us_qwerty.c \
-	layout/us_dvorak.c
-
-ifeq ($(UARCH),amd64)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(UARCH),arm32)
-	ifeq ($(MACHINE),gta02)
-		SOURCES += \
-			port/chardev.c \
-			ctl/stty.c
-	endif
-	ifeq ($(MACHINE),testarm)
-		SOURCES += \
-			port/gxemul.c
-		
-		ifeq ($(CONFIG_FB),y)
-			SOURCES += \
-				ctl/gxe_fb.c
-		else
-			SOURCES += \
-				ctl/stty.c
-		endif
-	endif
-	ifeq ($(MACHINE),integratorcp)
-		SOURCES += \
-			port/pl050.c \
-			ctl/pc.c
-	endif
-endif
-
-ifeq ($(UARCH),ia32)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(MACHINE),i460GX)
-	SOURCES += \
-		port/chardev.c \
-		ctl/pc.c
-endif
-
-ifeq ($(MACHINE),ski)
-	SOURCES += \
-		port/ski.c \
-		ctl/stty.c
-endif
-
-ifeq ($(MACHINE),msim)
-	SOURCES += \
-		port/msim.c \
-		ctl/stty.c
-endif
-
-ifeq ($(MACHINE),lgxemul)
-	SOURCES += \
-		port/gxemul.c
-	
-	ifeq ($(CONFIG_FB),y)
-		SOURCES += \
-			ctl/gxe_fb.c
-	else
-		SOURCES += \
-			ctl/stty.c
-	endif
-endif
-
-ifeq ($(MACHINE),bgxemul)
-	SOURCES += \
-		port/gxemul.c
-	
-	ifeq ($(CONFIG_FB),y)
-		SOURCES += \
-			ctl/gxe_fb.c
-	else
-		SOURCES += \
-			ctl/stty.c
-	endif
-endif
-
-ifeq ($(UARCH),ppc32)
-	SOURCES += \
-		port/adb.c \
-		ctl/apple.c
-endif
-
-ifeq ($(UARCH),sparc64)
-	ifeq ($(PROCESSOR),sun4v)
-		SOURCES += \
-			port/niagara.c \
-			ctl/stty.c
-	else
-		ifeq ($(MACHINE),serengeti)
-			SOURCES += \
-				port/sgcn.c \
-				ctl/stty.c
-		endif
-		ifeq ($(MACHINE),generic)
-			SOURCES += \
-			port/sun.c \
-			port/z8530.c \
-			port/ns16550.c \
-			ctl/sun.c
-		endif
-	endif
-endif
-
-ifeq ($(UARCH),abs32le)
-	SOURCES += \
-		port/dummy.c \
-		ctl/pc.c
-endif
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/hid/kbd/ctl/apple.c
===================================================================
--- uspace/srv/hid/kbd/ctl/apple.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,209 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief	Apple ADB keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-
-#define KBD_KEY_RELEASE		0x80
-
-static int scanmap[];
-
-int kbd_ctl_init(void)
-{
-	return 0;
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	console_ev_type_t type;
-	unsigned int key;
-
-	if (scancode < 0 || scancode >= 0x100)
-		return;
-
-	if (scancode & KBD_KEY_RELEASE) {
-		scancode &= ~KBD_KEY_RELEASE;
-		type = KEY_RELEASE;
-	} else {
-		type = KEY_PRESS;
-	}
-
-	key = scanmap[scancode];
-	if (key != 0)
-		kbd_push_ev(type, key);
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-static int scanmap[] = {
-	[0x00] = KC_A,
-	[0x01] = KC_S,
-	[0x02] = KC_D,
-	[0x03] = KC_F,
-	[0x04] = KC_H,
-	[0x05] = KC_G,
-	[0x06] = KC_Z,
-	[0x07] = KC_X,
-	[0x08] = KC_C,
-	[0x09] = KC_V,
-	[0x0a] = KC_BACKSLASH,
-	[0x0b] = KC_B,
-	[0x0c] = KC_Q,
-	[0x0d] = KC_W,
-	[0x0e] = KC_E,
-	[0x0f] = KC_R,
-	[0x10] = KC_Y,
-	[0x11] = KC_T,
-	[0x12] = KC_1,
-	[0x13] = KC_2,
-	[0x14] = KC_3,
-	[0x15] = KC_4,
-	[0x16] = KC_6,
-	[0x17] = KC_5,
-	[0x18] = KC_EQUALS,
-	[0x19] = KC_9,
-	[0x1a] = KC_7,
-	[0x1b] = KC_MINUS,
-	[0x1c] = KC_8,
-	[0x1d] = KC_0,
-	[0x1e] = KC_RBRACKET,
-	[0x1f] = KC_O,
-	[0x20] = KC_U,
-	[0x21] = KC_LBRACKET,
-	[0x22] = KC_I,
-	[0x23] = KC_P,
-	[0x24] = KC_ENTER,
-	[0x25] = KC_L,
-	[0x26] = KC_J,
-	[0x27] = KC_QUOTE,
-	[0x28] = KC_K,
-	[0x29] = KC_SEMICOLON,
-	[0x2a] = KC_BACKSLASH,
-	[0x2b] = KC_COMMA,
-	[0x2c] = KC_SLASH,
-	[0x2d] = KC_N,
-	[0x2e] = KC_M,
-	[0x2f] = KC_PERIOD,
-	[0x30] = KC_TAB,
-	[0x31] = KC_SPACE,
-	[0x32] = KC_BACKTICK,
-	[0x33] = KC_BACKSPACE,
-	[0x34] = 0,
-	[0x35] = KC_ESCAPE,
-	[0x36] = KC_LCTRL,
-	[0x37] = 0,
-	[0x38] = KC_LSHIFT,
-	[0x39] = KC_CAPS_LOCK,
-	[0x3a] = KC_LALT,
-	[0x3b] = KC_LEFT,
-	[0x3c] = KC_RIGHT,
-	[0x3d] = KC_DOWN,
-	[0x3e] = KC_UP,
-	[0x3f] = 0,
-	[0x40] = 0,
-	[0x41] = KC_NPERIOD,
-	[0x42] = 0,
-	[0x43] = KC_NTIMES,
-	[0x44] = 0,
-	[0x45] = KC_NPLUS,
-	[0x46] = 0,
-	[0x47] = KC_NUM_LOCK,
-	[0x48] = 0,
-	[0x49] = 0,
-	[0x4a] = 0,
-	[0x4b] = KC_NSLASH,
-	[0x4c] = KC_NENTER,
-	[0x4d] = 0,
-	[0x4e] = KC_NMINUS,
-	[0x4f] = 0,
-	[0x50] = 0,
-	[0x51] = 0,
-	[0x52] = KC_N0,
-	[0x53] = KC_N1,
-	[0x54] = KC_N2,
-	[0x55] = KC_N3,
-	[0x56] = KC_N4,
-	[0x57] = KC_N5,
-	[0x58] = KC_N6,
-	[0x59] = KC_N7,
-	[0x5a] = 0,
-	[0x5b] = KC_N8,
-	[0x5c] = KC_N9,
-	[0x5d] = 0,
-	[0x5e] = 0,
-	[0x5f] = 0,
-	[0x60] = KC_F5,
-	[0x61] = KC_F6,
-	[0x62] = KC_F7,
-	[0x63] = KC_F3,
-	[0x64] = KC_F8,
-	[0x65] = KC_F9,
-	[0x66] = 0,
-	[0x67] = KC_F11,
-	[0x68] = 0,
-	[0x69] = 0,
-	[0x6a] = 0,
-	[0x6b] = KC_SCROLL_LOCK,
-	[0x6c] = 0,
-	[0x6d] = KC_F10,
-	[0x6e] = 0,
-	[0x6f] = KC_F12,
-	[0x70] = 0,
-	[0x71] = 0,
-	[0x72] = KC_INSERT,
-	[0x73] = KC_HOME,
-	[0x74] = KC_PAGE_UP,
-	[0x75] = KC_DELETE,
-	[0x76] = KC_F4,
-	[0x77] = KC_END,
-	[0x78] = KC_F2,
-	[0x79] = KC_PAGE_DOWN,
-	[0x7a] = KC_F1,
-	[0x7b] = KC_RSHIFT,
-	[0x7c] = KC_RALT,
-	[0x7d] = KC_RCTRL,
-	[0x7e] = 0,
-	[0x7f] = 0
-};
-
-/** @}
- */
Index: uspace/srv/hid/kbd/ctl/gxe_fb.c
===================================================================
--- uspace/srv/hid/kbd/ctl/gxe_fb.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,234 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief	GXEmul framebuffer-mode keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <gsp.h>
-#include <stroke.h>
-
-/** Scancode parser */
-static gsp_t sp;
-
-/** Current parser state */
-static int ds;
-
-#include <stdio.h>
-
-int seq_defs[] = {
-	/* Not shifted */
-
-	0,	KC_BACKTICK,	0x60, GSP_END,
-
-	0,	KC_1,		0x31, GSP_END,
-	0,	KC_2,		0x32, GSP_END,
-	0,	KC_3,		0x33, GSP_END,
-	0,	KC_4,		0x34, GSP_END,
-	0,	KC_5,		0x35, GSP_END,
-	0,	KC_6,		0x36, GSP_END,
-	0,	KC_7,		0x37, GSP_END,
-	0,	KC_8,		0x38, GSP_END,
-	0,	KC_9,		0x39, GSP_END,
-	0,	KC_0,		0x30, GSP_END,
-
-	0,	KC_MINUS,	0x2d, GSP_END,
-	0,	KC_EQUALS,	0x3d, GSP_END,
-	0,	KC_BACKSPACE,	0x08, GSP_END,
-
-	0,	KC_TAB,		0x09, GSP_END,
-
-	0,	KC_Q,		0x71, GSP_END,
-	0,	KC_W,		0x77, GSP_END,
-	0,	KC_E,		0x65, GSP_END,
-	0,	KC_R,		0x72, GSP_END,
-	0,	KC_T,		0x74, GSP_END,
-	0,	KC_Y,		0x79, GSP_END,
-	0,	KC_U,		0x75, GSP_END,
-	0,	KC_I,		0x69, GSP_END,
-	0,	KC_O,		0x6f, GSP_END,
-	0,	KC_P,		0x70, GSP_END,
-
-	0,	KC_LBRACKET,	0x5b, GSP_END,
-	0,	KC_RBRACKET,	0x5d, GSP_END,
-
-	0,	KC_A,		0x61, GSP_END,
-	0,	KC_S,		0x73, GSP_END,
-	0,	KC_D,		0x64, GSP_END,
-	0,	KC_F,		0x66, GSP_END,
-	0,	KC_G,		0x67, GSP_END,
-	0,	KC_H,		0x68, GSP_END,
-	0,	KC_J,		0x6a, GSP_END,
-	0,	KC_K,		0x6b, GSP_END,
-	0,	KC_L,		0x6c, GSP_END,
-
-	0,	KC_SEMICOLON,	0x3b, GSP_END,
-	0,	KC_QUOTE,	0x27, GSP_END,
-	0,	KC_BACKSLASH,	0x5c, GSP_END,
-
-	0,	KC_Z,		0x7a, GSP_END,
-	0,	KC_X,		0x78, GSP_END,
-	0,	KC_C,		0x63, GSP_END,
-	0,	KC_V,		0x76, GSP_END,
-	0,	KC_B,		0x62, GSP_END,
-	0,	KC_N,		0x6e, GSP_END,
-	0,	KC_M,		0x6d, GSP_END,
-
-	0,	KC_COMMA,	0x2c, GSP_END,
-	0,	KC_PERIOD,	0x2e, GSP_END,
-	0,	KC_SLASH,	0x2f, GSP_END,
-
-	/* Shifted */
-
-	KM_SHIFT,	KC_BACKTICK,	0x7e, GSP_END,
-
-	KM_SHIFT,	KC_1,		0x21, GSP_END,
-	KM_SHIFT,	KC_2,		0x40, GSP_END,
-	KM_SHIFT,	KC_3,		0x23, GSP_END,
-	KM_SHIFT,	KC_4,		0x24, GSP_END,
-	KM_SHIFT,	KC_5,		0x25, GSP_END,
-	KM_SHIFT,	KC_6,		0x5e, GSP_END,
-	KM_SHIFT,	KC_7,		0x26, GSP_END,
-	KM_SHIFT,	KC_8,		0x2a, GSP_END,
-	KM_SHIFT,	KC_9,		0x28, GSP_END,
-	KM_SHIFT,	KC_0,		0x29, GSP_END,
-
-	KM_SHIFT,	KC_MINUS,	0x5f, GSP_END,
-	KM_SHIFT,	KC_EQUALS,	0x2b, GSP_END,
-
-	KM_SHIFT,	KC_Q,		0x51, GSP_END,
-	KM_SHIFT,	KC_W,		0x57, GSP_END,
-	KM_SHIFT,	KC_E,		0x45, GSP_END,
-	KM_SHIFT,	KC_R,		0x52, GSP_END,
-	KM_SHIFT,	KC_T,		0x54, GSP_END,
-	KM_SHIFT,	KC_Y,		0x59, GSP_END,
-	KM_SHIFT,	KC_U,		0x55, GSP_END,
-	KM_SHIFT,	KC_I,		0x49, GSP_END,
-	KM_SHIFT,	KC_O,		0x4f, GSP_END,
-	KM_SHIFT,	KC_P,		0x50, GSP_END,
-
-	KM_SHIFT,	KC_LBRACKET,	0x7b, GSP_END,
-	KM_SHIFT,	KC_RBRACKET,	0x7d, GSP_END,
-
-	KM_SHIFT,	KC_A,		0x41, GSP_END,
-	KM_SHIFT,	KC_S,		0x53, GSP_END,
-	KM_SHIFT,	KC_D,		0x44, GSP_END,
-	KM_SHIFT,	KC_F,		0x46, GSP_END,
-	KM_SHIFT,	KC_G,		0x47, GSP_END,
-	KM_SHIFT,	KC_H,		0x48, GSP_END,
-	KM_SHIFT,	KC_J,		0x4a, GSP_END,
-	KM_SHIFT,	KC_K,		0x4b, GSP_END,
-	KM_SHIFT,	KC_L,		0x4c, GSP_END,
-
-	KM_SHIFT,	KC_SEMICOLON,	0x3a, GSP_END,
-	KM_SHIFT,	KC_QUOTE,	0x22, GSP_END,
-	KM_SHIFT,	KC_BACKSLASH,	0x7c, GSP_END,
-
-	KM_SHIFT,	KC_Z,		0x5a, GSP_END,
-	KM_SHIFT,	KC_X,		0x58, GSP_END,
-	KM_SHIFT,	KC_C,		0x43, GSP_END,
-	KM_SHIFT,	KC_V,		0x56, GSP_END,
-	KM_SHIFT,	KC_B,		0x42, GSP_END,
-	KM_SHIFT,	KC_N,		0x4e, GSP_END,
-	KM_SHIFT,	KC_M,		0x4d, GSP_END,
-
-	KM_SHIFT,	KC_COMMA,	0x3c, GSP_END,
-	KM_SHIFT,	KC_PERIOD,	0x3e, GSP_END,
-	KM_SHIFT,	KC_SLASH,	0x3f, GSP_END,
-
-	/* ... */
-
-	0,	KC_SPACE,	0x20, GSP_END,
-	0,	KC_ENTER,	0x0a, GSP_END,
-	0,	KC_ENTER,	0x0d, GSP_END,
-
-	0,	KC_ESCAPE,	0x1b, 0x1b, GSP_END,
-
-	0,	KC_F1,		0x1b, 0x5b, 0x4f, 0x50, GSP_END,
-	0,	KC_F2,		0x1b, 0x5b, 0x4f, 0x51, GSP_END,
-	0,	KC_F3,		0x1b, 0x5b, 0x4f, 0x52, GSP_END,
-	0,	KC_F4,		0x1b, 0x5b, 0x4f, 0x53, GSP_END,
-	0,	KC_F5,		0x1b, 0x5b, 0x31, 0x35, GSP_END,
-	0,	KC_F6,		0x1b, 0x5b, 0x31, 0x37, GSP_END,
-	0,	KC_F7,		0x1b, 0x5b, 0x31, 0x38, GSP_END,
-	0,	KC_F8,		0x1b, 0x5b, 0x31, 0x39, GSP_END,
-	0,	KC_F9,		0x1b, 0x5b, 0x32, 0x38, GSP_END,
-	0,	KC_F10,		0x1b, 0x5b, 0x32, 0x39, GSP_END,
-	0,	KC_F11,		0x1b, 0x5b, 0x32, 0x33, GSP_END,
-	0,	KC_F12,		0x1b, 0x5b, 0x32, 0x34, GSP_END,
-
-	0,	KC_INSERT,	0x1b, 0x5b, 0x32, 0x7e, GSP_END,
-	0,	KC_HOME,	0x1b, 0x5b, 0x48, GSP_END,
-	0,	KC_PAGE_UP,	0x1b, 0x5b, 0x35, 0x7e, GSP_END,
-	0,	KC_DELETE,	0x1b, 0x5b, 0x33, 0x7e, GSP_END,
-	0,	KC_END,		0x1b, 0x5b, 0x46, GSP_END,
-	0,	KC_PAGE_DOWN,	0x1b, 0x5b, 0x36, 0x7e, GSP_END,
-
-	0,	KC_UP,		0x1b, 0x5b, 0x41, GSP_END,
-	0,	KC_LEFT,	0x1b, 0x5b, 0x44, GSP_END,
-	0,	KC_DOWN,	0x1b, 0x5b, 0x42, GSP_END,
-	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
-
-	0,	0
-};
-
-int kbd_ctl_init(void)
-{
-	ds = 0;
-
-	gsp_init(&sp);
-	return gsp_insert_defs(&sp, seq_defs);
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	unsigned mods, key;
-
-	ds = gsp_step(&sp, ds, scancode, &mods, &key);
-	if (key != 0) {
-		stroke_sim(mods, key);
-	}
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/ctl/pc.c
===================================================================
--- uspace/srv/hid/kbd/ctl/pc.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,273 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief PC keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <kbd_port.h>
-#include <gsp.h>
-
-enum dec_state {
-	ds_s,
-	ds_e
-};
-
-enum special_code {
-	SC_ACK = 0xfa,
-	SC_NAK = 0xfe
-};
-
-enum lock_ind_bits {
-	LI_SCROLL	= 0x01,
-	LI_NUM		= 0x02,
-	LI_CAPS		= 0x04
-};
-
-enum kbd_command {
-	KBD_CMD_SET_LEDS = 0xed
-};
-
-static enum dec_state ds;
-
-static int scanmap_simple[] = {
-
-	[0x29] = KC_BACKTICK,
-
-	[0x02] = KC_1,
-	[0x03] = KC_2,
-	[0x04] = KC_3,
-	[0x05] = KC_4,
-	[0x06] = KC_5,
-	[0x07] = KC_6,
-	[0x08] = KC_7,
-	[0x09] = KC_8,
-	[0x0a] = KC_9,
-	[0x0b] = KC_0,
-
-	[0x0c] = KC_MINUS,
-	[0x0d] = KC_EQUALS,
-	[0x0e] = KC_BACKSPACE,
-
-	[0x0f] = KC_TAB,
-
-	[0x10] = KC_Q,
-	[0x11] = KC_W,
-	[0x12] = KC_E,
-	[0x13] = KC_R,
-	[0x14] = KC_T,
-	[0x15] = KC_Y,
-	[0x16] = KC_U,
-	[0x17] = KC_I,
-	[0x18] = KC_O,
-	[0x19] = KC_P,
-
-	[0x1a] = KC_LBRACKET,
-	[0x1b] = KC_RBRACKET,
-
-	[0x3a] = KC_CAPS_LOCK,
-
-	[0x1e] = KC_A,
-	[0x1f] = KC_S,
-	[0x20] = KC_D,
-	[0x21] = KC_F,
-	[0x22] = KC_G,
-	[0x23] = KC_H,
-	[0x24] = KC_J,
-	[0x25] = KC_K,
-	[0x26] = KC_L,
-
-	[0x27] = KC_SEMICOLON,
-	[0x28] = KC_QUOTE,
-	[0x2b] = KC_BACKSLASH,
-
-	[0x2a] = KC_LSHIFT,
-
-	[0x2c] = KC_Z,
-	[0x2d] = KC_X,
-	[0x2e] = KC_C,
-	[0x2f] = KC_V,
-	[0x30] = KC_B,
-	[0x31] = KC_N,
-	[0x32] = KC_M,
-
-	[0x33] = KC_COMMA,
-	[0x34] = KC_PERIOD,
-	[0x35] = KC_SLASH,
-
-	[0x36] = KC_RSHIFT,
-
-	[0x1d] = KC_LCTRL,
-	[0x38] = KC_LALT,
-	[0x39] = KC_SPACE,
-
-	[0x01] = KC_ESCAPE,
-
-	[0x3b] = KC_F1,
-	[0x3c] = KC_F2,
-	[0x3d] = KC_F3,
-	[0x3e] = KC_F4,
-	[0x3f] = KC_F5,
-	[0x40] = KC_F6,
-	[0x41] = KC_F7,
-
-	[0x42] = KC_F8,
-	[0x43] = KC_F9,
-	[0x44] = KC_F10,
-
-	[0x57] = KC_F11,
-	[0x58] = KC_F12,
-
-	[0x46] = KC_SCROLL_LOCK,
-
-	[0x1c] = KC_ENTER,
-
-	[0x45] = KC_NUM_LOCK,
-	[0x37] = KC_NTIMES,
-	[0x4a] = KC_NMINUS,
-	[0x4e] = KC_NPLUS,
-	[0x47] = KC_N7,
-	[0x48] = KC_N8,
-	[0x49] = KC_N9,
-	[0x4b] = KC_N4,
-	[0x4c] = KC_N5,
-	[0x4d] = KC_N6,
-	[0x4f] = KC_N1,
-	[0x50] = KC_N2,
-	[0x51] = KC_N3,
-	[0x52] = KC_N0,
-	[0x53] = KC_NPERIOD
-};
-
-static int scanmap_e0[] = {
-	[0x38] = KC_RALT,
-	[0x1d] = KC_RSHIFT,
-
-	[0x37] = KC_PRTSCR,
-
-	[0x52] = KC_INSERT,
-	[0x47] = KC_HOME,
-	[0x49] = KC_PAGE_UP,
-
-	[0x53] = KC_DELETE,
-	[0x4f] = KC_END,
-	[0x51] = KC_PAGE_DOWN,
-
-	[0x48] = KC_UP,
-	[0x4b] = KC_LEFT,
-	[0x50] = KC_DOWN,
-	[0x4d] = KC_RIGHT,
-
-	[0x35] = KC_NSLASH,
-	[0x1c] = KC_NENTER
-};
-
-int kbd_ctl_init(void)
-{
-	ds = ds_s;
-	return 0;
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	console_ev_type_t type;
-	unsigned int key;
-	int *map;
-	size_t map_length;
-
-	/*
-	 * ACK/NAK are returned as response to us sending a command.
-	 * We are not interested in them.
-	 */
-	if (scancode == SC_ACK || scancode == SC_NAK)
-		return;
-
-	if (scancode == 0xe0) {
-		ds = ds_e;
-		return;
-	}
-
-	switch (ds) {
-	case ds_s:
-		map = scanmap_simple;
-		map_length = sizeof(scanmap_simple) / sizeof(int);
-		break;
-	case ds_e:
-		map = scanmap_e0;
-		map_length = sizeof(scanmap_e0) / sizeof(int);
-		break;
-	default:
-		map = NULL;
-		map_length = 0;
-	}
-
-	ds = ds_s;
-
-	if (scancode & 0x80) {
-		scancode &= ~0x80;
-		type = KEY_RELEASE;
-	} else {
-		type = KEY_PRESS;
-	}
-
-	if ((scancode < 0) || ((size_t) scancode >= map_length))
-		return;
-
-	key = map[scancode];
-	if (key != 0)
-		kbd_push_ev(type, key);
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	uint8_t b;
-
-	b = 0;
-	if ((mods & KM_CAPS_LOCK) != 0)
-		b = b | LI_CAPS;
-	if ((mods & KM_NUM_LOCK) != 0)
-		b = b | LI_NUM;
-	if ((mods & KM_SCROLL_LOCK) != 0)
-		b = b | LI_SCROLL;
-
-	kbd_port_write(KBD_CMD_SET_LEDS);
-	kbd_port_write(b);
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/ctl/stty.c
===================================================================
--- uspace/srv/hid/kbd/ctl/stty.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,233 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief	Serial TTY-like keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-#include <gsp.h>
-#include <stroke.h>
-
-/** Scancode parser */
-static gsp_t sp;
-
-/** Current parser state */
-static int ds;
-
-#include <stdio.h>
-
-int seq_defs[] = {
-	/* Not shifted */
-
-	0,	KC_BACKTICK,	0x60, GSP_END,
-
-	0,	KC_1,		0x31, GSP_END,
-	0,	KC_2,		0x32, GSP_END,
-	0,	KC_3,		0x33, GSP_END,
-	0,	KC_4,		0x34, GSP_END,
-	0,	KC_5,		0x35, GSP_END,
-	0,	KC_6,		0x36, GSP_END,
-	0,	KC_7,		0x37, GSP_END,
-	0,	KC_8,		0x38, GSP_END,
-	0,	KC_9,		0x39, GSP_END,
-	0,	KC_0,		0x30, GSP_END,
-
-	0,	KC_MINUS,	0x2d, GSP_END,
-	0,	KC_EQUALS,	0x3d, GSP_END,
-	0,	KC_BACKSPACE,	0x08, GSP_END,
-
-	0,	KC_TAB,		0x09, GSP_END,
-
-	0,	KC_Q,		0x71, GSP_END,
-	0,	KC_W,		0x77, GSP_END,
-	0,	KC_E,		0x65, GSP_END,
-	0,	KC_R,		0x72, GSP_END,
-	0,	KC_T,		0x74, GSP_END,
-	0,	KC_Y,		0x79, GSP_END,
-	0,	KC_U,		0x75, GSP_END,
-	0,	KC_I,		0x69, GSP_END,
-	0,	KC_O,		0x6f, GSP_END,
-	0,	KC_P,		0x70, GSP_END,
-
-	0,	KC_LBRACKET,	0x5b, GSP_END,
-	0,	KC_RBRACKET,	0x5d, GSP_END,
-
-	0,	KC_A,		0x61, GSP_END,
-	0,	KC_S,		0x73, GSP_END,
-	0,	KC_D,		0x64, GSP_END,
-	0,	KC_F,		0x66, GSP_END,
-	0,	KC_G,		0x67, GSP_END,
-	0,	KC_H,		0x68, GSP_END,
-	0,	KC_J,		0x6a, GSP_END,
-	0,	KC_K,		0x6b, GSP_END,
-	0,	KC_L,		0x6c, GSP_END,
-
-	0,	KC_SEMICOLON,	0x3b, GSP_END,
-	0,	KC_QUOTE,	0x27, GSP_END,
-	0,	KC_BACKSLASH,	0x5c, GSP_END,
-
-	0,	KC_Z,		0x7a, GSP_END,
-	0,	KC_X,		0x78, GSP_END,
-	0,	KC_C,		0x63, GSP_END,
-	0,	KC_V,		0x76, GSP_END,
-	0,	KC_B,		0x62, GSP_END,
-	0,	KC_N,		0x6e, GSP_END,
-	0,	KC_M,		0x6d, GSP_END,
-
-	0,	KC_COMMA,	0x2c, GSP_END,
-	0,	KC_PERIOD,	0x2e, GSP_END,
-	0,	KC_SLASH,	0x2f, GSP_END,
-
-	/* Shifted */
-
-	KM_SHIFT,	KC_BACKTICK,	0x7e, GSP_END,
-
-	KM_SHIFT,	KC_1,		0x21, GSP_END,
-	KM_SHIFT,	KC_2,		0x40, GSP_END,
-	KM_SHIFT,	KC_3,		0x23, GSP_END,
-	KM_SHIFT,	KC_4,		0x24, GSP_END,
-	KM_SHIFT,	KC_5,		0x25, GSP_END,
-	KM_SHIFT,	KC_6,		0x5e, GSP_END,
-	KM_SHIFT,	KC_7,		0x26, GSP_END,
-	KM_SHIFT,	KC_8,		0x2a, GSP_END,
-	KM_SHIFT,	KC_9,		0x28, GSP_END,
-	KM_SHIFT,	KC_0,		0x29, GSP_END,
-
-	KM_SHIFT,	KC_MINUS,	0x5f, GSP_END,
-	KM_SHIFT,	KC_EQUALS,	0x2b, GSP_END,
-
-	KM_SHIFT,	KC_Q,		0x51, GSP_END,
-	KM_SHIFT,	KC_W,		0x57, GSP_END,
-	KM_SHIFT,	KC_E,		0x45, GSP_END,
-	KM_SHIFT,	KC_R,		0x52, GSP_END,
-	KM_SHIFT,	KC_T,		0x54, GSP_END,
-	KM_SHIFT,	KC_Y,		0x59, GSP_END,
-	KM_SHIFT,	KC_U,		0x55, GSP_END,
-	KM_SHIFT,	KC_I,		0x49, GSP_END,
-	KM_SHIFT,	KC_O,		0x4f, GSP_END,
-	KM_SHIFT,	KC_P,		0x50, GSP_END,
-
-	KM_SHIFT,	KC_LBRACKET,	0x7b, GSP_END,
-	KM_SHIFT,	KC_RBRACKET,	0x7d, GSP_END,
-
-	KM_SHIFT,	KC_A,		0x41, GSP_END,
-	KM_SHIFT,	KC_S,		0x53, GSP_END,
-	KM_SHIFT,	KC_D,		0x44, GSP_END,
-	KM_SHIFT,	KC_F,		0x46, GSP_END,
-	KM_SHIFT,	KC_G,		0x47, GSP_END,
-	KM_SHIFT,	KC_H,		0x48, GSP_END,
-	KM_SHIFT,	KC_J,		0x4a, GSP_END,
-	KM_SHIFT,	KC_K,		0x4b, GSP_END,
-	KM_SHIFT,	KC_L,		0x4c, GSP_END,
-
-	KM_SHIFT,	KC_SEMICOLON,	0x3a, GSP_END,
-	KM_SHIFT,	KC_QUOTE,	0x22, GSP_END,
-	KM_SHIFT,	KC_BACKSLASH,	0x7c, GSP_END,
-
-	KM_SHIFT,	KC_Z,		0x5a, GSP_END,
-	KM_SHIFT,	KC_X,		0x58, GSP_END,
-	KM_SHIFT,	KC_C,		0x43, GSP_END,
-	KM_SHIFT,	KC_V,		0x56, GSP_END,
-	KM_SHIFT,	KC_B,		0x42, GSP_END,
-	KM_SHIFT,	KC_N,		0x4e, GSP_END,
-	KM_SHIFT,	KC_M,		0x4d, GSP_END,
-
-	KM_SHIFT,	KC_COMMA,	0x3c, GSP_END,
-	KM_SHIFT,	KC_PERIOD,	0x3e, GSP_END,
-	KM_SHIFT,	KC_SLASH,	0x3f, GSP_END,
-
-	/* ... */
-
-	0,	KC_SPACE,	0x20, GSP_END,
-	0,	KC_ENTER,	0x0a, GSP_END,
-	0,	KC_ENTER,	0x0d, GSP_END,
-
-	0,	KC_ESCAPE,	0x1b, 0x1b, GSP_END,
-
-	0,	KC_F1,		0x1b, 0x4f, 0x50, GSP_END,
-	0,	KC_F2,		0x1b, 0x4f, 0x51, GSP_END,
-	0,	KC_F3,		0x1b, 0x4f, 0x52, GSP_END,
-	0,	KC_F4,		0x1b, 0x4f, 0x53, GSP_END,
-	0,	KC_F5,		0x1b, 0x5b, 0x31, 0x35, 0x7e, GSP_END,
-	0,	KC_F6,		0x1b, 0x5b, 0x31, 0x37, 0x7e, GSP_END,
-	0,	KC_F7,		0x1b, 0x5b, 0x31, 0x38, 0x7e, GSP_END,
-	0,	KC_F8,		0x1b, 0x5b, 0x31, 0x39, 0x7e, GSP_END,
-	0,	KC_F9,		0x1b, 0x5b, 0x32, 0x30, 0x7e, GSP_END,
-	0,	KC_F10,		0x1b, 0x5b, 0x32, 0x31, 0x7e, GSP_END,
-	0,	KC_F11,		0x1b, 0x5b, 0x32, 0x33, 0x7e, GSP_END,
-	0,	KC_F12,		0x1b, 0x5b, 0x32, 0x34, 0x7e, GSP_END,
-
-	0,	KC_INSERT,	0x1b, 0x5b, 0x32, 0x7e, GSP_END,
-	0,	KC_HOME,	0x1b, 0x5b, 0x48, GSP_END,
-	0,	KC_PAGE_UP,	0x1b, 0x5b, 0x35, 0x7e, GSP_END,
-	0,	KC_DELETE,	0x1b, 0x5b, 0x33, 0x7e, GSP_END,
-	0,	KC_END,		0x1b, 0x5b, 0x46, GSP_END,
-	0,	KC_PAGE_DOWN,	0x1b, 0x5b, 0x36, 0x7e, GSP_END,
-
-	0,	KC_UP,		0x1b, 0x5b, 0x41, GSP_END,
-	0,	KC_LEFT,	0x1b, 0x5b, 0x44, GSP_END,
-	0,	KC_DOWN,	0x1b, 0x5b, 0x42, GSP_END,
-	0,	KC_RIGHT,	0x1b, 0x5b, 0x43, GSP_END,
-
-	0,	0
-};
-
-int kbd_ctl_init(void)
-{
-	ds = 0;
-
-	gsp_init(&sp);
-	return gsp_insert_defs(&sp, seq_defs);
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	unsigned mods, key;
-
-	ds = gsp_step(&sp, ds, scancode, &mods, &key);
-	if (key != 0) {
-		stroke_sim(mods, key);
-	}
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/ctl/sun.c
===================================================================
--- uspace/srv/hid/kbd/ctl/sun.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,214 +1,0 @@
-/*
- * Copyright (c) 2006 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_ctl
- * @ingroup kbd
- * @{
- */
-/**
- * @file
- * @brief	Sun keyboard controller driver.
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <kbd_ctl.h>
-
-#define KBD_KEY_RELEASE		0x80
-#define KBD_ALL_KEYS_UP		0x7f
-
-static int scanmap_simple[];
-
-int kbd_ctl_init(void)
-{
-	return 0;
-}
-
-void kbd_ctl_parse_scancode(int scancode)
-{
-	console_ev_type_t type;
-	unsigned int key;
-
-	if (scancode < 0 || scancode >= 0x100)
-		return;
-
-	if (scancode == KBD_ALL_KEYS_UP)
-		return;
-
-	if (scancode & KBD_KEY_RELEASE) {
-		scancode &= ~KBD_KEY_RELEASE;
-		type = KEY_RELEASE;
-	} else {
-		type = KEY_PRESS;
-	}
-
-	key = scanmap_simple[scancode];
-	if (key != 0)
-		kbd_push_ev(type, key);
-}
-
-void kbd_ctl_set_ind(unsigned mods)
-{
-	(void) mods;
-}
-
-/** Primary meaning of scancodes. */
-static int scanmap_simple[] = {
-	[0x00] = 0,
-	[0x01] = 0,
-	[0x02] = 0,
-	[0x03] = 0,
-	[0x04] = 0,
-	[0x05] = KC_F1,
-	[0x06] = KC_F2,
-	[0x07] = KC_F10,
-	[0x08] = KC_F3,
-	[0x09] = KC_F11,
-	[0x0a] = KC_F4,
-	[0x0b] = KC_F12,
-	[0x0c] = KC_F5,
-	[0x0d] = KC_RALT,
-	[0x0e] = KC_F6,
-	[0x0f] = 0,
-	[0x10] = KC_F7,
-	[0x11] = KC_F8,
-	[0x12] = KC_F9,
-	[0x13] = KC_LALT,
-	[0x14] = KC_UP,
-	[0x15] = KC_PAUSE,
-	[0x16] = 0,
-	[0x17] = KC_SCROLL_LOCK,
-	[0x18] = KC_LEFT,
-	[0x19] = 0,
-	[0x1a] = 0,
-	[0x1b] = KC_DOWN,
-	[0x1c] = KC_RIGHT,
-	[0x1d] = KC_ESCAPE,
-	[0x1e] = KC_1,
-	[0x1f] = KC_2,
-	[0x20] = KC_3,
-	[0x21] = KC_4,
-	[0x22] = KC_5,
-	[0x23] = KC_6,
-	[0x24] = KC_7,
-	[0x25] = KC_8,
-	[0x26] = KC_9,
-	[0x27] = KC_0,
-	[0x28] = KC_MINUS,
-	[0x29] = KC_EQUALS,
-	[0x2a] = KC_BACKTICK,
-	[0x2b] = KC_BACKSPACE,
-	[0x2c] = KC_INSERT,
-	[0x2d] = 0,
-	[0x2e] = KC_NSLASH,
-	[0x2f] = KC_NTIMES,
-	[0x30] = 0,
-	[0x31] = 0,
-	[0x32] = KC_NPERIOD,
-	[0x33] = 0,
-	[0x34] = KC_HOME,
-	[0x35] = KC_TAB,
-	[0x36] = KC_Q,
-	[0x37] = KC_W,
-	[0x38] = KC_E,
-	[0x39] = KC_R,
-	[0x3a] = KC_T,
-	[0x3b] = KC_Y,
-	[0x3c] = KC_U,
-	[0x3d] = KC_I,
-	[0x3e] = KC_O,
-	[0x3f] = KC_P,
-	[0x40] = KC_LBRACKET,
-	[0x41] = KC_RBRACKET,
-	[0x42] = KC_DELETE,
-	[0x43] = 0,
-	[0x44] = KC_N7,
-	[0x45] = KC_N8,
-	[0x46] = KC_N9,
-	[0x47] = KC_NMINUS,
-	[0x48] = 0,
-	[0x49] = 0,
-	[0x4a] = KC_END,
-	[0x4b] = 0,
-	[0x4c] = KC_LCTRL,
-	[0x4d] = KC_A,
-	[0x4e] = KC_S,
-	[0x4f] = KC_D,
-	[0x50] = KC_F,
-	[0x51] = KC_G,
-	[0x52] = KC_H,
-	[0x53] = KC_J,
-	[0x54] = KC_K,
-	[0x55] = KC_L,
-	[0x56] = KC_SEMICOLON,
-	[0x57] = KC_QUOTE,
-	[0x58] = KC_BACKSLASH,
-	[0x59] = KC_ENTER,
-	[0x5a] = KC_NENTER,
-	[0x5b] = KC_N4,
-	[0x5c] = KC_N5,
-	[0x5d] = KC_N6,
-	[0x5e] = KC_N0,
-	[0x5f] = 0,
-	[0x60] = KC_PAGE_UP,
-	[0x61] = 0,
-	[0x62] = KC_NUM_LOCK,
-	[0x63] = KC_LSHIFT,
-	[0x64] = KC_Z,
-	[0x65] = KC_X,
-	[0x66] = KC_C,
-	[0x67] = KC_V,
-	[0x68] = KC_B,
-	[0x69] = KC_N,
-	[0x6a] = KC_M,
-	[0x6b] = KC_COMMA,
-	[0x6c] = KC_PERIOD,
-	[0x6d] = KC_SLASH,
-	[0x6e] = KC_RSHIFT,
-	[0x6f] = 0,
-	[0x70] = KC_N1,
-	[0x71] = KC_N2,
-	[0x72] = KC_N3,
-	[0x73] = 0,
-	[0x74] = 0,
-	[0x75] = 0,
-	[0x76] = 0,
-	[0x77] = KC_CAPS_LOCK,
-	[0x78] = 0,
-	[0x79] = KC_SPACE,
-	[0x7a] = 0,
-	[0x7b] = KC_PAGE_DOWN,
-	[0x7c] = 0,
-	[0x7d] = KC_NPLUS,
-	[0x7e] = 0,
-	[0x7f] = 0
-};
-
-/** @}
- */
Index: uspace/srv/hid/kbd/genarch/gsp.c
===================================================================
--- uspace/srv/hid/kbd/genarch/gsp.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,289 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup kbdgen generic
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- * @brief	Generic scancode parser.
- *
- * The scancode parser is a simple finite state machine. It is described
- * using sequences of input symbols (scancodes) and the corresponding output
- * value (mods, key pair). When the parser recognizes a sequence,
- * it outputs the value and restarts. If a transition is undefined,
- * the parser restarts, too.
- *
- * Apart from precise values, GSP_DEFAULT allows to catch general cases.
- * I.e. if we knew that after 0x1b 0x4f there always follow two more
- * scancodes, we can define (0x1b, 0x4f, GSP_DEFAULT, GSP_DEFAULT, GSP_END)
- * with null output. This will force the parser to read the entire sequence,
- * not leaving garbage on the input if it does not recognize the specific
- * sequence.
- */
-
-#include <gsp.h>
-#include <adt/hash_table.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define TRANS_TABLE_CHAINS 256
-
-/*
- * Hash table operations for the transition function.
- */
-
-static hash_index_t trans_op_hash(unsigned long key[]);
-static int trans_op_compare(unsigned long key[], hash_count_t keys,
-    link_t *item);
-static void trans_op_remove_callback(link_t *item);
-
-static hash_table_operations_t trans_ops = {
-	.hash = trans_op_hash,
-	.compare = trans_op_compare,
-	.remove_callback = trans_op_remove_callback
-};
-
-static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input);
-static void trans_insert(gsp_t *p, gsp_trans_t *t);
-static gsp_trans_t *trans_new(void);
-
-/** Initialise scancode parser. */
-void gsp_init(gsp_t *p)
-{
-	p->states = 1;
-	hash_table_create(&p->trans, TRANS_TABLE_CHAINS, 2, &trans_ops);
-}
-
-/** Insert a series of definitions into the parser.
- *
- * @param p	The parser.
- * @param defs	Definition list. Each definition starts with two output values
- *		(mods, key) and continues with a sequence of input values
- *		terminated with GSP_END. The definition list is terminated
- *		with two zeroes (0, 0) for output values.
- */
-int gsp_insert_defs(gsp_t *p, const int *defs)
-{
-	unsigned mods, key;
-	const int *dp;
-	int rc;
-
-	dp = defs;
-
-	while (1) {
-		/* Read the output values. */
-		mods = *dp++;
-		key = *dp++;
-		if (key == 0) break;
-
-		/* Insert one sequence. */		
-		rc = gsp_insert_seq(p, dp, mods, key);
-		if (rc != 0)
-			return rc;
-
-		/* Skip to the next definition. */
-		while (*dp != GSP_END)
-			++dp;
-		++dp;
-	}
-
-	return 0;
-}
-
-/** Insert one sequence into the parser.
- *
- * @param p	The parser.
- * @param seq	Sequence of input values terminated with GSP_END.
- * @param mods	Corresponsing output value.
- * @param key	Corresponsing output value.
- */
-int gsp_insert_seq(gsp_t *p, const int *seq, unsigned mods, unsigned key)
-{
-	int state;
-	gsp_trans_t *t;
-
-	state = 0;
-	t = NULL;
-
-	/* Input sequence must be non-empty. */
-	if (*seq == GSP_END)
-		return -1;
-
-	while (*(seq + 1) != GSP_END) {
-		t = trans_lookup(p, state, *seq);
-		if (t == NULL) {
-			/* Create new state. */
-			t = trans_new();
-			t->old_state = state;
-			t->input = *seq;
-			t->new_state = p->states++;
-
-			t->out_mods = 0;
-			t->out_key = 0;
-
-			trans_insert(p, t);
-		}
-		state = t->new_state;
-		++seq;
-	}
-
-	/* Process the last transition. */
-	t = trans_lookup(p, state, *seq);
-	if (t != NULL) {
-		exit(1);
-		return -1;	/* Conflicting definition. */
-	}
-
-	t = trans_new();
-	t->old_state = state;
-	t->input = *seq;
-	t->new_state = 0;
-
-	t->out_mods = mods;
-	t->out_key = key;
-
-	trans_insert(p, t);
-
-	return 0;
-}
-
-/** Compute one parser step.
- *
- * Computes the next state and output values for a given state and input.
- * This handles everything including restarts and default branches.
- *
- * @param p		The parser.
- * @param state		Old state.
- * @param input		Input symbol (scancode).
- * @param mods		Output value (modifier).
- * @param key		Output value (key).
- * @return		New state.
- */
-int gsp_step(gsp_t *p, int state, int input, unsigned *mods, unsigned *key)
-{
-	gsp_trans_t *t;
-
-	t = trans_lookup(p, state, input);
-	if (t == NULL) {
-		t = trans_lookup(p, state, GSP_DEFAULT);
-	}
-
-	if (t == NULL) {
-		printf("gsp_step: not found\n");
-		*mods = 0;
-		*key = 0;
-		return 0;
-	}
-
-	*mods = t->out_mods;
-	*key = t->out_key;
-	return t->new_state;
-}
-
-/** Transition function lookup.
- *
- * Returns the value of the transition function for the given state
- * and input. Note that the transition must be specified precisely,
- * to obtain the default branch use input = GSP_DEFAULT.
- *
- * @param p		Parser.
- * @param state		Current state.
- * @param input		Input value.
- * @return		The transition or @c NULL if not defined.
- */
-static gsp_trans_t *trans_lookup(gsp_t *p, int state, int input)
-{
-	link_t *item;
-	unsigned long key[2];
-
-	key[0] = state;
-	key[1] = input;
-
-	item = hash_table_find(&p->trans, key);
-	if (item == NULL) return NULL;
-
-	return hash_table_get_instance(item, gsp_trans_t, link);
-}
-
-/** Define a new transition.
- *
- * @param p	The parser.
- * @param t	Transition with all fields defined.
- */
-static void trans_insert(gsp_t *p, gsp_trans_t *t)
-{
-	unsigned long key[2];
-
-	key[0] = t->old_state;
-	key[1] = t->input;
-
-	hash_table_insert(&p->trans, key, &t->link);
-}
-
-/** Allocate transition structure. */
-static gsp_trans_t *trans_new(void)
-{
-	gsp_trans_t *t;
-
-	t = malloc(sizeof(gsp_trans_t));
-	if (t == NULL) {
-		printf("Memory allocation failed.\n");
-		exit(1);
-	}
-
-	return t;
-}
-
-/*
- * Transition function hash table operations.
- */
-
-static hash_index_t trans_op_hash(unsigned long key[])
-{
-	return (key[0] * 17 + key[1]) % TRANS_TABLE_CHAINS;
-}
-
-static int trans_op_compare(unsigned long key[], hash_count_t keys,
-    link_t *item)
-{
-	gsp_trans_t *t;
-
-	t = hash_table_get_instance(item, gsp_trans_t, link);
-	return ((key[0] == (unsigned long) t->old_state)
-	    && (key[1] == (unsigned long) t->input));
-}
-
-static void trans_op_remove_callback(link_t *item)
-{
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/genarch/stroke.c
===================================================================
--- uspace/srv/hid/kbd/genarch/stroke.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd
- * @{
- */
-/**
- * @file
- * @brief Stroke simulator.
- *
- * When simulating a keyboard using a serial TTY we need to convert the
- * recognized strokes (such as Shift-A) to sequences of key presses and
- * releases (such as 'press Shift, press A, release A, release Shift').
- *
- */
-
-#include <stroke.h>
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-
-/** Correspondence between modifers and the modifier keycodes. */
-static unsigned int mods_keys[][2] = {
-	{ KM_LSHIFT, KC_LSHIFT },
-	{ 0, 0 }
-};
-
-/** Simulate keystroke using sequences of key presses and releases. */
-void stroke_sim(unsigned mod, unsigned key)
-{
-	int i;
-
-	/* Simulate modifier presses. */
-	i = 0;
-	while (mods_keys[i][0] != 0) {
-		if (mod & mods_keys[i][0]) {
-			kbd_push_ev(KEY_PRESS, mods_keys[i][1]);
-		}
-		++i;
-	}
-
-	/* Simulate key press and release. */
-	if (key != 0) {
-		kbd_push_ev(KEY_PRESS, key);
-		kbd_push_ev(KEY_RELEASE, key);
-	}
-
-	/* Simulate modifier releases. */
-	i = 0;
-	while (mods_keys[i][0] != 0) {
-		if (mod & mods_keys[i][0]) {
-			kbd_push_ev(KEY_RELEASE, mods_keys[i][1]);
-		}
-		++i;
-	}
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/kbd/generic/kbd.c
===================================================================
--- uspace/srv/hid/kbd/generic/kbd.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,263 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @addtogroup kbdgen generic
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#include <ipc/services.h>
-#include <ipc/kbd.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ipc/ns.h>
-#include <async.h>
-#include <errno.h>
-#include <adt/fifo.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <devmap.h>
-
-#include <kbd.h>
-#include <kbd_port.h>
-#include <kbd_ctl.h>
-#include <layout.h>
-
-#define NAME       "kbd"
-#define NAMESPACE  "hid_in"
-
-int client_phone = -1;
-
-/** Currently active modifiers. */
-static unsigned mods = KM_NUM_LOCK;
-
-/** Currently pressed lock keys. We track these to tackle autorepeat. */
-static unsigned lock_keys;
-
-bool irc_service = false;
-int irc_phone = -1;
-
-#define NUM_LAYOUTS 3
-
-static layout_op_t *layout[NUM_LAYOUTS] = {
-	&us_qwerty_op,
-	&us_dvorak_op,
-	&cz_op
-};
-
-static int active_layout = 0;
-
-void kbd_push_scancode(int scancode)
-{
-/*	printf("scancode: 0x%x\n", scancode);*/
-	kbd_ctl_parse_scancode(scancode);
-}
-
-void kbd_push_ev(int type, unsigned int key)
-{
-	console_event_t ev;
-	unsigned mod_mask;
-
-	switch (key) {
-	case KC_LCTRL: mod_mask = KM_LCTRL; break;
-	case KC_RCTRL: mod_mask = KM_RCTRL; break;
-	case KC_LSHIFT: mod_mask = KM_LSHIFT; break;
-	case KC_RSHIFT: mod_mask = KM_RSHIFT; break;
-	case KC_LALT: mod_mask = KM_LALT; break;
-	case KC_RALT: mod_mask = KM_RALT; break;
-	default: mod_mask = 0; break;
-	}
-
-	if (mod_mask != 0) {
-		if (type == KEY_PRESS)
-			mods = mods | mod_mask;
-		else
-			mods = mods & ~mod_mask;
-	}
-
-	switch (key) {
-	case KC_CAPS_LOCK: mod_mask = KM_CAPS_LOCK; break;
-	case KC_NUM_LOCK: mod_mask = KM_NUM_LOCK; break;
-	case KC_SCROLL_LOCK: mod_mask = KM_SCROLL_LOCK; break;
-	default: mod_mask = 0; break;
-	}
-
-	if (mod_mask != 0) {
-		if (type == KEY_PRESS) {
-			/*
-			 * Only change lock state on transition from released
-			 * to pressed. This prevents autorepeat from messing
-			 * up the lock state.
-			 */
-			mods = mods ^ (mod_mask & ~lock_keys);
-			lock_keys = lock_keys | mod_mask;
-
-			/* Update keyboard lock indicator lights. */
-			kbd_ctl_set_ind(mods);
-		} else {
-			lock_keys = lock_keys & ~mod_mask;
-		}
-	}
-/*
-	printf("type: %d\n", type);
-	printf("mods: 0x%x\n", mods);
-	printf("keycode: %u\n", key);
-*/
-	if (type == KEY_PRESS && (mods & KM_LCTRL) &&
-		key == KC_F1) {
-		active_layout = 0;
-		layout[active_layout]->reset();
-		return;
-	}
-
-	if (type == KEY_PRESS && (mods & KM_LCTRL) &&
-		key == KC_F2) {
-		active_layout = 1;
-		layout[active_layout]->reset();
-		return;
-	}
-
-	if (type == KEY_PRESS && (mods & KM_LCTRL) &&
-		key == KC_F3) {
-		active_layout = 2;
-		layout[active_layout]->reset();
-		return;
-	}
-
-	ev.type = type;
-	ev.key = key;
-	ev.mods = mods;
-
-	ev.c = layout[active_layout]->parse_ev(&ev);
-
-	async_msg_4(client_phone, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c);
-}
-
-static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			if (client_phone != -1) {
-				async_hangup(client_phone);
-				client_phone = -1;
-			}
-			
-			async_answer_0(callid, EOK);
-			return;
-		case IPC_M_CONNECT_TO_ME:
-			if (client_phone != -1) {
-				retval = ELIMIT;
-				break;
-			}
-			client_phone = IPC_GET_ARG5(call);
-			retval = 0;
-			break;
-		case KBD_YIELD:
-			kbd_port_yield();
-			retval = 0;
-			break;
-		case KBD_RECLAIM:
-			kbd_port_reclaim();
-			retval = 0;
-			break;
-		default:
-			retval = EINVAL;
-		}
-		async_answer_0(callid, retval);
-	}	
-}
-
-
-int main(int argc, char **argv)
-{
-	printf("%s: HelenOS Keyboard service\n", NAME);
-	
-	sysarg_t fhc;
-	sysarg_t obio;
-	
-	if (((sysinfo_get_value("kbd.cir.fhc", &fhc) == EOK) && (fhc))
-	    || ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio)))
-		irc_service = true;
-	
-	if (irc_service) {
-		while (irc_phone < 0)
-			irc_phone = service_connect_blocking(SERVICE_IRC, 0, 0);
-	}
-	
-	/* Initialize port driver. */
-	if (kbd_port_init() != 0)
-		return -1;
-
-	/* Initialize controller driver. */
-	if (kbd_ctl_init() != 0)
-		return -1;
-
-	/* Initialize (reset) layout. */
-	layout[active_layout]->reset();
-	
-	/* Register driver */
-	int rc = devmap_driver_register(NAME, client_connection);
-	if (rc < 0) {
-		printf("%s: Unable to register driver (%d)\n", NAME, rc);
-		return -1;
-	}
-	
-	char kbd[DEVMAP_NAME_MAXLEN + 1];
-	snprintf(kbd, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);
-	
-	devmap_handle_t devmap_handle;
-	if (devmap_device_register(kbd, &devmap_handle) != EOK) {
-		printf("%s: Unable to register device %s\n", NAME, kbd);
-		return -1;
-	}
-
-	printf(NAME ": Accepting connections\n");
-	async_manager();
-
-	/* Not reached. */
-	return 0;
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/include/gsp.h
===================================================================
--- uspace/srv/hid/kbd/include/gsp.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen generic
- * @brief	Generic scancode parser.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_GSP_H_
-#define KBD_GSP_H_
-
-#include <adt/hash_table.h>
-
-enum {
-	GSP_END		= -1,	/**< Terminates a sequence. */
-	GSP_DEFAULT	= -2	/**< Wildcard, catches unhandled cases. */
-};
-
-/** Scancode parser description */
-typedef struct {
-	/** Transition table, (state, input) -> (state, output) */
-	hash_table_t trans;
-
-	/** Number of states */
-	int states;
-} gsp_t;
-
-/** Scancode parser transition. */
-typedef struct {
-	link_t link;		/**< Link to hash table in @c gsp_t */ 
-
-	/* Preconditions */
-
-	int old_state;		/**< State before transition */
-	int input;		/**< Input symbol (scancode) */
-
-	/* Effects */
-
-	int new_state;		/**< State after transition */
-
-	/* Output emitted during transition */
-
-	unsigned out_mods;	/**< Modifier to emit */
-	unsigned out_key;	/**< Keycode to emit */
-} gsp_trans_t;
-
-extern void gsp_init(gsp_t *);
-extern int gsp_insert_defs(gsp_t *, const int *);
-extern int gsp_insert_seq(gsp_t *, const int *, unsigned, unsigned);
-extern int gsp_step(gsp_t *, int, int, unsigned *, unsigned *);
-
-#endif
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/include/kbd.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen generic
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_KBD_H_
-#define KBD_KBD_H_
-
-#include <bool.h>
-
-extern bool irc_service;
-extern int irc_phone;
-
-extern void kbd_push_scancode(int);
-extern void kbd_push_ev(int, unsigned int);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/hid/kbd/include/kbd_ctl.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd_ctl.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,49 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen generic
- * @brief	HelenOS generic uspace keyboard handler.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_CTL_H_
-#define KBD_CTL_H_
-
-extern void kbd_ctl_parse_scancode(int);
-extern int kbd_ctl_init(void);
-extern void kbd_ctl_set_ind(unsigned);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: uspace/srv/hid/kbd/include/kbd_port.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd_port.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen generic
- * @brief	HelenOS generic uspace keyboard handler.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_PORT_H_
-#define KBD_PORT_H_
-
-#include <sys/types.h>
-
-extern int kbd_port_init(void);
-extern void kbd_port_yield(void);
-extern void kbd_port_reclaim(void);
-extern void kbd_port_write(uint8_t);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: uspace/srv/hid/kbd/include/layout.h
===================================================================
--- uspace/srv/hid/kbd/include/layout.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen generic
- * @brief HelenOS generic uspace keyboard handler.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_LAYOUT_H_
-#define KBD_LAYOUT_H_
-
-#include <sys/types.h>
-#include <io/console.h>
-
-typedef struct {
-	void (*reset)(void);
-	wchar_t (*parse_ev)(console_event_t *);
-} layout_op_t;
-
-extern layout_op_t us_qwerty_op;
-extern layout_op_t us_dvorak_op;
-extern layout_op_t cz_op;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/hid/kbd/include/stroke.h
===================================================================
--- uspace/srv/hid/kbd/include/stroke.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen generic
- * @brief	Generic scancode parser.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#ifndef KBD_STROKE_H_
-#define KBD_STROKE_H_
-
-extern void stroke_sim(unsigned, unsigned);
-
-#endif
-
-/**
- * @}
- */ 
-
Index: uspace/srv/hid/kbd/include/sun.h
===================================================================
--- uspace/srv/hid/kbd/include/sun.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2009 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbdgen generic
- * @brief Sun keyboard virtual port driver.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_SUN_H_
-#define KBD_SUN_H_
-
-extern int ns16550_port_init(void);
-extern int z8530_port_init(void);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/hid/kbd/layout/cz.c
===================================================================
--- uspace/srv/hid/kbd/layout/cz.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,408 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd
- * @brief Czech QWERTZ layout.
- * @{
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <bool.h>
-#include <layout.h>
-
-static void layout_reset(void);
-static wchar_t layout_parse_ev(console_event_t *ev);
-
-enum m_state {
-	ms_start,
-	ms_hacek,
-	ms_carka
-};
-
-static enum m_state mstate;
-
-layout_op_t cz_op = {
-	layout_reset,
-	layout_parse_ev
-};
-
-static wchar_t map_lcase[] = {
-	[KC_Q] = 'q',
-	[KC_W] = 'w',
-	[KC_E] = 'e',
-	[KC_R] = 'r',
-	[KC_T] = 't',
-	[KC_Y] = 'z',
-	[KC_U] = 'u',
-	[KC_I] = 'i',
-	[KC_O] = 'o',
-	[KC_P] = 'p',
-
-	[KC_A] = 'a',
-	[KC_S] = 's',
-	[KC_D] = 'd',
-	[KC_F] = 'f',
-	[KC_G] = 'g',
-	[KC_H] = 'h',
-	[KC_J] = 'j',
-	[KC_K] = 'k',
-	[KC_L] = 'l',
-
-	[KC_Z] = 'y',
-	[KC_X] = 'x',
-	[KC_C] = 'c',
-	[KC_V] = 'v',
-	[KC_B] = 'b',
-	[KC_N] = 'n',
-	[KC_M] = 'm',
-};
-
-static wchar_t map_ucase[] = {
-	[KC_Q] = 'Q',
-	[KC_W] = 'W',
-	[KC_E] = 'E',
-	[KC_R] = 'R',
-	[KC_T] = 'T',
-	[KC_Y] = 'Z',
-	[KC_U] = 'U',
-	[KC_I] = 'I',
-	[KC_O] = 'O',
-	[KC_P] = 'P',
-
-	[KC_A] = 'A',
-	[KC_S] = 'S',
-	[KC_D] = 'D',
-	[KC_F] = 'F',
-	[KC_G] = 'G',
-	[KC_H] = 'H',
-	[KC_J] = 'J',
-	[KC_K] = 'K',
-	[KC_L] = 'L',
-
-	[KC_Z] = 'Y',
-	[KC_X] = 'X',
-	[KC_C] = 'C',
-	[KC_V] = 'V',
-	[KC_B] = 'B',
-	[KC_N] = 'N',
-	[KC_M] = 'M',
-};
-
-static wchar_t map_not_shifted[] = {
-	[KC_BACKTICK] = ';',
-
-	[KC_1] = '+',
-
-	[KC_MINUS] = '=',
-
-	[KC_RBRACKET] = ')',
-
-	[KC_QUOTE] = L'§',
-
-	[KC_COMMA] = ',',
-	[KC_PERIOD] = '.',
-	[KC_SLASH] = '-',
-};
-
-static wchar_t map_shifted[] = {
-	[KC_1] = '1',
-	[KC_2] = '2',
-	[KC_3] = '3',
-	[KC_4] = '4',
-	[KC_5] = '5',
-	[KC_6] = '6',
-	[KC_7] = '7',
-	[KC_8] = '8',
-	[KC_9] = '9',
-	[KC_0] = '0',
-
-	[KC_MINUS] = '%',
-
-	[KC_LBRACKET] = '/',
-	[KC_RBRACKET] = '(',
-
-	[KC_SEMICOLON] = '"',
-	[KC_QUOTE] = '!',
-	[KC_BACKSLASH] = '\'',
-
-	[KC_COMMA] = '?',
-	[KC_PERIOD] = ':',
-	[KC_SLASH] = '_',
-};
-
-static wchar_t map_ns_nocaps[] = {
-	[KC_2] = L'ě',
-	[KC_3] = L'š',
-	[KC_4] = L'č',
-	[KC_5] = L'ř',
-	[KC_6] = L'ž',
-	[KC_7] = L'ý',
-	[KC_8] = L'á',
-	[KC_9] = L'í',
-	[KC_0] = L'é',
-
-	[KC_LBRACKET] = L'ú',
-	[KC_SEMICOLON] = L'ů'
-};
-
-static wchar_t map_ns_caps[] = {
-	[KC_2] = L'Ě',
-	[KC_3] = L'Š',
-	[KC_4] = L'Č',
-	[KC_5] = L'Ř',
-	[KC_6] = L'Ž',
-	[KC_7] = L'Ý',
-	[KC_8] = L'Á',
-	[KC_9] = L'Í',
-	[KC_0] = L'É',
-
-	[KC_LBRACKET] = L'Ú',
-	[KC_SEMICOLON] = L'Ů'
-};
-
-static wchar_t map_neutral[] = {
-	[KC_BACKSPACE] = '\b',
-	[KC_TAB] = '\t',
-	[KC_ENTER] = '\n',
-	[KC_SPACE] = ' ',
-
-	[KC_NSLASH] = '/',
-	[KC_NTIMES] = '*',
-	[KC_NMINUS] = '-',
-	[KC_NPLUS] = '+',
-	[KC_NENTER] = '\n'
-};
-
-static wchar_t map_numeric[] = {
-	[KC_N7] = '7',
-	[KC_N8] = '8',
-	[KC_N9] = '9',
-	[KC_N4] = '4',
-	[KC_N5] = '5',
-	[KC_N6] = '6',
-	[KC_N1] = '1',
-	[KC_N2] = '2',
-	[KC_N3] = '3',
-
-	[KC_N0] = '0',
-	[KC_NPERIOD] = '.'
-};
-
-static wchar_t map_hacek_lcase[] = {
-	[KC_E] = L'ě',
-	[KC_R] = L'ř',
-	[KC_T] = L'ť',
-	[KC_Y] = L'ž',
-	[KC_U] = L'ů',
-
-	[KC_S] = L'š',
-	[KC_D] = L'ď',
-
-	[KC_C] = L'č',
-	[KC_N] = L'ň'
-};
-
-static wchar_t map_hacek_ucase[] = {
-	[KC_E] = L'Ě',
-	[KC_R] = L'Ř',
-	[KC_T] = L'Ť',
-	[KC_Y] = L'Ž',
-	[KC_U] = L'Ů',
-
-	[KC_S] = L'Š',
-	[KC_D] = L'Ď',
-
-	[KC_C] = L'Č',
-	[KC_N] = L'Ň'
-};
-
-static wchar_t map_carka_lcase[] = {
-	[KC_E] = L'é',
-	[KC_U] = L'ú',
-	[KC_I] = L'í',
-	[KC_O] = L'ó',
-
-	[KC_A] = L'á',
-
-	[KC_Z] = L'ý',
-};
-
-static wchar_t map_carka_ucase[] = {
-	[KC_E] = L'É',
-	[KC_U] = L'Ú',
-	[KC_I] = L'Í',
-	[KC_O] = L'Ó',
-
-	[KC_A] = L'Á',
-
-	[KC_Z] = L'Ý',
-};
-
-static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
-{
-	if (key >= map_length)
-		return 0;
-	return map[key];
-}
-
-static wchar_t parse_ms_hacek(console_event_t *ev)
-{
-	wchar_t c;
-
-	mstate = ms_start;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_hacek_ucase, sizeof(map_hacek_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_hacek_lcase, sizeof(map_hacek_lcase) / sizeof(wchar_t));
-
-	return c;
-}
-
-static wchar_t parse_ms_carka(console_event_t *ev)
-{
-	wchar_t c;
-
-	mstate = ms_start;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_carka_ucase, sizeof(map_carka_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_carka_lcase, sizeof(map_carka_lcase) / sizeof(wchar_t));
-
-	return c;
-}
-
-static wchar_t parse_ms_start(console_event_t *ev)
-{
-	wchar_t c;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	if (ev->key == KC_EQUALS) {
-		if ((ev->mods & KM_SHIFT) != 0)
-			mstate = ms_hacek;
-		else
-			mstate = ms_carka;
-
-		return 0;
-	}
-
-	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_SHIFT) == 0) {
-		if ((ev->mods & KM_CAPS_LOCK) != 0)
-			c = translate(ev->key, map_ns_caps, sizeof(map_ns_caps) / sizeof(wchar_t));
-		else
-			c = translate(ev->key, map_ns_nocaps, sizeof(map_ns_nocaps) / sizeof(wchar_t));
-
-		if (c != 0)
-			return c;
-	}	
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_SHIFT) != 0)
-		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_NUM_LOCK) != 0)
-		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
-	else
-		c = 0;
-
-	return c;
-}
-
-static bool key_is_mod(unsigned key)
-{
-	switch (key) {
-	case KC_LSHIFT:
-	case KC_RSHIFT:
-	case KC_LALT:
-	case KC_RALT:
-	case KC_LCTRL:
-	case KC_RCTRL:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static void layout_reset(void)
-{
-	mstate = ms_start;
-}
-
-static wchar_t layout_parse_ev(console_event_t *ev)
-{
-	if (ev->type != KEY_PRESS)
-		return 0;
-	
-	if (key_is_mod(ev->key))
-		return 0;
-	
-	switch (mstate) {
-	case ms_start:
-		return parse_ms_start(ev);
-	case ms_hacek:
-		return parse_ms_hacek(ev);
-	case ms_carka:
-		return parse_ms_carka(ev);
-	}
-	
-	return 0;
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/kbd/layout/us_dvorak.c
===================================================================
--- uspace/srv/hid/kbd/layout/us_dvorak.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,250 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd
- * @brief US Dvorak Simplified Keyboard layout.
- * @{
- */
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <layout.h>
-
-static void layout_reset(void);
-static wchar_t layout_parse_ev(console_event_t *ev);
-
-layout_op_t us_dvorak_op = {
-	layout_reset,
-	layout_parse_ev
-};
-
-static wchar_t map_lcase[] = {
-	[KC_R] = 'p',
-	[KC_T] = 'y',
-	[KC_Y] = 'f',
-	[KC_U] = 'g',
-	[KC_I] = 'c',
-	[KC_O] = 'r',
-	[KC_P] = 'l',
-
-	[KC_A] = 'a',
-	[KC_S] = 'o',
-	[KC_D] = 'e',
-	[KC_F] = 'u',
-	[KC_G] = 'i',
-	[KC_H] = 'd',
-	[KC_J] = 'h',
-	[KC_K] = 't',
-	[KC_L] = 'n',
-
-	[KC_SEMICOLON] = 's',
-
-	[KC_X] = 'q',
-	[KC_C] = 'j',
-	[KC_V] = 'k',
-	[KC_B] = 'x',
-	[KC_N] = 'b',
-	[KC_M] = 'm',
-
-	[KC_COMMA] = 'w',
-	[KC_PERIOD] = 'v',
-	[KC_SLASH] = 'z',
-};
-
-static wchar_t map_ucase[] = {
-	[KC_R] = 'P',
-	[KC_T] = 'Y',
-	[KC_Y] = 'F',
-	[KC_U] = 'G',
-	[KC_I] = 'C',
-	[KC_O] = 'R',
-	[KC_P] = 'L',
-
-	[KC_A] = 'A',
-	[KC_S] = 'O',
-	[KC_D] = 'E',
-	[KC_F] = 'U',
-	[KC_G] = 'I',
-	[KC_H] = 'D',
-	[KC_J] = 'H',
-	[KC_K] = 'T',
-	[KC_L] = 'N',
-
-	[KC_SEMICOLON] = 'S',
-
-	[KC_X] = 'Q',
-	[KC_C] = 'J',
-	[KC_V] = 'K',
-	[KC_B] = 'X',
-	[KC_N] = 'B',
-	[KC_M] = 'M',
-
-	[KC_COMMA] = 'W',
-	[KC_PERIOD] = 'V',
-	[KC_SLASH] = 'Z',
-};
-
-static wchar_t map_not_shifted[] = {
-	[KC_BACKTICK] = '`',
-
-	[KC_1] = '1',
-	[KC_2] = '2',
-	[KC_3] = '3',
-	[KC_4] = '4',
-	[KC_5] = '5',
-	[KC_6] = '6',
-	[KC_7] = '7',
-	[KC_8] = '8',
-	[KC_9] = '9',
-	[KC_0] = '0',
-
-	[KC_MINUS] = '[',
-	[KC_EQUALS] = ']',
-
-	[KC_Q] = '\'',
-	[KC_W] = ',',
-	[KC_E] = '.',
-
-	[KC_LBRACKET] = '/',
-	[KC_RBRACKET] = '=',
-
-	[KC_QUOTE] = '-',
-	[KC_BACKSLASH] = '\\',
-
-	[KC_Z] = ';',
-};
-
-static wchar_t map_shifted[] = {
-	[KC_BACKTICK] = '~',
-
-	[KC_1] = '!',
-	[KC_2] = '@',
-	[KC_3] = '#',
-	[KC_4] = '$',
-	[KC_5] = '%',
-	[KC_6] = '^',
-	[KC_7] = '&',
-	[KC_8] = '*',
-	[KC_9] = '(',
-	[KC_0] = ')',
-
-	[KC_MINUS] = '{',
-	[KC_EQUALS] = '}',
-
-	[KC_Q] = '"',
-	[KC_W] = '<',
-	[KC_E] = '>',
-
-	[KC_LBRACKET] = '?',
-	[KC_RBRACKET] = '+',
-
-	[KC_QUOTE] = '_',
-	[KC_BACKSLASH] = '|',
-
-	[KC_Z] = ':',
-};
-
-static wchar_t map_neutral[] = {
-	[KC_BACKSPACE] = '\b',
-	[KC_TAB] = '\t',
-	[KC_ENTER] = '\n',
-	[KC_SPACE] = ' ',
-
-	[KC_NSLASH] = '/',
-	[KC_NTIMES] = '*',
-	[KC_NMINUS] = '-',
-	[KC_NPLUS] = '+',
-	[KC_NENTER] = '\n'
-};
-
-static wchar_t map_numeric[] = {
-	[KC_N7] = '7',
-	[KC_N8] = '8',
-	[KC_N9] = '9',
-	[KC_N4] = '4',
-	[KC_N5] = '5',
-	[KC_N6] = '6',
-	[KC_N1] = '1',
-	[KC_N2] = '2',
-	[KC_N3] = '3',
-
-	[KC_N0] = '0',
-	[KC_NPERIOD] = '.'
-};
-
-static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
-{
-	if (key >= map_length)
-		return 0;
-	return map[key];
-}
-
-static void layout_reset(void)
-{
-}
-
-static wchar_t layout_parse_ev(console_event_t *ev)
-{
-	wchar_t c;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
-	if (c != 0)
-		return c;
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_SHIFT) != 0)
-		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_NUM_LOCK) != 0)
-		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
-	else
-		c = 0;
-
-	return c;
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/kbd/layout/us_qwerty.c
===================================================================
--- uspace/srv/hid/kbd/layout/us_qwerty.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,244 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd
- * @brief	US QWERTY layout.
- * @{
- */ 
-
-#include <kbd.h>
-#include <io/console.h>
-#include <io/keycode.h>
-#include <layout.h>
-
-static void layout_reset(void);
-static wchar_t layout_parse_ev(console_event_t *ev);
-
-layout_op_t us_qwerty_op = {
-	layout_reset,
-	layout_parse_ev
-};
-
-static wchar_t map_lcase[] = {
-	[KC_Q] = 'q',
-	[KC_W] = 'w',
-	[KC_E] = 'e',
-	[KC_R] = 'r',
-	[KC_T] = 't',
-	[KC_Y] = 'y',
-	[KC_U] = 'u',
-	[KC_I] = 'i',
-	[KC_O] = 'o',
-	[KC_P] = 'p',
-
-	[KC_A] = 'a',
-	[KC_S] = 's',
-	[KC_D] = 'd',
-	[KC_F] = 'f',
-	[KC_G] = 'g',
-	[KC_H] = 'h',
-	[KC_J] = 'j',
-	[KC_K] = 'k',
-	[KC_L] = 'l',
-
-	[KC_Z] = 'z',
-	[KC_X] = 'x',
-	[KC_C] = 'c',
-	[KC_V] = 'v',
-	[KC_B] = 'b',
-	[KC_N] = 'n',
-	[KC_M] = 'm',
-};
-
-static wchar_t map_ucase[] = {
-	[KC_Q] = 'Q',
-	[KC_W] = 'W',
-	[KC_E] = 'E',
-	[KC_R] = 'R',
-	[KC_T] = 'T',
-	[KC_Y] = 'Y',
-	[KC_U] = 'U',
-	[KC_I] = 'I',
-	[KC_O] = 'O',
-	[KC_P] = 'P',
-
-	[KC_A] = 'A',
-	[KC_S] = 'S',
-	[KC_D] = 'D',
-	[KC_F] = 'F',
-	[KC_G] = 'G',
-	[KC_H] = 'H',
-	[KC_J] = 'J',
-	[KC_K] = 'K',
-	[KC_L] = 'L',
-
-	[KC_Z] = 'Z',
-	[KC_X] = 'X',
-	[KC_C] = 'C',
-	[KC_V] = 'V',
-	[KC_B] = 'B',
-	[KC_N] = 'N',
-	[KC_M] = 'M',
-};
-
-static wchar_t map_not_shifted[] = {
-	[KC_BACKTICK] = '`',
-
-	[KC_1] = '1',
-	[KC_2] = '2',
-	[KC_3] = '3',
-	[KC_4] = '4',
-	[KC_5] = '5',
-	[KC_6] = '6',
-	[KC_7] = '7',
-	[KC_8] = '8',
-	[KC_9] = '9',
-	[KC_0] = '0',
-
-	[KC_MINUS] = '-',
-	[KC_EQUALS] = '=',
-
-	[KC_LBRACKET] = '[',
-	[KC_RBRACKET] = ']',
-
-	[KC_SEMICOLON] = ';',
-	[KC_QUOTE] = '\'',
-	[KC_BACKSLASH] = '\\',
-
-	[KC_COMMA] = ',',
-	[KC_PERIOD] = '.',
-	[KC_SLASH] = '/',
-};
-
-static wchar_t map_shifted[] = {
-	[KC_BACKTICK] = '~',
-
-	[KC_1] = '!',
-	[KC_2] = '@',
-	[KC_3] = '#',
-	[KC_4] = '$',
-	[KC_5] = '%',
-	[KC_6] = '^',
-	[KC_7] = '&',
-	[KC_8] = '*',
-	[KC_9] = '(',
-	[KC_0] = ')',
-
-	[KC_MINUS] = '_',
-	[KC_EQUALS] = '+',
-
-	[KC_LBRACKET] = '{',
-	[KC_RBRACKET] = '}',
-
-	[KC_SEMICOLON] = ':',
-	[KC_QUOTE] = '"',
-	[KC_BACKSLASH] = '|',
-
-	[KC_COMMA] = '<',
-	[KC_PERIOD] = '>',
-	[KC_SLASH] = '?',
-};
-
-static wchar_t map_neutral[] = {
-	[KC_BACKSPACE] = '\b',
-	[KC_TAB] = '\t',
-	[KC_ENTER] = '\n',
-	[KC_SPACE] = ' ',
-
-	[KC_NSLASH] = '/',
-	[KC_NTIMES] = '*',
-	[KC_NMINUS] = '-',
-	[KC_NPLUS] = '+',
-	[KC_NENTER] = '\n'
-};
-
-static wchar_t map_numeric[] = {
-	[KC_N7] = '7',
-	[KC_N8] = '8',
-	[KC_N9] = '9',
-	[KC_N4] = '4',
-	[KC_N5] = '5',
-	[KC_N6] = '6',
-	[KC_N1] = '1',
-	[KC_N2] = '2',
-	[KC_N3] = '3',
-
-	[KC_N0] = '0',
-	[KC_NPERIOD] = '.'
-};
-
-static wchar_t translate(unsigned int key, wchar_t *map, size_t map_length)
-{
-	if (key >= map_length)
-		return 0;
-	return map[key];
-}
-
-static void layout_reset(void)
-{
-}
-
-static wchar_t layout_parse_ev(console_event_t *ev)
-{
-	wchar_t c;
-
-	/* Produce no characters when Ctrl or Alt is pressed. */
-	if ((ev->mods & (KM_CTRL | KM_ALT)) != 0)
-		return 0;
-
-	c = translate(ev->key, map_neutral, sizeof(map_neutral) / sizeof(wchar_t));
-	if (c != 0)
-		return c;
-
-	if (((ev->mods & KM_SHIFT) != 0) ^ ((ev->mods & KM_CAPS_LOCK) != 0))
-		c = translate(ev->key, map_ucase, sizeof(map_ucase) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_lcase, sizeof(map_lcase) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_SHIFT) != 0)
-		c = translate(ev->key, map_shifted, sizeof(map_shifted) / sizeof(wchar_t));
-	else
-		c = translate(ev->key, map_not_shifted, sizeof(map_not_shifted) / sizeof(wchar_t));
-
-	if (c != 0)
-		return c;
-
-	if ((ev->mods & KM_NUM_LOCK) != 0)
-		c = translate(ev->key, map_numeric, sizeof(map_numeric) / sizeof(wchar_t));
-	else
-		c = 0;
-
-	return c;
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/port/adb.c
===================================================================
--- uspace/srv/hid/kbd/port/adb.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,132 +1,0 @@
-/*
- * Copyright (c) 2010 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup kbd
- * @{
- */ 
-/** @file
- * @brief ADB keyboard port driver.
- */
-
-#include <ipc/adb.h>
-#include <async.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <vfs/vfs.h>
-#include <fcntl.h>
-#include <errno.h>
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall);
-static void adb_kbd_reg0_data(uint16_t data);
-
-static int dev_phone;
-
-#define NAME "kbd"
-
-int kbd_port_init(void)
-{
-	const char *input = "/dev/adb/kbd";
-	int input_fd;
-
-	printf(NAME ": open %s\n", input);
-
-	input_fd = open(input, O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": Failed opening %s (%d)\n", input, input_fd);
-		return false;
-	}
-
-	dev_phone = fd_phone(input_fd);
-	if (dev_phone < 0) {
-		printf(NAME ": Failed to connect to device\n");
-		return false;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(dev_phone, 0, 0, 0, kbd_port_events) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return false;
-	}
-
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	/*async_msg_1(dev_phone, CHAR_WRITE_BYTE, data);*/
-}
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case ADB_REG_NOTIF:
-			adb_kbd_reg0_data(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-static void adb_kbd_reg0_data(uint16_t data)
-{
-	uint8_t b0, b1;
-
-	b0 = (data >> 8) & 0xff;
-	b1 = data & 0xff;
-
-	if (b0 != 0xff)
-		kbd_push_scancode(b0);
-	if (b1 != 0xff)
-		kbd_push_scancode(b1);
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/kbd/port/chardev.c
===================================================================
--- uspace/srv/hid/kbd/port/chardev.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,140 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup kbd
- * @{
- */ 
-/** @file
- * @brief Chardev keyboard port driver.
- */
-
-#include <ipc/char.h>
-#include <async.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <vfs/vfs.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall);
-
-static int dev_phone;
-
-#define NAME "kbd"
-
-/** List of devices to try connecting to. */
-static const char *in_devs[] = {
-	"/dev/char/ps2a",
-	"/dev/char/s3c24ser"
-};
-
-static const int num_devs = sizeof(in_devs) / sizeof(in_devs[0]);
-
-int kbd_port_init(void)
-{
-	int input_fd;
-	int i;
-
-	input_fd = -1;
-	for (i = 0; i < num_devs; i++) {
-		struct stat s;
-
-		if (stat(in_devs[i], &s) == EOK)
-			break;
-	}
-
-	if (i >= num_devs) {
-		printf(NAME ": Could not find any suitable input device.\n");
-		return -1;
-	}
-
-	input_fd = open(in_devs[i], O_RDONLY);
-	if (input_fd < 0) {
-		printf(NAME ": failed opening device %s (%d).\n", in_devs[i],
-		    input_fd);
-		return -1;
-	}
-
-	dev_phone = fd_phone(input_fd);
-	if (dev_phone < 0) {
-		printf(NAME ": Failed connecting to device\n");
-		return -1;
-	}
-
-	/* NB: The callback connection is slotted for removal */
-	if (async_connect_to_me(dev_phone, 0, 0, 0, kbd_port_events) != 0) {
-		printf(NAME ": Failed to create callback from device\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	async_msg_1(dev_phone, CHAR_WRITE_BYTE, data);
-}
-
-static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/* Ignore parameters, the connection is already opened */
-	while (true) {
-
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		int retval;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			/* TODO: Handle hangup */
-			return;
-		case CHAR_NOTIF_BYTE:
-			kbd_push_scancode(IPC_GET_ARG1(call));
-			break;
-		default:
-			retval = ENOENT;
-		}
-		async_answer_0(callid, retval);
-	}
-}
-
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/port/dummy.c
===================================================================
--- uspace/srv/hid/kbd/port/dummy.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @brief	Dummy keyboard port driver.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#include <kbd_port.h>
-#include <kbd.h>
-
-int kbd_port_init(void)
-{
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: uspace/srv/hid/kbd/port/gxemul.c
===================================================================
--- uspace/srv/hid/kbd/port/gxemul.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,107 +1,0 @@
-/*
- * Copyright (c) 2007 Michal Kebrt
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @{
- * @ingroup  kbd
- */ 
-/** @file
- * @brief	GXEmul keyboard port driver.
- */
-
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <ddi.h>
-#include <errno.h>
-
-static irq_cmd_t gxemul_cmds[] = {
-	{ 
-		.cmd = CMD_PIO_READ_8, 
-		.addr = (void *) 0, 	/* will be patched in run-time */
-		.dstarg = 2,
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-static irq_code_t gxemul_kbd = {
-	sizeof(gxemul_cmds) / sizeof(irq_cmd_t),
-	gxemul_cmds
-};
-
-static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-/** Initializes keyboard handler. */
-int kbd_port_init(void)
-{
-	sysarg_t addr;
-	if (sysinfo_get_value("kbd.address.virtual", &addr) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	async_set_interrupt_received(gxemul_irq_handler);
-	gxemul_cmds[0].addr = (void *) addr;
-	register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** Process data sent when a key is pressed.
- *  
- *  @param keybuffer Buffer of pressed keys.
- *  @param call      IPC call.
- *
- *  @return Always 1.
- */
-static void gxemul_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-
-	kbd_push_scancode(scan_code);
-}
-
-/** @}
- */
Index: uspace/srv/hid/kbd/port/msim.c
===================================================================
--- uspace/srv/hid/kbd/port/msim.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,100 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Msim keyboard port driver.
- */
-
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <ddi.h>
-#include <errno.h>
-
-irq_cmd_t msim_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-	
-};
-
-irq_code_t msim_kbd = {
-	sizeof(msim_cmds) / sizeof(irq_cmd_t),
-	msim_cmds
-};
-
-static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-int kbd_port_init(void)
-{
-	sysarg_t vaddr;
-	if (sysinfo_get_value("kbd.address.virtual", &vaddr) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	msim_cmds[0].addr = (void *) vaddr;
-	async_set_interrupt_received(msim_irq_handler);
-	register_irq(inr, device_assign_devno(), 0, &msim_kbd);
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
-}
-
-/** @}
-*/
Index: uspace/srv/hid/kbd/port/niagara.c
===================================================================
--- uspace/srv/hid/kbd/port/niagara.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,152 +1,0 @@
-/*
- * Copyright (c) 2008 Pavel Rimsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- * @brief	Niagara console keyboard port driver.
- */
-
-#include <as.h>
-#include <ddi.h>
-#include <async.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <thread.h>
-#include <bool.h>
-#include <errno.h>
-
-#define POLL_INTERVAL  10000
-
-/**
- * Virtual address mapped to the buffer shared with the kernel counterpart.
- */
-static uintptr_t input_buffer_addr;
-
-/*
- * Kernel counterpart of the driver pushes characters (it has read) here.
- * Keep in sync with the definition from
- * kernel/arch/sparc64/src/drivers/niagara.c.
- */
-#define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
-
-typedef volatile struct {
-	uint64_t write_ptr;
-	uint64_t read_ptr;
-	char data[INPUT_BUFFER_SIZE];
-}
-	__attribute__ ((packed))
-	__attribute__ ((aligned(PAGE_SIZE)))
-	*input_buffer_t;
-
-/* virtual address of the shared buffer */
-input_buffer_t input_buffer;
-
-static volatile bool polling_disabled = false;
-static void niagara_thread_impl(void *arg);
-
-/**
- * Initializes the Niagara driver.
- * Maps the shared buffer and creates the polling thread. 
- */
-int kbd_port_init(void)
-{
-	sysarg_t paddr;
-	if (sysinfo_get_value("niagara.inbuf.address", &paddr) != EOK)
-		return -1;
-	
-	input_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
-	int rc = physmem_map((void *) paddr, (void *) input_buffer_addr,
-	    1, AS_AREA_READ | AS_AREA_WRITE);
-	
-	if (rc != 0) {
-		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
-		    rc);
-		return rc;
-	}
-	
-	input_buffer = (input_buffer_t) input_buffer_addr;
-	
-	thread_id_t tid;
-	rc = thread_create(niagara_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0)
-		return rc;
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-void kbd_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/**
- * Called regularly by the polling thread. Reads codes of all the
- * pressed keys from the buffer. 
- */
-static void niagara_key_pressed(void)
-{
-	char c;
-	
-	while (input_buffer->read_ptr != input_buffer->write_ptr) {
-		c = input_buffer->data[input_buffer->read_ptr];
-		input_buffer->read_ptr =
-			((input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
-		kbd_push_scancode(c);
-	}
-}
-
-/**
- * Thread to poll SGCN for keypresses.
- */
-static void niagara_thread_impl(void *arg)
-{
-	(void) arg;
-
-	while (1) {
-		if (polling_disabled == false)
-			niagara_key_pressed();
-		usleep(POLL_INTERVAL);
-	}
-}
-/** @}
- */
Index: uspace/srv/hid/kbd/port/ns16550.c
===================================================================
--- uspace/srv/hid/kbd/port/ns16550.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,129 +1,0 @@
-/*
- * Copyright (c) 2006 Josef Cejka
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief NS16550 port driver.
- */
-
-#include <ipc/irc.h>
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <ddi.h>
-#include <errno.h>
-
-/* NS16550 registers */
-#define RBR_REG  0  /** Receiver Buffer Register. */
-#define IER_REG  1  /** Interrupt Enable Register. */
-#define IIR_REG  2  /** Interrupt Ident Register (read). */
-#define FCR_REG  2  /** FIFO control register (write). */
-#define LCR_REG  3  /** Line Control register. */
-#define MCR_REG  4  /** Modem Control Register. */
-#define LSR_REG  5  /** Line Status Register. */
-
-#define LSR_DATA_READY  0x01
-
-static irq_cmd_t ns16550_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = LSR_DATA_READY,
-		.srcarg = 1,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-irq_code_t ns16550_kbd = {
-	sizeof(ns16550_cmds) / sizeof(irq_cmd_t),
-	ns16550_cmds
-};
-
-static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-static uintptr_t ns16550_physical;
-static uintptr_t ns16550_kernel; 
-
-int ns16550_port_init(void)
-{
-	void *vaddr;
-
-	if (sysinfo_get_value("kbd.address.physical", &ns16550_physical) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("kbd.address.kernel", &ns16550_kernel) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG);
-	ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG);
-	
-	async_set_interrupt_received(ns16550_irq_handler);
-	register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
-	
-	return pio_enable((void *) ns16550_physical, 8, &vaddr);
-}
-
-static void ns16550_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
-	
-	if (irc_service)
-		async_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
-		    IPC_GET_IMETHOD(*call));
-}
-
-/**
- * @}
- */
Index: uspace/srv/hid/kbd/port/pl050.c
===================================================================
--- uspace/srv/hid/kbd/port/pl050.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,130 +1,0 @@
-/*
- * Copyright (c) 2009 Vineeth Pillai
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup kbd
- * @{
- */ 
-/** @file
- * @brief pl050 port driver.
- */
-
-#include <ddi.h>
-#include <libarch/ddi.h>
-#include <async.h>
-#include <unistd.h>
-#include <sysinfo.h>
-#include <kbd_port.h>
-#include <kbd.h>
-#include <ddi.h>
-#include <stdio.h>
-#include <errno.h>
-
-#define PL050_STAT_RXFULL  (1 << 4)
-
-static irq_cmd_t pl050_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = PL050_STAT_RXFULL,
-		.srcarg = 1,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = NULL,  /* Will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-
-static irq_code_t pl050_kbd = {
-	sizeof(pl050_cmds) / sizeof(irq_cmd_t),
-	pl050_cmds
-};
-
-static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-int kbd_port_init(void)
-{
-	sysarg_t addr;
-	if (sysinfo_get_value("kbd.address.status", &addr) != EOK)
-		return -1;
-	
-	pl050_kbd.cmds[0].addr = (void *) addr;
-	
-	if (sysinfo_get_value("kbd.address.data", &addr) != EOK)
-		return -1;
-	
-	pl050_kbd.cmds[3].addr = (void *) addr;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	async_set_interrupt_received(pl050_irq_handler);
-	register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-
-	kbd_push_scancode(scan_code);
-	return;
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hid/kbd/port/sgcn.c
===================================================================
--- uspace/srv/hid/kbd/port/sgcn.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,188 +1,0 @@
-/*
- * Copyright (c) 2008 Pavel Rimsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief SGCN (Serengeti Console) keyboard port driver.
- */
-
-#include <as.h>
-#include <ddi.h>
-#include <async.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <thread.h>
-#include <bool.h>
-#include <errno.h>
-
-#define POLL_INTERVAL  10000
-
-/**
- * SGCN buffer header. It is placed at the very beginning of the SGCN
- * buffer.
- */
-typedef struct {
-	/** hard-wired to "CON" */
-	char magic[4];
-	
-	/** we don't need this */
-	char unused[8];
-	
-	/** offset within the SGCN buffer of the input buffer start */
-	uint32_t in_begin;
-	
-	/** offset within the SGCN buffer of the input buffer end */
-	uint32_t in_end;
-	
-	/** offset within the SGCN buffer of the input buffer read pointer */
-	uint32_t in_rdptr;
-	
-	/** offset within the SGCN buffer of the input buffer write pointer */
-	uint32_t in_wrptr;
-} __attribute__ ((packed)) sgcn_buffer_header_t;
-
-/*
- * Returns a pointer to the object of a given type which is placed at the given
- * offset from the console buffer beginning.
- */
-#define SGCN_BUFFER(type, offset) \
-		((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
-
-/** Returns a pointer to the console buffer header. */
-#define SGCN_BUFFER_HEADER	(SGCN_BUFFER(sgcn_buffer_header_t, 0))
-
-/**
- * Virtual address mapped to SRAM.
- */
-static uintptr_t sram_virt_addr;
-
-/**
- * SGCN buffer offset within SGCN.
- */
-static uintptr_t sram_buffer_offset;
-
-/* polling thread */
-static void sgcn_thread_impl(void *arg);
-
-static volatile bool polling_disabled = false;
-
-/**
- * Initializes the SGCN driver.
- * Maps the physical memory (SRAM) and creates the polling thread. 
- */
-int kbd_port_init(void)
-{
-	sysarg_t sram_paddr;
-	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
-		return -1;
-	
-	sysarg_t sram_size;
-	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
-		sram_buffer_offset = 0;
-	
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
-	
-	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
-	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0) {
-		printf("SGCN: uspace driver could not map physical memory.");
-		return -1;
-	}
-	
-	thread_id_t tid;
-	int rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0)
-		return rc;
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-void kbd_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/**
- * Handler of the "key pressed" event. Reads codes of all the pressed keys from
- * the buffer. 
- */
-static void sgcn_key_pressed(void)
-{
-	char c;
-	
-	uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
-	uint32_t end = SGCN_BUFFER_HEADER->in_end;
-	uint32_t size = end - begin;
-	
-	volatile char *buf_ptr = (volatile char *)
-		SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-	volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
-	volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
-	
-	while (*in_rdptr_ptr != *in_wrptr_ptr) {
-		c = *buf_ptr;
-		*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
-		buf_ptr = (volatile char *)
-			SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-		kbd_push_scancode(c);
-	}
-}
-
-/**
- * Thread to poll SGCN for keypresses.
- */
-static void sgcn_thread_impl(void *arg)
-{
-	(void) arg;
-
-	while (1) {
-		if (polling_disabled == false)
-			sgcn_key_pressed();
-		usleep(POLL_INTERVAL);
-	}
-}
-
-/** @}
- */
Index: uspace/srv/hid/kbd/port/ski.c
===================================================================
--- uspace/srv/hid/kbd/port/ski.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,128 +1,0 @@
-/*
- * Copyright (c) 2005 Jakub Jermar
- * Copyright (c) 2009 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- * @brief	Ski console keyboard port driver.
- */
-
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sys/types.h>
-#include <thread.h>
-#include <bool.h>
-
-#define SKI_GETCHAR		21
-
-#define POLL_INTERVAL		10000
-
-static void ski_thread_impl(void *arg);
-static int32_t ski_getchar(void);
-
-static volatile bool polling_disabled = false;
-
-/** Initialize Ski port driver. */
-int kbd_port_init(void)
-{
-	thread_id_t tid;
-	int rc;
-
-	rc = thread_create(ski_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0) {
-		return rc;
-	}
-
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-void kbd_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** Thread to poll Ski for keypresses. */
-static void ski_thread_impl(void *arg)
-{
-	int32_t c;
-	(void) arg;
-
-	while (1) {
-		while (polling_disabled == false) {
-			c = ski_getchar();
-			if (c == 0)
-				break;
-			kbd_push_scancode(c);
-		}
-
-		usleep(POLL_INTERVAL);
-	}
-}
-
-/** Ask Ski if a key was pressed.
- *
- * Use SSC (Simulator System Call) to get character from the debug console.
- * This call is non-blocking.
- *
- * @return ASCII code of pressed key or 0 if no key pressed.
- */
-static int32_t ski_getchar(void)
-{
-	uint64_t ch;
-	
-	asm volatile (
-		"mov r15 = %1\n"
-		"break 0x80000;;\n"	/* modifies r8 */
-		"mov %0 = r8;;\n"		
-
-		: "=r" (ch)
-		: "i" (SKI_GETCHAR)
-		: "r15", "r8"
-	);
-
-	return (int32_t) ch;
-}
-
-/** @}
- */
Index: uspace/srv/hid/kbd/port/sun.c
===================================================================
--- uspace/srv/hid/kbd/port/sun.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * Copyright (c) 2009 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Sun keyboard virtual port driver.
- */
-
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <sysinfo.h>
-#include <errno.h>
-#include <bool.h>
-
-/** Sun keyboard virtual port driver.
- *
- * This is a virtual port driver which can use
- * both ns16550_port_init and z8530_port_init
- * according to the information passed from the
- * kernel. This is just a temporal hack.
- *
- */
-int kbd_port_init(void)
-{
-	sysarg_t z8530;
-	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
-		z8530 = false;
-	
-	sysarg_t ns16550;
-	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
-		ns16550 = false;
-	
-	if (z8530) {
-		if (z8530_port_init() == 0)
-			return 0;
-	}
-	
-	if (ns16550) {
-		if (ns16550_port_init() == 0)
-			return 0;
-	}
-	
-	return -1;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: uspace/srv/hid/kbd/port/z8530.c
===================================================================
--- uspace/srv/hid/kbd/port/z8530.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,116 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Z8530 keyboard port driver.
- */
-
-#include <ipc/irc.h>
-#include <async.h>
-#include <sysinfo.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <sys/types.h>
-#include <ddi.h>
-#include <errno.h>
-
-#define CHAN_A_STATUS  4
-#define CHAN_A_DATA    6
-
-#define RR0_RCA  1
-
-static irq_cmd_t z8530_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = RR0_RCA,
-		.srcarg = 1,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-	
-irq_code_t z8530_kbd = {
-	sizeof(z8530_cmds) / sizeof(irq_cmd_t),
-	z8530_cmds
-};
-
-static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-int z8530_port_init(void)
-{
-	sysarg_t kaddr;
-	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	z8530_cmds[0].addr = (void *) kaddr + CHAN_A_STATUS;
-	z8530_cmds[3].addr = (void *) kaddr + CHAN_A_DATA;
-	
-	async_set_interrupt_received(z8530_irq_handler);
-	register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
-	
-	return 0;
-}
-
-static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
-	
-	if (irc_service)
-		async_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
-		    IPC_GET_IMETHOD(*call));
-}
-
-/** @}
- */
Index: uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
===================================================================
--- uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -42,6 +42,7 @@
 #include <io/console.h>
 #include <vfs/vfs.h>
-#include <ipc/mouse.h>
+#include <ipc/mouseev.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -50,9 +51,11 @@
 #include <errno.h>
 #include <inttypes.h>
-
 #include "s3c24xx_ts.h"
 
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
+
 #define NAME "s3c24ser"
-#define NAMESPACE "hid_in"
+#define NAMESPACE "hid"
 
 static irq_cmd_t ts_irq_cmds[] = {
@@ -70,5 +73,6 @@
 static s3c24xx_ts_t *ts;
 
-static void s3c24xx_ts_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void s3c24xx_ts_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg);
 static void s3c24xx_ts_irq_handler(ipc_callid_t iid, ipc_call_t *call);
 static void s3c24xx_ts_pen_down(s3c24xx_ts_t *ts);
@@ -280,5 +284,5 @@
 	button = 1;
 	press = 0;
-	async_msg_2(ts->client_phone, MEVENT_BUTTON, button, press);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_BUTTON_EVENT, button, press);
 
 	s3c24xx_ts_wait_for_int_mode(ts, updn_down);
@@ -321,6 +325,6 @@
 
 	/* Send notifications to client. */
-	async_msg_2(ts->client_phone, MEVENT_MOVE, dx, dy);
-	async_msg_2(ts->client_phone, MEVENT_BUTTON, button, press);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_MOVE_EVENT, dx, dy);
+	async_obsolete_msg_2(ts->client_phone, MOUSEEV_BUTTON_EVENT, button, press);
 
 	ts->last_x = x_pos;
@@ -370,5 +374,6 @@
 
 /** Handle mouse client connection. */
-static void s3c24xx_ts_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void s3c24xx_ts_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	ipc_callid_t callid;
@@ -380,8 +385,8 @@
 	while (1) {
 		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!IPC_GET_IMETHOD(call)) {
 			if (ts->client_phone != -1) {
-				async_hangup(ts->client_phone);
+				async_obsolete_hangup(ts->client_phone);
 				ts->client_phone = -1;
 			}
@@ -389,4 +394,7 @@
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case IPC_M_CONNECT_TO_ME:
 			if (ts->client_phone != -1) {
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -48,10 +48,14 @@
 #include <ipc/adb.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <assert.h>
 #include "cuda_adb.h"
 
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
+
 #define NAME "cuda_adb"
 
-static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static int cuda_init(void);
 static void cuda_irq_handler(ipc_callid_t iid, ipc_call_t *call);
@@ -189,5 +193,5 @@
 
 /** Character device connection handler */
-static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -219,9 +223,12 @@
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case IPC_M_CONNECT_TO_ME:
 			if (adb_dev[dev_addr].client_phone != -1) {
@@ -479,5 +486,5 @@
 		return;
 
-	async_msg_1(adb_dev[dev_addr].client_phone, ADB_REG_NOTIF, reg_val);
+	async_obsolete_msg_1(adb_dev[dev_addr].client_phone, ADB_REG_NOTIF, reg_val);
 }
 
Index: uspace/srv/hw/char/i8042/i8042.c
===================================================================
--- uspace/srv/hw/char/i8042/i8042.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/char/i8042/i8042.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -41,4 +41,5 @@
 #include <devmap.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <unistd.h>
 #include <sysinfo.h>
@@ -46,6 +47,8 @@
 #include <errno.h>
 #include <inttypes.h>
-
 #include "i8042.h"
+
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
 
 #define NAME "i8042"
@@ -119,5 +122,5 @@
 
 static void i8042_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static int i8042_init(void);
 static void i8042_port_write(int devid, uint8_t data);
@@ -213,5 +216,5 @@
 
 /** Character device connection handler */
-static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void i8042_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -247,9 +250,12 @@
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case IPC_M_CONNECT_TO_ME:
 			printf(NAME ": creating callback connection\n");
@@ -300,5 +306,5 @@
 
 	if (i8042_port[devid].client_phone != -1) {
-		async_msg_1(i8042_port[devid].client_phone,
+		async_obsolete_msg_1(i8042_port[devid].client_phone,
 		    IPC_FIRST_USER_METHOD, data);
 	}
Index: uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c
===================================================================
--- uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/char/s3c24xx_uart/s3c24xx_uart.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -42,4 +42,5 @@
 #include <ipc/char.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -48,6 +49,8 @@
 #include <errno.h>
 #include <inttypes.h>
-
 #include "s3c24xx_uart.h"
+
+// FIXME: remove this header
+#include <kernel/ipc/ipc_methods.h>
 
 #define NAME "s3c24ser"
@@ -68,5 +71,6 @@
 static s3c24xx_uart_t *uart;
 
-static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall);
+static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg);
 static void s3c24xx_uart_irq_handler(ipc_callid_t iid, ipc_call_t *call);
 static int s3c24xx_uart_init(s3c24xx_uart_t *uart);
@@ -110,5 +114,6 @@
 
 /** Character device connection handler. */
-static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void s3c24xx_uart_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	ipc_callid_t callid;
@@ -123,9 +128,12 @@
 		callid = async_get_call(&call);
 		method = IPC_GET_IMETHOD(call);
-		switch (method) {
-		case IPC_M_PHONE_HUNGUP:
+		
+		if (!method) {
 			/* The other side has hung up. */
 			async_answer_0(callid, EOK);
 			return;
+		}
+		
+		switch (method) {
 		case IPC_M_CONNECT_TO_ME:
 			printf(NAME ": creating callback connection\n");
@@ -156,5 +164,5 @@
 
 		if (uart->client_phone != -1) {
-			async_msg_1(uart->client_phone, CHAR_NOTIF_BYTE,
+			async_obsolete_msg_1(uart->client_phone, CHAR_NOTIF_BYTE,
 			    data);
 		}
Index: uspace/srv/hw/irc/apic/apic.c
===================================================================
--- uspace/srv/hw/irc/apic/apic.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/irc/apic/apic.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -38,24 +38,117 @@
 #include <ipc/services.h>
 #include <ipc/irc.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <sysinfo.h>
 #include <as.h>
 #include <ddi.h>
-#include <libarch/ddi.h>
-#include <align.h>
 #include <bool.h>
 #include <errno.h>
 #include <async.h>
-#include <align.h>
-#include <async.h>
-#include <stdio.h>
-#include <ipc/devmap.h>
 
 #define NAME  "apic"
 
+#define APIC_MAX_IRQ	15
+
+#define IOREGSEL  (0x00U / sizeof(uint32_t))
+#define IOWIN     (0x10U / sizeof(uint32_t))
+
+#define IOREDTBL   0x10U
+
+/** I/O Register Select Register. */
+typedef union {
+	uint32_t value;
+	struct {
+		uint8_t reg_addr;	/**< APIC Register Address. */
+		unsigned int : 24;	/**< Reserved. */
+	} __attribute__ ((packed));
+} io_regsel_t;
+
+/** I/O Redirection Register. */
+typedef struct io_redirection_reg {
+	union {
+		uint32_t lo;
+		struct {
+			uint8_t intvec;			/**< Interrupt Vector. */
+			unsigned int delmod : 3;	/**< Delivery Mode. */
+			unsigned int destmod : 1;	/**< Destination mode. */
+			unsigned int delivs : 1;	/**< Delivery status (RO). */
+			unsigned int intpol : 1;	/**< Interrupt Input Pin Polarity. */
+			unsigned int irr : 1;		/**< Remote IRR (RO). */
+			unsigned int trigger_mode : 1;	/**< Trigger Mode. */
+			unsigned int masked : 1;	/**< Interrupt Mask. */
+			unsigned int : 15;		/**< Reserved. */
+		} __attribute__ ((packed));
+	};
+	union {
+		uint32_t hi;
+		struct {
+			unsigned int : 24;	/**< Reserved. */
+			uint8_t dest : 8;  	/**< Destination Field. */
+		} __attribute__ ((packed));
+	};
+} __attribute__ ((packed)) io_redirection_reg_t;
+
+// FIXME: get the address from the kernel
+#define IO_APIC_BASE	0xfec00000UL
+#define IO_APIC_SIZE	20
+
+ioport32_t *io_apic = NULL;
+
+/** Read from IO APIC register.
+ *
+ * @param address IO APIC register address.
+ *
+ * @return Content of the addressed IO APIC register.
+ *
+ */
+static uint32_t io_apic_read(uint8_t address)
+{
+	io_regsel_t regsel;
+
+	regsel.value = io_apic[IOREGSEL];
+	regsel.reg_addr = address;
+	io_apic[IOREGSEL] = regsel.value;
+	return io_apic[IOWIN];
+}
+
+/** Write to IO APIC register.
+ *
+ * @param address IO APIC register address.
+ * @param val     Content to be written to the addressed IO APIC register.
+ *
+ */
+static void io_apic_write(uint8_t address, uint32_t val)
+{
+	io_regsel_t regsel;
+
+	regsel.value = io_apic[IOREGSEL];
+	regsel.reg_addr = address;
+	io_apic[IOREGSEL] = regsel.value;
+	io_apic[IOWIN] = val;
+}
+
+static int irq_to_pin(int irq)
+{
+	// FIXME: get the map from the kernel, even though this may work
+	//	  for simple cases
+	return irq;
+}
+
 static int apic_enable_irq(sysarg_t irq)
 {
-	// FIXME: TODO
-	return ENOTSUP;
+	io_redirection_reg_t reg;
+
+	if (irq > APIC_MAX_IRQ)
+		return ELIMIT;
+
+	int pin = irq_to_pin(irq);
+ 	if (pin == -1)
+		return ENOENT;
+
+	reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2));
+	reg.masked = false;
+	io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo);
+
+	return EOK;
 }
 
@@ -64,7 +157,7 @@
  * @param iid   Hash of the request that opened the connection.
  * @param icall Call data of the request that opened the connection.
- *
- */
-static void apic_connection(ipc_callid_t iid, ipc_call_t *icall)
+ * @param arg	Local argument.
+ */
+static void apic_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -78,4 +171,10 @@
 	while (true) {
 		callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
 		
 		switch (IPC_GET_IMETHOD(call)) {
@@ -102,7 +201,11 @@
 	
 	if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) {
-		printf(NAME ": No APIC found\n");
+		printf("%s: No APIC found\n", NAME);
 		return false;
 	}
+
+	if (pio_enable((void *) IO_APIC_BASE, IO_APIC_SIZE,
+	    (void **) &io_apic) != EOK)
+		return false;	
 	
 	async_set_client_connection(apic_connection);
@@ -114,10 +217,11 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS APIC driver\n");
+	printf("%s: HelenOS APIC driver\n", NAME);
 	
 	if (!apic_init())
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
 	
Index: uspace/srv/hw/irc/fhc/Makefile
===================================================================
--- uspace/srv/hw/irc/fhc/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(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: uspace/srv/hw/irc/fhc/fhc.c
===================================================================
--- uspace/srv/hw/irc/fhc/fhc.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,159 +1,0 @@
-/*
- * Copyright (c) 2009 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fhc
- * @{
- */
-
-/**
- * @file fhc.c
- * @brief FHC bus controller driver.
- */
-
-#include <ipc/services.h>
-#include <ipc/irc.h>
-#include <ipc/ns.h>
-#include <sysinfo.h>
-#include <as.h>
-#include <ddi.h>
-#include <align.h>
-#include <bool.h>
-#include <errno.h>
-#include <async.h>
-#include <align.h>
-#include <async.h>
-#include <stdio.h>
-#include <ipc/devmap.h>
-
-#define NAME "fhc"
-
-#define FHC_UART_INR	0x39	
-
-#define FHC_UART_IMAP	0x0
-#define FHC_UART_ICLR	0x4
-
-static void *fhc_uart_phys;
-static volatile uint32_t *fhc_uart_virt;
-static size_t fhc_uart_size;
-
-/** Handle one connection to fhc.
- *
- * @param iid		Hash of the request that opened the connection.
- * @param icall		Call data of the request that opened the connection.
- */
-static void fhc_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-
-	/*
-	 * Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-
-	while (1) {
-		int inr;
-	
-		callid = async_get_call(&call);
-		switch (IPC_GET_IMETHOD(call)) {
-		case IRC_ENABLE_INTERRUPT:
-			/* Noop */
-			async_answer_0(callid, EOK);
-			break;
-		case IRC_CLEAR_INTERRUPT:
-			inr = IPC_GET_ARG1(call);
-			switch (inr) {
-			case FHC_UART_INR:
-				fhc_uart_virt[FHC_UART_ICLR] = 0;
-				async_answer_0(callid, EOK);
-				break;
-			default:
-				async_answer_0(callid, ENOTSUP);
-				break;
-			}
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-			break;
-		}
-	}
-}
-
-/** Initialize the FHC driver.
- *
- * So far, the driver heavily depends on information provided by the kernel via
- * sysinfo. In the future, there should be a standalone FHC driver.
- */
-static bool fhc_init(void)
-{
-	sysarg_t paddr;
-
-	if ((sysinfo_get_value("fhc.uart.physical", &paddr) != EOK)
-	    || (sysinfo_get_value("fhc.uart.size", &fhc_uart_size) != EOK)) {
-		printf(NAME ": no FHC UART registers found\n");
-		return false;
-	}
-	
-	fhc_uart_phys = (void *) paddr;
-	fhc_uart_virt = as_get_mappable_page(fhc_uart_size);
-	
-	int flags = AS_AREA_READ | AS_AREA_WRITE;
-	int retval = physmem_map(fhc_uart_phys, (void *) fhc_uart_virt,
-	    ALIGN_UP(fhc_uart_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
-	
-	if (retval < 0) {
-		printf(NAME ": Error mapping FHC UART registers\n");
-		return false;
-	}
-	
-	printf(NAME ": FHC UART registers at %p, %zu bytes\n", fhc_uart_phys,
-	    fhc_uart_size);
-	
-	async_set_client_connection(fhc_connection);
-	service_register(SERVICE_IRC);
-	
-	return true;
-}
-
-int main(int argc, char **argv)
-{
-	printf(NAME ": HelenOS FHC bus controller driver\n");
-	
-	if (!fhc_init())
-		return -1;
-	
-	printf(NAME ": Accepting connections\n");
-	async_manager();
-
-	/* Never reached */
-	return 0;
-}
-
-/**
- * @}
- */ 
Index: uspace/srv/hw/irc/i8259/i8259.c
===================================================================
--- uspace/srv/hw/irc/i8259/i8259.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/irc/i8259/i8259.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -38,5 +38,5 @@
 #include <ipc/services.h>
 #include <ipc/irc.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <sysinfo.h>
 #include <as.h>
@@ -98,7 +98,7 @@
  * @param iid   Hash of the request that opened the connection.
  * @param icall Call data of the request that opened the connection.
- *
+ * @param arg	Local argument.
  */
-static void i8259_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void i8259_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -112,4 +112,10 @@
 	while (true) {
 		callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
 		
 		switch (IPC_GET_IMETHOD(call)) {
@@ -136,5 +142,5 @@
 	
 	if ((sysinfo_get_value("i8259", &i8259) != EOK) || (!i8259)) {
-		printf(NAME ": No i8259 found\n");
+		printf("%s: No i8259 found\n", NAME);
 		return false;
 	}
@@ -144,5 +150,5 @@
 	    (pio_enable((void *) IO_RANGE1_START, IO_RANGE1_SIZE,
 	    (void **) &io_range1) != EOK)) {
-		printf(NAME ": i8259 not accessible\n");
+		printf("%s: i8259 not accessible\n", NAME);
 		return false;
 	}
@@ -156,10 +162,11 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS i8259 driver\n");
+	printf("%s: HelenOS i8259 driver\n", NAME);
 	
 	if (!i8259_init())
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
 	
Index: uspace/srv/hw/irc/obio/obio.c
===================================================================
--- uspace/srv/hw/irc/obio/obio.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/irc/obio/obio.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -44,5 +44,5 @@
 #include <ipc/services.h>
 #include <ipc/irc.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <sysinfo.h>
 #include <as.h>
@@ -76,6 +76,7 @@
  * @param iid		Hash of the request that opened the connection.
  * @param icall		Call data of the request that opened the connection.
+ * @param arg		Local argument.
  */
-static void obio_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void obio_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	ipc_callid_t callid;
@@ -118,5 +119,5 @@
 	
 	if (sysinfo_get_value("obio.base.physical", &paddr) != EOK) {
-		printf(NAME ": no OBIO registers found\n");
+		printf("%s: No OBIO registers found\n", NAME);
 		return false;
 	}
@@ -130,9 +131,9 @@
 	
 	if (retval < 0) {
-		printf(NAME ": Error mapping OBIO registers\n");
+		printf("%s: Error mapping OBIO registers\n", NAME);
 		return false;
 	}
 	
-	printf(NAME ": OBIO registers with base at %p\n", base_phys);
+	printf("%s: OBIO registers with base at %p\n", NAME, base_phys);
 	
 	async_set_client_connection(obio_connection);
@@ -144,12 +145,13 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS OBIO driver\n");
+	printf("%s: HelenOS OBIO driver\n", NAME);
 	
 	if (!obio_init())
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
+	task_retval(0);
 	async_manager();
-
+	
 	/* Never reached */
 	return 0;
@@ -158,3 +160,3 @@
 /**
  * @}
- */ 
+ */
Index: uspace/srv/hw/netif/ne2000/dp8390.c
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/netif/ne2000/dp8390.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -483,5 +483,5 @@
 }
 
-static link_t *ne2k_receive(ne2k_t *ne2k)
+static list_t *ne2k_receive(ne2k_t *ne2k)
 {
 	/*
@@ -490,5 +490,5 @@
 	 * frames from the network, but they will be lost.
 	 */
-	link_t *frames = (link_t *) malloc(sizeof(link_t));
+	list_t *frames = (list_t *) malloc(sizeof(list_t));
 	if (frames != NULL)
 		list_initialize(frames);
@@ -567,8 +567,8 @@
 }
 
-link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
+list_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
 {
 	/* List of received frames */
-	link_t *frames = NULL;
+	list_t *frames = NULL;
 	
 	if (isr & (ISR_PTX | ISR_TXE)) {
Index: uspace/srv/hw/netif/ne2000/dp8390.h
===================================================================
--- uspace/srv/hw/netif/ne2000/dp8390.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/netif/ne2000/dp8390.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -241,5 +241,5 @@
 extern void ne2k_down(ne2k_t *);
 extern void ne2k_send(ne2k_t *, packet_t *);
-extern link_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
+extern list_t *ne2k_interrupt(ne2k_t *, uint8_t, uint8_t);
 
 #endif
Index: uspace/srv/hw/netif/ne2000/ne2000.c
===================================================================
--- uspace/srv/hw/netif/ne2000/ne2000.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/hw/netif/ne2000/ne2000.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -43,6 +43,6 @@
 #include <malloc.h>
 #include <sysinfo.h>
+#include <ns.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
 #include <ipc/irc.h>
 #include <net/modules.h>
@@ -76,5 +76,5 @@
 
 static bool irc_service = false;
-static int irc_phone = -1;
+static async_sess_t *irc_sess = NULL;
 
 /** NE2000 kernel interrupt command sequence.
@@ -152,13 +152,14 @@
 	device_id_t device_id = IRQ_GET_DEVICE(*call);
 	netif_device_t *device;
-	int nil_phone;
+	async_sess_t *nil_sess;
 	ne2k_t *ne2k;
 	
 	fibril_rwlock_read_lock(&netif_globals.lock);
 	
-	if (find_device(device_id, &device) == EOK) {
-		nil_phone = device->nil_phone;
+	nil_sess = netif_globals.nil_sess;
+	
+	if (find_device(device_id, &device) == EOK)
 		ne2k = (ne2k_t *) device->specific;
-	} else
+	else
 		ne2k = NULL;
 	
@@ -166,14 +167,14 @@
 	
 	if (ne2k != NULL) {
-		link_t *frames =
+		list_t *frames =
 		    ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
 		
 		if (frames != NULL) {
 			while (!list_empty(frames)) {
-				frame_t *frame =
-				    list_get_instance(frames->next, frame_t, link);
+				frame_t *frame = list_get_instance(
+				    list_first(frames), frame_t, link);
 				
 				list_remove(&frame->link);
-				nil_received_msg(nil_phone, device_id, frame->packet,
+				nil_received_msg(nil_sess, device_id, frame->packet,
 				    SERVICE_NONE);
 				free(frame);
@@ -276,5 +277,4 @@
 	
 	device->device_id = device_id;
-	device->nil_phone = -1;
 	device->specific = (void *) ne2k;
 	device->state = NETIF_STOPPED;
@@ -329,6 +329,9 @@
 		change_state(device, NETIF_ACTIVE);
 		
-		if (irc_service)
-			async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
+		if (irc_service) {
+			async_exch_t *exch = async_exchange_begin(irc_sess);
+			async_msg_1(exch, IRC_ENABLE_INTERRUPT, ne2k->irq);
+			async_exchange_end(exch);
+		}
 	}
 	
@@ -388,11 +391,12 @@
 	
 	if (irc_service) {
-		while (irc_phone < 0)
-			irc_phone = service_connect_blocking(SERVICE_IRC, 0, 0);
+		while (!irc_sess)
+			irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+			    SERVICE_IRC, 0, 0);
 	}
 	
 	async_set_interrupt_received(irq_handler);
 	
-	return async_connect_to_me(PHONE_NS, SERVICE_NE2000, 0, 0, NULL);
+	return service_register(SERVICE_NE2000);
 }
 
Index: uspace/srv/loader/Makefile
===================================================================
--- uspace/srv/loader/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/loader/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -36,16 +36,12 @@
 -include $(COMMON_MAKEFILE)
 -include $(CONFIG_MAKEFILE)
--include arch/$(UARCH)/Makefile.inc
 
-LINKER_SCRIPT = arch/$(UARCH)/_link.ld
-EXTRA_CLEAN = $(LINKER_SCRIPT)
-
-EXTRA_CFLAGS = -Iinclude
+LINKER_SCRIPT = $(LIBC_PREFIX)/arch/$(UARCH)/_link-loader.ld
 
 BINARY = loader
+STATIC_ONLY = y
 
 GENERIC_SOURCES = \
 	main.c \
-	elf_load.c \
 	interp.s
 
@@ -55,5 +51,2 @@
 
 include $(USPACE_PREFIX)/Makefile.common
-
-$(LINKER_SCRIPT): $(LINKER_SCRIPT).in
-	$(GCC) $(DEFS) $(CFLAGS) -DLIBC_PREFIX=$(LIBC_PREFIX) -E -x c $< | grep -v "^\#" > $@
Index: uspace/srv/loader/arch/abs32le/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/abs32le/Makefile.inc	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,29 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/abs32le.c
Index: uspace/srv/loader/arch/abs32le/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/abs32le/_link.ld.in	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,60 +1,0 @@
-/*
- * The difference from _link.ld.in for regular statically-linked apps
- * is the base address and the special interp section.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FILEHDR PHDRS FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70001000;
-	
-	.text : {
-		*(.text .text.*);
-		*(.rodata .rodata.*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.data);
-		*(.data.rel*);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		*(.gnu.linkonce.tb.*);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.sbss : {
-		*(.scommon);
-		*(.sbss);
-	}
-	
-	.bss : {
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: uspace/srv/loader/arch/abs32le/abs32le.c
===================================================================
--- uspace/srv/loader/arch/abs32le/abs32le.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,42 +1,0 @@
-/*
- * Copyright (c) 2010 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- */
-
-#include <bool.h>
-#include "arch.h"
-
-void program_run(void *entry_point, void *pcb)
-{
-	while (true);
-}
-
-/**
- * @}
- */
Index: uspace/srv/loader/arch/amd64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/amd64/Makefile.inc	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,29 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/amd64.s
Index: uspace/srv/loader/arch/amd64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/amd64/_link.ld.in	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * The difference from _link.ld.in for regular statically-linked apps
- * is the base address and the special interp section.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-	debug PT_NOTE;
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	/* . = 0x0000700000001000; */
-	. = 0x70001000;
-	
-	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text .text.*);
-		*(.rodata .rodata.*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.data);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-#ifdef CONFIG_LINE_DEBUG
-	.comment 0 : { *(.comment); } :debug
-	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
-	.debug_aranges 0 : { *(.debug_aranges); } :debug
-	.debug_info 0 : { *(.debug_info); } :debug
-	.debug_line 0 : { *(.debug_line); } :debug
-	.debug_loc 0 : { *(.debug_loc); } :debug
-	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
-	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
-	.debug_ranges 0 : { *(.debug_ranges); } :debug
-	.debug_str 0 : { *(.debug_str); } :debug
-#endif
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: uspace/srv/loader/arch/amd64/amd64.s
===================================================================
--- uspace/srv/loader/arch/amd64/amd64.s	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,43 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# %rdi	contains entry_point
-# %rsi	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	# pcb must be passed in %rdi, use %rdx as a scratch register
-	mov %rdi, %rdx
-	mov %rsi, %rdi
-
-	# jump to entry point
-	jmp %rdx
Index: uspace/srv/loader/arch/arm32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/arm32/Makefile.inc	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,29 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/arm32.s
Index: uspace/srv/loader/arch/arm32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/arm32/_link.ld.in	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * The only difference from _link.ld.in for regular statically-linked apps
- * is the base address.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} : interp
-	
-	. = 0x70001000;
-	
-	.init ALIGN(0x1000): SUBALIGN(0x1000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text .text.*);
-		*(.rodata .rodata.*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.opd);
-		*(.data .data.*);
-		*(.sdata);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(.sbss);
-		*(.scommon);
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: uspace/srv/loader/arch/arm32/arm32.s
===================================================================
--- uspace/srv/loader/arch/arm32/arm32.s	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,42 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# r0	contains entry_point
-# r1	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	# load ras_page address to r2
-	ldr r2, =ras_page
-	ldr r2, [r2]
-	# pcb is passed to the entry point in r1 (where it already is)
-	mov r15, r0
Index: uspace/srv/loader/arch/ia32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ia32/Makefile.inc	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,29 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/ia32.s
Index: uspace/srv/loader/arch/ia32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia32/_link.ld.in	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * The difference from _link.ld.in for regular statically-linked apps
- * is the base address and the special interp section.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FILEHDR PHDRS FLAGS(5);
-	data PT_LOAD FLAGS(6);
-	debug PT_NOTE;
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70001000;
-	
-	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text .text.*);
-		*(.rodata .rodata.*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.data);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		*(.gnu.linkonce.tb.*);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-#ifdef CONFIG_LINE_DEBUG
-	.comment 0 : { *(.comment); } :debug
-	.debug_abbrev 0 : { *(.debug_abbrev); } :debug
-	.debug_aranges 0 : { *(.debug_aranges); } :debug
-	.debug_info 0 : { *(.debug_info); } :debug
-	.debug_line 0 : { *(.debug_line); } :debug
-	.debug_loc 0 : { *(.debug_loc); } :debug
-	.debug_pubnames 0 : { *(.debug_pubnames); } :debug
-	.debug_pubtypes 0 : { *(.debug_pubtypes); } :debug
-	.debug_ranges 0 : { *(.debug_ranges); } :debug
-	.debug_str 0 : { *(.debug_str); } :debug
-#endif
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: uspace/srv/loader/arch/ia32/ia32.s
===================================================================
--- uspace/srv/loader/arch/ia32/ia32.s	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,49 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# Jump to a program entry point
-program_run:
-	# Use standard ia32 prologue not to confuse anybody
-	push %ebp
-	movl %esp, %ebp
-
-	# %eax := entry_point
-	movl 0x8(%ebp), %eax
-
-	# %edi := pcb
-	# pcb is passed to the entry point in %edi
-	mov 0xc(%ebp), %edi
-
-	# Save a tiny bit of stack space
-	pop %ebp
-
-	jmp *%eax
Index: uspace/srv/loader/arch/ia64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ia64/Makefile.inc	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,30 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/ia64.s
-AFLAGS += -xexplicit
Index: uspace/srv/loader/arch/ia64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ia64/_link.ld.in	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,65 +1,0 @@
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	/* On Itanium code sections must be aligned to 16 bytes. */
-	. = ALIGN(0x800000000 + SIZEOF_HEADERS, 16);
-	
-	.init : {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text .text.*);
-		*(.rodata .rodata.*);
-	} :text
-	
-	. = . + 0x4000;
-	
-	.got : {
-		/* Tell the linker where we expect GP to point. */
-		__gp = .;
-		*(.got .got.*);
-	} :data
-	
-	.data : {
-		*(.opd);
-		*(.data .data.*);
-		*(.sdata);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(.sbss);
-		*(.scommon);
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: uspace/srv/loader/arch/ia64/ia64.s
===================================================================
--- uspace/srv/loader/arch/ia64/ia64.s	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,43 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-.text
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# in0 (r32)	contains entry_point
-# in1 (r33)	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	# Pass pcb to the entry point in r2
-
-	mov b6 = r32
-	mov r2 = r33 ;;
-	br b6 ;;
Index: uspace/srv/loader/arch/mips32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/mips32/Makefile.inc	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,29 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/mips32.s
Index: uspace/srv/loader/arch/mips32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/mips32/_link.ld.in	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,70 +1,0 @@
-/*
- * The only difference from _link.ld.in for regular statically-linked apps
- * is the base address.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70004000;
-	
-	.init ALIGN(0x4000) : SUBALIGN(0x4000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text .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/srv/loader/arch/mips32/mips32.s
===================================================================
--- uspace/srv/loader/arch/mips32/mips32.s	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,49 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-.text
-.section .text
-.global program_run
-.set noreorder
-
-## void program_run(void *entry_point, void *pcb);
-#
-# $a0 (=$4)	contains entry_point
-# $a1 (=$5)	contains pcb
-#
-# Jump to a program entry point
-.ent program_run
-program_run:
-	# tmp := entry_point
-	move $25, $a0
-
-	# Pass pcb to the entry point in $a0
-	move $a0, $a1
-	jr $25
-	nop
-.end
Index: uspace/srv/loader/arch/mips32eb
===================================================================
--- uspace/srv/loader/arch/mips32eb	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,1 +1,0 @@
-mips32
Index: uspace/srv/loader/arch/ppc32/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/ppc32/Makefile.inc	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,29 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/ppc32.s
Index: uspace/srv/loader/arch/ppc32/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/ppc32/_link.ld.in	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * The only difference from _link.ld.in for regular statically-linked apps
- * is the base address.
- */
-
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70001000;
-	
-	.init ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text .text.*);
-		*(.rodata .rodata.*);
-	} :text
-	
-	.data ALIGN(0x1000) : SUBALIGN(0x1000) {
-		*(.data);
-		*(.sdata);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(.sbss);
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: uspace/srv/loader/arch/ppc32/ppc32.s
===================================================================
--- uspace/srv/loader/arch/ppc32/ppc32.s	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,40 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# %r3	contains entry_point
-# %r4	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	mtctr %r3
-	mr %r6, %r4	# Pass pcb to the entry point in %r6
-	bctr
Index: uspace/srv/loader/arch/sparc64/Makefile.inc
===================================================================
--- uspace/srv/loader/arch/sparc64/Makefile.inc	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,29 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-ARCH_SOURCES = arch/$(UARCH)/sparc64.s
Index: uspace/srv/loader/arch/sparc64/_link.ld.in
===================================================================
--- uspace/srv/loader/arch/sparc64/_link.ld.in	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,61 +1,0 @@
-STARTUP(LIBC_PREFIX/arch/UARCH/src/entry.o)
-ENTRY(__entry)
-
-PHDRS {
-	interp PT_INTERP;
-	text PT_LOAD FLAGS(5);
-	data PT_LOAD FLAGS(6);
-}
-
-SECTIONS {
-	.interp : {
-		*(.interp);
-	} :interp
-	
-	. = 0x70004000 + SIZEOF_HEADERS;
-	
-	.init : {
-		*(.init);
-	} :text
-	
-	.text : {
-		*(.text .text.*);
-		*(.rodata .rodata.*);
-	} :text
-	
-	. = . + 0x4000;
-	
-	.got : {
-		 _gp = .;
-		 *(.got*);
-	} :data
-	
-	.data : {
-		*(.data);
-		*(.sdata);
-	} :data
-	
-	.tdata : {
-		_tdata_start = .;
-		*(.tdata);
-		_tdata_end = .;
-	} :data
-	
-	.tbss : {
-		_tbss_start = .;
-		*(.tbss);
-		_tbss_end = .;
-	} :data
-	
-	_tls_alignment = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
-	
-	.bss : {
-		*(.sbss);
-		*(COMMON);
-		*(.bss);
-	} :data
-	
-	/DISCARD/ : {
-		*(*);
-	}
-}
Index: uspace/srv/loader/arch/sparc64/sparc64.s
===================================================================
--- uspace/srv/loader/arch/sparc64/sparc64.s	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,42 +1,0 @@
-#
-# Copyright (c) 2008 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-.globl program_run
-
-## void program_run(void *entry_point, void *pcb);
-#
-# %o0	contains entry_point
-# %o1	contains pcb
-#
-# Jump to a program entry point
-program_run:
-	# Pass pcb pointer to entry point in %o1. As it is already
-	# there, no action is needed.
-	call %o0
-	nop
-	# fixme: use branch instead of call
Index: uspace/srv/loader/elf_load.c
===================================================================
--- uspace/srv/loader/elf_load.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,477 +1,0 @@
-/*
- * Copyright (c) 2006 Sergey Bondari
- * Copyright (c) 2006 Jakub Jermar
- * Copyright (c) 2008 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup generic	
- * @{
- */
-
-/**
- * @file
- * @brief	Userspace ELF loader.
- *
- * This module allows loading ELF binaries (both executables and
- * shared objects) from VFS. The current implementation allocates
- * anonymous memory, fills it with segment data and then adjusts
- * the memory areas' flags to the final value. In the future,
- * the segments will be mapped directly from the file.
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <align.h>
-#include <assert.h>
-#include <as.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <smc.h>
-#include <loader/pcb.h>
-
-#include "elf.h"
-#include "elf_load.h"
-#include "arch.h"
-
-#define DPRINTF(...)
-
-static const char *error_codes[] = {
-	"no error",
-	"invalid image",
-	"address space error",
-	"incompatible image",
-	"unsupported image type",
-	"irrecoverable error"
-};
-
-static unsigned int elf_load(elf_ld_t *elf, size_t so_bias);
-static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry);
-static int section_header(elf_ld_t *elf, elf_section_header_t *entry);
-static int load_segment(elf_ld_t *elf, elf_segment_header_t *entry);
-
-/** Read until the buffer is read in its entirety. */
-static int my_read(int fd, void *buf, size_t len)
-{
-	int cnt = 0;
-	do {
-		buf += cnt;
-		len -= cnt;
-		cnt = read(fd, buf, len);
-	} while ((cnt > 0) && ((len - cnt) > 0));
-
-	return cnt;
-}
-
-/** Load ELF binary from a file.
- *
- * Load an ELF binary from the specified file. If the file is
- * an executable program, it is loaded unbiased. If it is a shared
- * object, it is loaded with the bias @a so_bias. Some information
- * extracted from the binary is stored in a elf_info_t structure
- * pointed to by @a info.
- *
- * @param file_name Path to the ELF file.
- * @param so_bias   Bias to use if the file is a shared object.
- * @param info      Pointer to a structure for storing information
- *                  extracted from the binary.
- *
- * @return EOK on success or negative error code.
- *
- */
-int elf_load_file(const char *file_name, size_t so_bias, elf_info_t *info)
-{
-	elf_ld_t elf;
-
-	int fd;
-	int rc;
-	
-	fd = open(file_name, O_RDONLY);
-	if (fd < 0) {
-		DPRINTF("failed opening file\n");
-		return -1;
-	}
-
-	elf.fd = fd;
-	elf.info = info;
-
-	rc = elf_load(&elf, so_bias);
-
-	close(fd);
-
-	return rc;
-}
-
-/** Run an ELF executable.
- *
- * Transfers control to the entry point of an ELF executable loaded
- * earlier with elf_load_file(). This function does not return.
- *
- * @param info Info structure filled earlier by elf_load_file()
- *
- */
-void elf_run(elf_info_t *info, pcb_t *pcb)
-{
-	program_run(info->entry, pcb);
-
-	/* not reached */
-}
-
-/** Create the program control block (PCB).
- *
- * Fills the program control block @a pcb with information from
- * @a info.
- *
- * @param info	Program info structure
- * @return EOK on success or negative error code
- */
-void elf_create_pcb(elf_info_t *info, pcb_t *pcb)
-{
-	pcb->entry = info->entry;
-	pcb->dynamic = info->dynamic;
-}
-
-
-/** Load an ELF binary.
- *
- * The @a elf structure contains the loader state, including
- * an open file, from which the binary will be loaded,
- * a pointer to the @c info structure etc.
- *
- * @param elf		Pointer to loader state buffer.
- * @param so_bias	Bias to use if the file is a shared object.
- * @return EE_OK on success or EE_xx error code.
- */
-static unsigned int elf_load(elf_ld_t *elf, size_t so_bias)
-{
-	elf_header_t header_buf;
-	elf_header_t *header = &header_buf;
-	int i, rc;
-
-	rc = my_read(elf->fd, header, sizeof(elf_header_t));
-	if (rc < 0) {
-		DPRINTF("Read error.\n"); 
-		return EE_INVALID;
-	}
-
-	elf->header = header;
-
-	/* Identify ELF */
-	if (header->e_ident[EI_MAG0] != ELFMAG0 ||
-	    header->e_ident[EI_MAG1] != ELFMAG1 || 
-	    header->e_ident[EI_MAG2] != ELFMAG2 ||
-	    header->e_ident[EI_MAG3] != ELFMAG3) {
-		DPRINTF("Invalid header.\n");
-		return EE_INVALID;
-	}
-	
-	/* Identify ELF compatibility */
-	if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
-	    header->e_machine != ELF_MACHINE || 
-	    header->e_ident[EI_VERSION] != EV_CURRENT ||
-	    header->e_version != EV_CURRENT ||
-	    header->e_ident[EI_CLASS] != ELF_CLASS) {
-		DPRINTF("Incompatible data/version/class.\n");
-		return EE_INCOMPATIBLE;
-	}
-
-	if (header->e_phentsize != sizeof(elf_segment_header_t)) {
-		DPRINTF("e_phentsize:%d != %d\n", header->e_phentsize,
-		    sizeof(elf_segment_header_t));
-		return EE_INCOMPATIBLE;
-	}
-
-	if (header->e_shentsize != sizeof(elf_section_header_t)) {
-		DPRINTF("e_shentsize:%d != %d\n", header->e_shentsize,
-		    sizeof(elf_section_header_t));
-		return EE_INCOMPATIBLE;
-	}
-
-	/* Check if the object type is supported. */
-	if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
-		DPRINTF("Object type %d is not supported\n", header->e_type);
-		return EE_UNSUPPORTED;
-	}
-
-	/* Shared objects can be loaded with a bias */
-	if (header->e_type == ET_DYN)
-		elf->bias = so_bias;
-	else
-		elf->bias = 0;
-
-	elf->info->interp = NULL;
-	elf->info->dynamic = NULL;
-
-	/* Walk through all segment headers and process them. */
-	for (i = 0; i < header->e_phnum; i++) {
-		elf_segment_header_t segment_hdr;
-
-		/* Seek to start of segment header */
-		lseek(elf->fd, header->e_phoff
-		        + i * sizeof(elf_segment_header_t), SEEK_SET);
-
-		rc = my_read(elf->fd, &segment_hdr,
-		    sizeof(elf_segment_header_t));
-		if (rc < 0) {
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		rc = segment_header(elf, &segment_hdr);
-		if (rc != EE_OK)
-			return rc;
-	}
-
-	DPRINTF("Parse sections.\n");
-
-	/* Inspect all section headers and proccess them. */
-	for (i = 0; i < header->e_shnum; i++) {
-		elf_section_header_t section_hdr;
-
-		/* Seek to start of section header */
-		lseek(elf->fd, header->e_shoff
-		    + i * sizeof(elf_section_header_t), SEEK_SET);
-
-		rc = my_read(elf->fd, &section_hdr,
-		    sizeof(elf_section_header_t));
-		if (rc < 0) {
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		rc = section_header(elf, &section_hdr);
-		if (rc != EE_OK)
-			return rc;
-	}
-
-	elf->info->entry =
-	    (entry_point_t)((uint8_t *)header->e_entry + elf->bias);
-
-	DPRINTF("Done.\n");
-
-	return EE_OK;
-}
-
-/** Print error message according to error code.
- *
- * @param rc Return code returned by elf_load().
- *
- * @return NULL terminated description of error.
- */
-const char *elf_error(unsigned int rc)
-{
-	assert(rc < sizeof(error_codes) / sizeof(char *));
-
-	return error_codes[rc];
-}
-
-/** Process segment header.
- *
- * @param entry	Segment header.
- *
- * @return EE_OK on success, error code otherwise.
- */
-static int segment_header(elf_ld_t *elf, elf_segment_header_t *entry)
-{
-	switch (entry->p_type) {
-	case PT_NULL:
-	case PT_PHDR:
-	case PT_NOTE:
-		break;
-	case PT_LOAD:
-		return load_segment(elf, entry);
-		break;
-	case PT_INTERP:
-		/* Assume silently interp == "/rtld.so" */
-		elf->info->interp = "/rtld.so";
-		break;
-	case PT_DYNAMIC:
-	case PT_SHLIB:
-	case PT_LOPROC:
-	case PT_HIPROC:
-	default:
-		DPRINTF("Segment p_type %d unknown.\n", entry->p_type);
-		return EE_UNSUPPORTED;
-		break;
-	}
-	return EE_OK;
-}
-
-/** Load segment described by program header entry.
- *
- * @param elf	Loader state.
- * @param entry Program header entry describing segment to be loaded.
- *
- * @return EE_OK on success, error code otherwise.
- */
-int load_segment(elf_ld_t *elf, elf_segment_header_t *entry)
-{
-	void *a;
-	int flags = 0;
-	uintptr_t bias;
-	uintptr_t base;
-	void *seg_ptr;
-	uintptr_t seg_addr;
-	size_t mem_sz;
-	int rc;
-
-	bias = elf->bias;
-
-	seg_addr = entry->p_vaddr + bias;
-	seg_ptr = (void *) seg_addr;
-
-	DPRINTF("Load segment at addr %p, size 0x%x\n", (void *) seg_addr,
-		entry->p_memsz);
-
-	if (entry->p_align > 1) {
-		if ((entry->p_offset % entry->p_align) !=
-		    (seg_addr % entry->p_align)) {
-			DPRINTF("Align check 1 failed offset%%align=%d, "
-			    "vaddr%%align=%d\n",
-			    entry->p_offset % entry->p_align,
-			    seg_addr % entry->p_align
-			);
-			return EE_INVALID;
-		}
-	}
-
-	/* Final flags that will be set for the memory area */
-
-	if (entry->p_flags & PF_X)
-		flags |= AS_AREA_EXEC;
-	if (entry->p_flags & PF_W)
-		flags |= AS_AREA_WRITE;
-	if (entry->p_flags & PF_R)
-		flags |= AS_AREA_READ;
-	flags |= AS_AREA_CACHEABLE;
-	
-	base = ALIGN_DOWN(entry->p_vaddr, PAGE_SIZE);
-	mem_sz = entry->p_memsz + (entry->p_vaddr - base);
-
-	DPRINTF("Map to seg_addr=%p-%p.\n", (void *) seg_addr,
-	    (void *) (entry->p_vaddr + bias +
-	    ALIGN_UP(entry->p_memsz, PAGE_SIZE)));
-
-	/*
-	 * For the course of loading, the area needs to be readable
-	 * and writeable.
-	 */
-	a = as_area_create((uint8_t *)base + bias, mem_sz,
-	    AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
-	if (a == (void *)(-1)) {
-		DPRINTF("Memory mapping failed.\n");
-		return EE_MEMORY;
-	}
-
-	DPRINTF("as_area_create(%p, %#zx, %d) -> %p\n",
-	    (void *) (base + bias), mem_sz, flags, (void *) a);
-
-	/*
-	 * Load segment data
-	 */
-	rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
-	if (rc < 0) {
-		printf("seek error\n");
-		return EE_INVALID;
-	}
-
-/*	rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
-	if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
-
-	/* Long reads are not possible yet. Load segment piecewise. */
-
-	unsigned left, now;
-	uint8_t *dp;
-
-	left = entry->p_filesz;
-	dp = seg_ptr;
-
-	while (left > 0) {
-		now = 16384;
-		if (now > left) now = left;
-
-		rc = my_read(elf->fd, dp, now);
-
-		if (rc < 0) { 
-			DPRINTF("Read error.\n");
-			return EE_INVALID;
-		}
-
-		left -= now;
-		dp += now;
-	}
-
-	rc = as_area_change_flags(seg_ptr, flags);
-	if (rc != 0) {
-		DPRINTF("Failed to set memory area flags.\n");
-		return EE_MEMORY;
-	}
-
-	if (flags & AS_AREA_EXEC) {
-		/* Enforce SMC coherence for the segment */
-		if (smc_coherence(seg_ptr, entry->p_filesz))
-			return EE_MEMORY;
-	}
-
-	return EE_OK;
-}
-
-/** Process section header.
- *
- * @param elf	Loader state.
- * @param entry Segment header.
- *
- * @return EE_OK on success, error code otherwise.
- */
-static int section_header(elf_ld_t *elf, elf_section_header_t *entry)
-{
-	switch (entry->sh_type) {
-	case SHT_PROGBITS:
-		if (entry->sh_flags & SHF_TLS) {
-			/* .tdata */
-		}
-		break;
-	case SHT_NOBITS:
-		if (entry->sh_flags & SHF_TLS) {
-			/* .tbss */
-		}
-		break;
-	case SHT_DYNAMIC:
-		/* Record pointer to dynamic section into info structure */
-		elf->info->dynamic =
-		    (void *)((uint8_t *)entry->sh_addr + elf->bias);
-		DPRINTF("Dynamic section found at %p.\n",
-		    (void *) elf->info->dynamic);
-		break;
-	default:
-		break;
-	}
-	
-	return EE_OK;
-}
-
-/** @}
- */
Index: uspace/srv/loader/include/arch.h
===================================================================
--- uspace/srv/loader/include/arch.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2008 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup fs
- * @{
- */
-/** @file
- * @brief
- */
-
-#ifndef LOADER_ARCH_H_
-#define LOADER_ARCH_H_
-
-extern void program_run(void *entry_point, void *pcb);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/loader/include/elf.h
===================================================================
--- uspace/srv/loader/include/elf.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(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: uspace/srv/loader/include/elf_load.h
===================================================================
--- uspace/srv/loader/include/elf_load.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ 	(revision )
@@ -1,83 +1,0 @@
-/*
- * Copyright (c) 2008 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup generic
- * @{
- */
-/** @file
- * @brief ELF loader structures and public functions.
- */
-
-#ifndef ELF_LOAD_H_
-#define ELF_LOAD_H_
-
-#include <arch/elf.h>
-#include <sys/types.h>
-#include <loader/pcb.h>
-
-#include "elf.h"
-
-/**
- * Some data extracted from the headers are stored here
- */
-typedef struct {
-	/** Entry point */
-	entry_point_t entry;
-
-	/** ELF interpreter name or NULL if statically-linked */
-	const char *interp;
-
-	/** Pointer to the dynamic section */
-	void *dynamic;
-} elf_info_t;
-
-/**
- * Holds information about an ELF binary being loaded.
- */
-typedef struct {
-	/** Filedescriptor of the file from which we are loading */
-	int fd;
-
-	/** Difference between run-time addresses and link-time addresses */
-	uintptr_t bias;
-
-	/** A copy of the ELF file header */
-	elf_header_t *header;
-
-	/** Store extracted info here */
-	elf_info_t *info;
-} elf_ld_t;
-
-int elf_load_file(const char *file_name, size_t so_bias, elf_info_t *info);
-void elf_run(elf_info_t *info, pcb_t *pcb);
-void elf_create_pcb(elf_info_t *info, pcb_t *pcb);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/loader/main.c
===================================================================
--- uspace/srv/loader/main.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/loader/main.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -52,14 +52,21 @@
 #include <ipc/services.h>
 #include <ipc/loader.h>
-#include <ipc/ns.h>
-#include <macros.h>
+#include <ns.h>
 #include <loader/pcb.h>
+#include <entry_point.h>
 #include <errno.h>
 #include <async.h>
 #include <str.h>
 #include <as.h>
-
-#include <elf.h>
-#include <elf_load.h>
+#include <elf/elf.h>
+#include <elf/elf_load.h>
+
+#ifdef CONFIG_RTLD
+#include <rtld/rtld.h>
+#include <rtld/dynamic.h>
+#include <rtld/module.h>
+
+static int ldr_load_dyn_linked(elf_info_t *p_info);
+#endif
 
 #define DPRINTF(...)
@@ -89,10 +96,13 @@
 
 static elf_info_t prog_info;
-static elf_info_t interp_info;
-
-static bool is_dyn_linked;
 
 /** Used to limit number of connections to one. */
 static bool connected = false;
+
+#ifdef CONFIG_RTLD
+/** State structure of the dynamic linker. */
+runtime_env_t dload_re;
+static module_t prog_mod;
+#endif
 
 static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
@@ -283,5 +293,5 @@
 	int rc;
 	
-	rc = elf_load_file(pathname, 0, &prog_info);
+	rc = elf_load_file(pathname, 0, 0, &prog_info);
 	if (rc != EE_OK) {
 		DPRINTF("Failed to load executable '%s'.\n", pathname);
@@ -302,23 +312,70 @@
 	if (prog_info.interp == NULL) {
 		/* Statically linked program */
-		is_dyn_linked = false;
 		async_answer_0(rid, EOK);
 		return 0;
 	}
 	
-	rc = elf_load_file(prog_info.interp, 0, &interp_info);
-	if (rc != EE_OK) {
-		DPRINTF("Failed to load interpreter '%s.'\n",
-		    prog_info.interp);
-		async_answer_0(rid, EINVAL);
-		return 1;
-	}
-	
-	is_dyn_linked = true;
-	async_answer_0(rid, EOK);
-	
+	DPRINTF("Binary is dynamically linked.\n");
+#ifdef CONFIG_RTLD
+	DPRINTF(" - pcb address: %p\n", &pcb);
+	DPRINTF( "- prog dynamic: %p\n", prog_info.dynamic);
+
+	rc = ldr_load_dyn_linked(&prog_info);
+#else
+	rc = ENOTSUP;
+#endif
+	async_answer_0(rid, rc);
 	return 0;
 }
 
+#ifdef CONFIG_RTLD
+
+static int ldr_load_dyn_linked(elf_info_t *p_info)
+{
+	runtime_env = &dload_re;
+
+	DPRINTF("Load dynamically linked program.\n");
+
+	/*
+	 * First we need to process dynamic sections of the executable
+	 * program and insert it into the module graph.
+	 */
+
+	DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
+	dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
+	prog_mod.bias = 0;
+	prog_mod.dyn.soname = "[program]";
+
+	/* Initialize list of loaded modules */
+	list_initialize(&runtime_env->modules);
+	list_append(&prog_mod.modules_link, &runtime_env->modules);
+
+	/* Pointer to program module. Used as root of the module graph. */
+	runtime_env->program = &prog_mod;
+
+	/* Work around non-existent memory space allocation. */
+	runtime_env->next_bias = 0x1000000;
+
+	/*
+	 * Now we can continue with loading all other modules.
+	 */
+
+	DPRINTF("Load all program dependencies\n");
+	module_load_deps(&prog_mod);
+
+	/*
+	 * Now relocate/link all modules together.
+	 */
+
+	/* Process relocations in all modules */
+	DPRINTF("Relocate all modules\n");
+	modules_process_relocs(&prog_mod);
+
+	/* Pass runtime evironment pointer through PCB. */
+	pcb.rtld_runtime = (void *) runtime_env;
+
+	return 0;
+}
+#endif
 
 /** Run the previously loaded program.
@@ -332,4 +389,6 @@
 	const char *cp;
 	
+	DPRINTF("Set task name\n");
+
 	/* Set the task name. */
 	cp = str_rchr(pathname, '/');
@@ -337,16 +396,9 @@
 	task_set_name(cp);
 	
-	if (is_dyn_linked == true) {
-		/* Dynamically linked program */
-		DPRINTF("Run ELF interpreter.\n");
-		DPRINTF("Entry point: %p\n", interp_info.entry);
-		
-		async_answer_0(rid, EOK);
-		elf_run(&interp_info, &pcb);
-	} else {
-		/* Statically linked program */
-		async_answer_0(rid, EOK);
-		elf_run(&prog_info, &pcb);
-	}
+	/* Run program */
+	DPRINTF("Reply OK\n");
+	async_answer_0(rid, EOK);
+	DPRINTF("Jump to entry point at %p\n", pcb.entry);
+	entry_point_jmp(prog_info.entry, &pcb);
 	
 	/* Not reached */
@@ -358,10 +410,6 @@
  * to execute the loaded program).
  */
-static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int retval;
-	
+static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
 	/* Already have a connection? */
 	if (connected) {
@@ -376,13 +424,15 @@
 	
 	/* Ignore parameters, the connection is already open */
-	(void) iid;
 	(void) icall;
 	
-	while (1) {
-		callid = async_get_call(&call);
+	while (true) {
+		int retval;
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call))
+			exit(0);
 		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			exit(0);
 		case LOADER_GET_TASKID:
 			ldr_get_taskid(callid, &call);
@@ -411,6 +461,5 @@
 		}
 		
-		if (IPC_GET_IMETHOD(call) != IPC_M_PHONE_HUNGUP)
-			async_answer_0(callid, retval);
+		async_answer_0(callid, retval);
 	}
 }
@@ -425,5 +474,5 @@
 	/* Introduce this task to the NS (give it our task ID). */
 	task_id_t id = task_get_id();
-	int rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
+	int rc = ns_intro(id);
 	if (rc != EOK)
 		return -1;
Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/il/arp/arp.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -164,5 +164,5 @@
 }
 
-static int arp_clean_cache_req(int arp_phone)
+static int arp_clean_cache_req(void)
 {
 	int count;
@@ -190,6 +190,6 @@
 }
 
-static int arp_clear_address_req(int arp_phone, device_id_t device_id,
-    services_t protocol, measured_string_t *address)
+static int arp_clear_address_req(device_id_t device_id, services_t protocol,
+    measured_string_t *address)
 {
 	fibril_mutex_lock(&arp_globals.lock);
@@ -218,5 +218,5 @@
 }
 
-static int arp_clear_device_req(int arp_phone, device_id_t device_id)
+static int arp_clear_device_req(device_id_t device_id)
 {
 	fibril_mutex_lock(&arp_globals.lock);
@@ -375,5 +375,5 @@
 				return rc;
 			
-			nil_send_msg(device->phone, device_id, packet,
+			nil_send_msg(device->sess, device_id, packet,
 			    SERVICE_ARP);
 			return 1;
@@ -416,7 +416,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -431,5 +432,5 @@
 		
 		case NET_IL_RECEIVED:
-			rc = packet_translate_remote(arp_globals.net_phone, &packet,
+			rc = packet_translate_remote(arp_globals.net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK) {
@@ -439,5 +440,5 @@
 					rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
 					if (rc != 1) {
-						pq_release_remote(arp_globals.net_phone,
+						pq_release_remote(arp_globals.net_sess,
 						    packet_get_id(packet));
 					}
@@ -564,8 +565,8 @@
 		
 		/* Bind */
-		device->phone = nil_bind_service(device->service,
+		device->sess = nil_bind_service(device->service,
 		    (sysarg_t) device->device_id, SERVICE_ARP,
 		    arp_receiver);
-		if (device->phone < 0) {
+		if (device->sess == NULL) {
 			fibril_mutex_unlock(&arp_globals.lock);
 			arp_protos_destroy(&device->protos, free);
@@ -575,5 +576,5 @@
 		
 		/* Get packet dimensions */
-		rc = nil_packet_size_req(device->phone, device_id,
+		rc = nil_packet_size_req(device->sess, device_id,
 		    &device->packet_dimension);
 		if (rc != EOK) {
@@ -585,5 +586,5 @@
 		
 		/* Get hardware address */
-		rc = nil_get_addr_req(device->phone, device_id, &device->addr,
+		rc = nil_get_addr_req(device->sess, device_id, &device->addr,
 		    &device->addr_data);
 		if (rc != EOK) {
@@ -595,5 +596,5 @@
 		
 		/* Get broadcast address */
-		rc = nil_get_broadcast_addr_req(device->phone, device_id,
+		rc = nil_get_broadcast_addr_req(device->sess, device_id,
 		    &device->broadcast_addr, &device->broadcast_data);
 		if (rc != EOK) {
@@ -627,10 +628,10 @@
 }
 
-int il_initialize(int net_phone)
+int il_initialize(async_sess_t *net_sess)
 {
 	fibril_mutex_initialize(&arp_globals.lock);
 	
 	fibril_mutex_lock(&arp_globals.lock);
-	arp_globals.net_phone = net_phone;
+	arp_globals.net_sess = net_sess;
 	int rc = arp_cache_initialize(&arp_globals.cache);
 	fibril_mutex_unlock(&arp_globals.lock);
@@ -647,5 +648,5 @@
 		return ELIMIT;
 	
-	packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
+	packet_t *packet = packet_get_4_remote(arp_globals.net_sess,
 	    device->packet_dimension.addr_len, device->packet_dimension.prefix,
 	    length, device->packet_dimension.suffix);
@@ -655,5 +656,5 @@
 	arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
 	if (!header) {
-		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
 		return ENOMEM;
 	}
@@ -680,9 +681,9 @@
 	    (uint8_t *) device->broadcast_addr->value, device->addr->length);
 	if (rc != EOK) {
-		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
 		return rc;
 	}
 	
-	nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
+	nil_send_msg(device->sess, device_id, packet, SERVICE_ARP);
 	return EOK;
 }
@@ -845,8 +846,9 @@
 	
 	*count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
 	case NET_ARP_DEVICE:
 		rc = measured_strings_receive(&address, &data, 1);
@@ -889,5 +891,5 @@
 	
 	case NET_ARP_CLEAR_DEVICE:
-		return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
+		return arp_clear_device_req(IPC_GET_DEVICE(*call));
 	
 	case NET_ARP_CLEAR_ADDRESS:
@@ -896,5 +898,5 @@
 			return rc;
 		
-		arp_clear_address_req(0, IPC_GET_DEVICE(*call),
+		arp_clear_address_req(IPC_GET_DEVICE(*call),
 		    IPC_GET_SERVICE(*call), address);
 		free(address);
@@ -903,5 +905,5 @@
 	
 	case NET_ARP_CLEAN_CACHE:
-		return arp_clean_cache_req(0);
+		return arp_clean_cache_req();
 	}
 	
Index: uspace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/il/arp/arp.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -38,4 +38,5 @@
 #define NET_ARP_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
@@ -104,6 +105,6 @@
 	/** Packet dimension. */
 	packet_dimension_t packet_dimension;
-	/** Device module phone. */
-	int phone;
+	/** Device module session. */
+	async_sess_t *sess;
 	
 	/**
@@ -122,6 +123,7 @@
 	arp_cache_t cache;
 	
-	/** Networking module phone. */
-	int net_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
+	
 	/** Safety lock. */
 	fibril_mutex_t lock;
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/il/ip/ip.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -120,35 +120,36 @@
 GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
 
-static void ip_receiver(ipc_callid_t, ipc_call_t *);
-
-/** Releases the packet and returns the result.
- *
- * @param[in] packet	The packet queue to be released.
- * @param[in] result	The result to be returned.
- * @return		The result parameter.
+static void ip_receiver(ipc_callid_t, ipc_call_t *, void *);
+
+/** Release the packet and returns the result.
+ *
+ * @param[in] packet Packet queue to be released.
+ * @param[in] result Result to be returned.
+ *
+ * @return Result parameter.
+ *
  */
 static int ip_release_and_return(packet_t *packet, int result)
 {
-	pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
 	return result;
 }
 
-/** Returns the ICMP phone.
- *
- * Searches the registered protocols.
- *
- * @return		The found ICMP phone.
- * @return		ENOENT if the ICMP is not registered.
- */
-static int ip_get_icmp_phone(void)
-{
-	ip_proto_t *proto;
-	int phone;
-
+/** Return the ICMP session.
+ *
+ * Search the registered protocols.
+ *
+ * @return Found ICMP session.
+ * @return NULL if the ICMP is not registered.
+ *
+ */
+static async_sess_t *ip_get_icmp_session(void)
+{
 	fibril_rwlock_read_lock(&ip_globals.protos_lock);
-	proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
-	phone = proto ? proto->phone : ENOENT;
+	ip_proto_t *proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
+	async_sess_t *sess = proto ? proto->sess : NULL;
 	fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-	return phone;
+	
+	return sess;
 }
 
@@ -179,5 +180,5 @@
 	next = pq_detach(packet);
 	if (next)
-		pq_release_remote(ip_globals.net_phone, packet_get_id(next));
+		pq_release_remote(ip_globals.net_sess, packet_get_id(next));
 
 	if (!header) {
@@ -201,5 +202,5 @@
 
 	/* Set the destination address */
-	switch (header->version) {
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(dest_in);
@@ -218,30 +219,33 @@
 }
 
-/** Prepares the ICMP notification packet.
- *
- * Releases additional packets and keeps only the first one.
+/** Prepare the ICMP notification packet.
+ *
+ * Release additional packets and keep only the first one.
  * All packets are released on error.
  *
- * @param[in] error	The packet error service.
- * @param[in] packet	The packet or the packet queue to be reported as faulty.
- * @param[in] header	The first packet IP header. May be NULL.
- * @return		The found ICMP phone.
- * @return		EINVAL if the error parameter is set.
- * @return		EINVAL if the ICMP phone is not found.
- * @return		EINVAL if the ip_prepare_icmp() fails.
- */
-static int
-ip_prepare_icmp_and_get_phone(services_t error, packet_t *packet,
-    ip_header_t *header)
-{
-	int phone;
-
-	phone = ip_get_icmp_phone();
-	if (error || (phone < 0) || ip_prepare_icmp(packet, header))
-		return ip_release_and_return(packet, EINVAL);
-	return phone;
-}
-
-int il_initialize(int net_phone)
+ * @param[in] error  Packet error service.
+ * @param[in] packet Packet or the packet queue to be reported as faulty.
+ * @param[in] header First packet IP header. May be NULL.
+ *
+ * @return Found ICMP session.
+ * @return NULL if the error parameter is set.
+ * @return NULL if the ICMP session is not found.
+ * @return NULL if the ip_prepare_icmp() fails.
+ *
+ */
+static async_sess_t *ip_prepare_icmp_and_get_session(services_t error,
+    packet_t *packet, ip_header_t *header)
+{
+	async_sess_t *sess = ip_get_icmp_session();
+	
+	if ((error) || (!sess) || (ip_prepare_icmp(packet, header))) {
+		pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
+		return NULL;
+	}
+	
+	return sess;
+}
+
+int il_initialize(async_sess_t *net_sess)
 {
 	fibril_rwlock_initialize(&ip_globals.lock);
@@ -250,5 +254,5 @@
 	fibril_rwlock_initialize(&ip_globals.netifs_lock);
 	
-	ip_globals.net_phone = net_phone;
+	ip_globals.net_sess = net_sess;
 	ip_globals.packet_counter = 0;
 	ip_globals.gateway.address.s_addr = 0;
@@ -352,5 +356,5 @@
 
 	/* Get configuration */
-	rc = net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id,
+	rc = net_get_device_conf_req(ip_globals.net_sess, ip_netif->device_id,
 	    &configuration, count, &data);
 	if (rc != EOK)
@@ -420,11 +424,11 @@
 
 	/* Bind netif service which also initializes the device */
-	ip_netif->phone = nil_bind_service(ip_netif->service,
+	ip_netif->sess = nil_bind_service(ip_netif->service,
 	    (sysarg_t) ip_netif->device_id, SERVICE_IP,
 	    ip_receiver);
-	if (ip_netif->phone < 0) {
+	if (ip_netif->sess == NULL) {
 		printf("Failed to contact the nil service %d\n",
 		    ip_netif->service);
-		return ip_netif->phone;
+		return ENOENT;
 	}
 
@@ -435,5 +439,5 @@
 			address.length = sizeof(in_addr_t);
 			
-			rc = arp_device_req(ip_netif->arp->phone,
+			rc = arp_device_req(ip_netif->arp->sess,
 			    ip_netif->device_id, SERVICE_IP, ip_netif->service,
 			    &address);
@@ -446,5 +450,5 @@
 
 	/* Get packet dimensions */
-	rc = nil_packet_size_req(ip_netif->phone, ip_netif->device_id,
+	rc = nil_packet_size_req(ip_netif->sess, ip_netif->device_id,
 	    &ip_netif->packet_dimension);
 	if (rc != EOK)
@@ -478,6 +482,5 @@
 }
 
-static int ip_device_req_local(int il_phone, device_id_t device_id,
-    services_t netif)
+static int ip_device_req_local(device_id_t device_id, services_t netif)
 {
 	ip_netif_t *ip_netif;
@@ -513,6 +516,6 @@
 
 	/* Print the settings */
-	printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
-	    NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
+	printf("%s: Device registered (id: %d, ipv: %d, conf: %s)\n",
+	    NAME, ip_netif->device_id, ip_netif->ipv,
 	    ip_netif->dhcp ? "dhcp" : "static");
 	
@@ -635,5 +638,5 @@
 
 	/* Process all IP options */
-	while (next < first->header_length) {
+	while (next < GET_IP_HEADER_LENGTH(first)) {
 		option = (ip_option_t *) (((uint8_t *) first) + next);
 		/* Skip end or noop */
@@ -656,7 +659,7 @@
 	if (length % 4) {
 		bzero(((uint8_t *) last) + length, 4 - (length % 4));
-		last->header_length = length / 4 + 1;
+		SET_IP_HEADER_LENGTH(last, (length / 4 + 1));
 	} else {
-		last->header_length = length / 4;
+		SET_IP_HEADER_LENGTH(last, (length / 4));
 	}
 
@@ -706,6 +709,6 @@
 		return rc;
 	
-	header->version = IPV4;
-	header->fragment_offset_high = 0;
+	SET_IP_HEADER_VERSION(header, IPV4);
+	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, 0);
 	header->fragment_offset_low = 0;
 	header->header_checksum = 0;
@@ -735,9 +738,10 @@
 			memcpy(middle_header, last_header,
 			    IP_HEADER_LENGTH(last_header));
-			header->flags |= IPFLAG_MORE_FRAGMENTS;
+			SET_IP_HEADER_FLAGS(header,
+			    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
 			middle_header->total_length =
 			    htons(packet_get_data_length(next));
-			middle_header->fragment_offset_high =
-			    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
+			SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
+			    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
 			middle_header->fragment_offset_low =
 			    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
@@ -768,6 +772,6 @@
 		middle_header->total_length =
 		    htons(packet_get_data_length(next));
-		middle_header->fragment_offset_high =
-		    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
+		SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
+		    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
 		middle_header->fragment_offset_low =
 		    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
@@ -785,5 +789,6 @@
 		length += packet_get_data_length(next);
 		free(last_header);
-		header->flags |= IPFLAG_MORE_FRAGMENTS;
+		SET_IP_HEADER_FLAGS(header,
+		    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
 	}
 
@@ -834,6 +839,6 @@
 	new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
 	offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
-	new_header->fragment_offset_high =
-	    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
+	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(new_header,
+	    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset));
 	new_header->fragment_offset_low =
 	    IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
@@ -865,5 +870,6 @@
 		return NULL;
 	memcpy(middle, last, IP_HEADER_LENGTH(last));
-	middle->flags |= IPFLAG_MORE_FRAGMENTS;
+	SET_IP_HEADER_FLAGS(middle,
+	    (GET_IP_HEADER_FLAGS(middle) | IPFLAG_MORE_FRAGMENTS));
 	return middle;
 }
@@ -922,9 +928,9 @@
 
 	/* Fragmentation forbidden? */
-	if(header->flags & IPFLAG_DONT_FRAGMENT)
+	if(GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT)
 		return EPERM;
 
 	/* Create the last fragment */
-	new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
+	new_packet = packet_get_4_remote(ip_globals.net_sess, prefix, length,
 	    suffix, ((addrlen > addr_len) ? addrlen : addr_len));
 	if (!new_packet)
@@ -958,9 +964,10 @@
 
 	/* Mark the first as fragmented */
-	header->flags |= IPFLAG_MORE_FRAGMENTS;
+	SET_IP_HEADER_FLAGS(header,
+	    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
 
 	/* Create middle fragments */
 	while (IP_TOTAL_LENGTH(header) > length) {
-		new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
+		new_packet = packet_get_4_remote(ip_globals.net_sess, prefix,
 		    length, suffix,
 		    ((addrlen >= addr_len) ? addrlen : addr_len));
@@ -987,21 +994,22 @@
 }
 
-/** Checks the packet queue lengths and fragments the packets if needed.
+/** Check the packet queue lengths and fragments the packets if needed.
  *
  * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
  * be fragmented and the fragmentation is not allowed.
  *
- * @param[in,out] packet The packet or the packet queue to be checked.
- * @param[in] prefix	The minimum prefix size.
- * @param[in] content	The maximum content size.
- * @param[in] suffix	The minimum suffix size.
- * @param[in] addr_len	The minimum address length.
- * @param[in] error	The error module service.
- * @return		The packet or the packet queue of the allowed length.
- * @return		NULL if there are no packets left.
- */
-static packet_t *
-ip_split_packet(packet_t *packet, size_t prefix, size_t content, size_t suffix,
-    socklen_t addr_len, services_t error)
+ * @param[in,out] packet   Packet or the packet queue to be checked.
+ * @param[in]     prefix   Minimum prefix size.
+ * @param[in]     content  Maximum content size.
+ * @param[in]     suffix   Minimum suffix size.
+ * @param[in]     addr_len Minimum address length.
+ * @param[in]     error    Error module service.
+ *
+ * @return The packet or the packet queue of the allowed length.
+ * @return NULL if there are no packets left.
+ *
+ */
+static packet_t *ip_split_packet(packet_t *packet, size_t prefix, size_t content,
+    size_t suffix, socklen_t addr_len, services_t error)
 {
 	size_t length;
@@ -1009,6 +1017,6 @@
 	packet_t *new_packet;
 	int result;
-	int phone;
-
+	async_sess_t *sess;
+	
 	next = packet;
 	/* Check all packets */
@@ -1032,13 +1040,12 @@
 			/* Fragmentation needed? */
 			if (result == EPERM) {
-				phone = ip_prepare_icmp_and_get_phone(
-				    error, next, NULL);
-				if (phone >= 0) {
+				sess = ip_prepare_icmp_and_get_session(error, next, NULL);
+				if (sess) {
 					/* Fragmentation necessary ICMP */
-					icmp_destination_unreachable_msg(phone,
+					icmp_destination_unreachable_msg(sess,
 					    ICMP_FRAG_NEEDED, content, next);
 				}
 			} else {
-				pq_release_remote(ip_globals.net_phone,
+				pq_release_remote(ip_globals.net_sess,
 				    packet_get_id(next));
 			}
@@ -1054,20 +1061,20 @@
 }
 
-/** Sends the packet or the packet queue via the specified route.
+/** Send the packet or the packet queue via the specified route.
  *
  * The ICMP_HOST_UNREACH error notification may be sent if route hardware
  * destination address is found.
  *
- * @param[in,out] packet The packet to be sent.
- * @param[in] netif	The target network interface.
- * @param[in] route	The target route.
- * @param[in] src	The source address.
- * @param[in] dest	The destination address.
- * @param[in] error	The error module service.
- * @return		EOK on success.
- * @return		Other error codes as defined for the arp_translate_req()
- *			function.
- * @return		Other error codes as defined for the ip_prepare_packet()
- *			function.
+ * @param[in,out] packet Packet to be sent.
+ * @param[in]     netif  Target network interface.
+ * @param[in]     route  Target route.
+ * @param[in]     src    Source address.
+ * @param[in]     dest   Destination address.
+ * @param[in]     error  Error module service.
+ *
+ * @return EOK on success.
+ * @return Other error codes as defined for arp_translate_req().
+ * @return Other error codes as defined for ip_prepare_packet().
+ *
  */
 static int ip_send_route(packet_t *packet, ip_netif_t *netif,
@@ -1077,5 +1084,5 @@
 	measured_string_t *translation;
 	uint8_t *data;
-	int phone;
+	async_sess_t *sess;
 	int rc;
 
@@ -1086,8 +1093,8 @@
 		destination.length = sizeof(dest.s_addr);
 
-		rc = arp_translate_req(netif->arp->phone, netif->device_id,
+		rc = arp_translate_req(netif->arp->sess, netif->device_id,
 		    SERVICE_IP, &destination, &translation, &data);
 		if (rc != EOK) {
-			pq_release_remote(ip_globals.net_phone,
+			pq_release_remote(ip_globals.net_sess,
 			    packet_get_id(packet));
 			return rc;
@@ -1099,9 +1106,9 @@
 				free(data);
 			}
-			phone = ip_prepare_icmp_and_get_phone(error, packet,
+			sess = ip_prepare_icmp_and_get_session(error, packet,
 			    NULL);
-			if (phone >= 0) {
+			if (sess) {
 				/* Unreachable ICMP if no routing */
-				icmp_destination_unreachable_msg(phone,
+				icmp_destination_unreachable_msg(sess,
 				    ICMP_HOST_UNREACH, 0, packet);
 			}
@@ -1115,5 +1122,5 @@
 	rc = ip_prepare_packet(src, dest, packet, translation);
 	if (rc != EOK) {
-		pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
 	} else {
 		packet = ip_split_packet(packet, netif->packet_dimension.prefix,
@@ -1122,5 +1129,5 @@
 		    netif->packet_dimension.addr_len, error);
 		if (packet) {
-			nil_send_msg(netif->phone, netif->device_id, packet,
+			nil_send_msg(netif->sess, netif->device_id, packet,
 			    SERVICE_IP);
 		}
@@ -1135,6 +1142,6 @@
 }
 
-static int ip_send_msg_local(int il_phone, device_id_t device_id,
-    packet_t *packet, services_t sender, services_t error)
+static int ip_send_msg_local(device_id_t device_id, packet_t *packet,
+    services_t sender, services_t error)
 {
 	int addrlen;
@@ -1145,5 +1152,5 @@
 	in_addr_t *dest;
 	in_addr_t *src;
-	int phone;
+	async_sess_t *sess;
 	int rc;
 
@@ -1190,8 +1197,8 @@
 	if (!netif || !route) {
 		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-		phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
-		if (phone >= 0) {
+		sess = ip_prepare_icmp_and_get_session(error, packet, NULL);
+		if (sess) {
 			/* Unreachable ICMP if no routing */
-			icmp_destination_unreachable_msg(phone,
+			icmp_destination_unreachable_msg(sess,
 			    ICMP_NET_UNREACH, 0, packet);
 		}
@@ -1221,9 +1228,9 @@
 		if (!netif || !route) {
 			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-			phone = ip_prepare_icmp_and_get_phone(error, packet,
+			sess = ip_prepare_icmp_and_get_session(error, packet,
 			    NULL);
-			if (phone >= 0) {
+			if (sess) {
 				/* Unreachable ICMP if no routing */
-				icmp_destination_unreachable_msg(phone,
+				icmp_destination_unreachable_msg(sess,
 				    ICMP_HOST_UNREACH, 0, packet);
 			}
@@ -1309,5 +1316,5 @@
 {
 	ip_proto_t *proto;
-	int phone;
+	async_sess_t *sess;
 	services_t service;
 	tl_received_msg_t received_msg;
@@ -1319,5 +1326,5 @@
 	int rc;
 
-	if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
+	if ((GET_IP_HEADER_FLAGS(header) & IPFLAG_MORE_FRAGMENTS) ||
 	    IP_FRAGMENT_OFFSET(header)) {
 		// TODO fragmented
@@ -1325,5 +1332,5 @@
 	}
 	
-	switch (header->version) {
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(src_in);
@@ -1362,8 +1369,8 @@
 	if (!proto) {
 		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-		phone = ip_prepare_icmp_and_get_phone(error, packet, header);
-		if (phone >= 0) {
+		sess = ip_prepare_icmp_and_get_session(error, packet, header);
+		if (sess) {
 			/* Unreachable ICMP */
-			icmp_destination_unreachable_msg(phone,
+			icmp_destination_unreachable_msg(sess,
 			    ICMP_PROT_UNREACH, 0, packet);
 		}
@@ -1377,5 +1384,5 @@
 		rc = received_msg(device_id, packet, service, error);
 	} else {
-		rc = tl_received_msg(proto->phone, device_id, packet,
+		rc = tl_received_msg(proto->sess, device_id, packet,
 		    proto->service, error);
 		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
@@ -1411,5 +1418,5 @@
 	in_addr_t dest;
 	ip_route_t *route;
-	int phone;
+	async_sess_t *sess;
 	struct sockaddr *addr;
 	struct sockaddr_in addr_in;
@@ -1424,8 +1431,8 @@
 	if ((header->header_checksum) &&
 	    (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
+		sess = ip_prepare_icmp_and_get_session(0, packet, header);
+		if (sess) {
 			/* Checksum error ICMP */
-			icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
+			icmp_parameter_problem_msg(sess, ICMP_PARAM_POINTER,
 			    ((size_t) ((void *) &header->header_checksum)) -
 			    ((size_t) ((void *) header)), packet);
@@ -1435,8 +1442,8 @@
 
 	if (header->ttl <= 1) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
+		sess = ip_prepare_icmp_and_get_session(0, packet, header);
+		if (sess) {
 			/* TTL exceeded ICMP */
-			icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
+			icmp_time_exceeded_msg(sess, ICMP_EXC_TTL, packet);
 		}
 		return EINVAL;
@@ -1447,5 +1454,5 @@
 
 	/* Set the destination address */
-	switch (header->version) {
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(addr_in);
@@ -1466,8 +1473,8 @@
 	route = ip_find_route(dest);
 	if (!route) {
-		phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-		if (phone >= 0) {
+		sess = ip_prepare_icmp_and_get_session(0, packet, header);
+		if (sess) {
 			/* Unreachable ICMP */
-			icmp_destination_unreachable_msg(phone,
+			icmp_destination_unreachable_msg(sess,
 			    ICMP_HOST_UNREACH, 0, packet);
 		}
@@ -1486,8 +1493,8 @@
 	}
 
-	phone = ip_prepare_icmp_and_get_phone(0, packet, header);
-	if (phone >= 0) {
+	sess = ip_prepare_icmp_and_get_session(0, packet, header);
+	if (sess) {
 		/* Unreachable ICMP if no routing */
-		icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
+		icmp_destination_unreachable_msg(sess, ICMP_HOST_UNREACH, 0,
 		    packet);
 	}
@@ -1496,14 +1503,14 @@
 }
 
-/** Returns the device packet dimensions for sending.
- *
- * @param[in] phone	The service module phone.
- * @param[in] message	The service specific message.
- * @param[in] device_id	The device identifier.
- * @param[out] addr_len	The minimum reserved address length.
- * @param[out] prefix	The minimum reserved prefix size.
- * @param[out] content	The maximum content size.
- * @param[out] suffix	The minimum reserved suffix size.
- * @return		EOK on success.
+/** Return the device packet dimensions for sending.
+ *
+ * @param[in]  device_id Device identifier.
+ * @param[out] addr_len  Minimum reserved address length.
+ * @param[out] prefix    Minimum reserved prefix size.
+ * @param[out] content   Maximum content size.
+ * @param[out] suffix    Minimum reserved suffix size.
+ *
+ * @return EOK on success.
+ *
  */
 static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
@@ -1587,7 +1594,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -1603,5 +1611,5 @@
 		
 		case NET_IL_RECEIVED:
-			rc = packet_translate_remote(ip_globals.net_phone, &packet,
+			rc = packet_translate_remote(ip_globals.net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK) {
@@ -1630,22 +1638,23 @@
 }
 
-/** Registers the transport layer protocol.
+/** Register the transport layer protocol.
  *
  * The traffic of this protocol will be supplied using either the receive
  * function or IPC message.
  *
- * @param[in] protocol	The transport layer module protocol.
- * @param[in] service	The transport layer module service.
- * @param[in] phone	The transport layer module phone.
- * @param[in] received_msg The receiving function.
- * @return		EOK on success.
- * @return		EINVAL if the protocol parameter and/or the service
- *			parameter is zero.
- * @return		EINVAL if the phone parameter is not a positive number
- *			and the tl_receive_msg is NULL.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int
-ip_register(int protocol, services_t service, int phone,
+ * @param[in] protocol     Transport layer module protocol.
+ * @param[in] service      Transport layer module service.
+ * @param[in] sess         Transport layer module session.
+ * @param[in] received_msg Receiving function.
+ *
+ * @return EOK on success.
+ * @return EINVAL if the protocol parameter and/or the service
+ *         parameter is zero.
+ * @return EINVAL if the phone parameter is not a positive number
+ *         and the tl_receive_msg is NULL.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+static int ip_register(int protocol, services_t service, async_sess_t *sess,
     tl_received_msg_t received_msg)
 {
@@ -1653,7 +1662,7 @@
 	int index;
 
-	if (!protocol || !service || ((phone < 0) && !received_msg))
+	if ((!protocol) || (!service) || ((!sess) && (!received_msg)))
 		return EINVAL;
-
+	
 	proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
 	if (!proto)
@@ -1662,5 +1671,5 @@
 	proto->protocol = protocol;
 	proto->service = service;
-	proto->phone = phone;
+	proto->sess = sess;
 	proto->received_msg = received_msg;
 
@@ -1674,13 +1683,11 @@
 	fibril_rwlock_write_unlock(&ip_globals.protos_lock);
 
-	printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
-	    NAME, proto->protocol, proto->phone);
+	printf("%s: Protocol registered (protocol: %d)\n",
+	    NAME, proto->protocol);
 
 	return EOK;
 }
 
-
-static int
-ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
+static int ip_add_route_req_local(device_id_t device_id, in_addr_t address,
     in_addr_t netmask, in_addr_t gateway)
 {
@@ -1716,6 +1723,5 @@
 }
 
-static int
-ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
+static int ip_set_gateway_req_local(device_id_t device_id, in_addr_t gateway)
 {
 	ip_netif_t *netif;
@@ -1741,16 +1747,15 @@
 /** Notify the IP module about the received error notification packet.
  *
- * @param[in] ip_phone	The IP module phone used for (semi)remote calls.
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The received packet or the received packet queue.
- * @param[in] target	The target internetwork module service to be
- *			delivered to.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- *
- */
-static int
-ip_received_error_msg_local(int ip_phone, device_id_t device_id,
+ * @param[in] device_id Device identifier.
+ * @param[in] packet    Received packet or the received packet queue.
+ * @param[in] target    Target internetwork module service to be
+ *                      delivered to.
+ * @param[in] error     Packet error reporting service. Prefixes the
+ *                      received packet.
+ *
+ * @return EOK on success.
+ *
+ */
+static int ip_received_error_msg_local(device_id_t device_id,
     packet_t *packet, services_t target, services_t error)
 {
@@ -1797,5 +1802,5 @@
 			address.value = (uint8_t *) &header->destination_address;
 			address.length = sizeof(header->destination_address);
-			arp_clear_address_req(netif->arp->phone,
+			arp_clear_address_req(netif->arp->sess,
 			    netif->device_id, SERVICE_IP, &address);
 		}
@@ -1811,6 +1816,5 @@
 }
 
-static int
-ip_get_route_req_local(int ip_phone, ip_protocol_t protocol,
+static int ip_get_route_req_local(ip_protocol_t protocol,
     const struct sockaddr *destination, socklen_t addrlen,
     device_id_t *device_id, void **header, size_t *headerlen)
@@ -1909,31 +1913,34 @@
 	
 	*answer_count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
+		    callback, NULL);
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
-	case IPC_M_CONNECT_TO_ME:
-		return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
-		    IPC_GET_PHONE(*call), NULL);
-	
 	case NET_IP_DEVICE:
-		return ip_device_req_local(0, IPC_GET_DEVICE(*call),
+		return ip_device_req_local(IPC_GET_DEVICE(*call),
 		    IPC_GET_SERVICE(*call));
 	
 	case NET_IP_RECEIVED_ERROR:
-		rc = packet_translate_remote(ip_globals.net_phone, &packet,
+		rc = packet_translate_remote(ip_globals.net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
-		return ip_received_error_msg_local(0, IPC_GET_DEVICE(*call),
+		return ip_received_error_msg_local(IPC_GET_DEVICE(*call),
 		    packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
 	
 	case NET_IP_ADD_ROUTE:
-		return ip_add_route_req_local(0, IPC_GET_DEVICE(*call),
+		return ip_add_route_req_local(IPC_GET_DEVICE(*call),
 		    IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
 		    IP_GET_GATEWAY(*call));
 
 	case NET_IP_SET_GATEWAY:
-		return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call),
+		return ip_set_gateway_req_local(IPC_GET_DEVICE(*call),
 		    IP_GET_GATEWAY(*call));
 
@@ -1944,5 +1951,5 @@
 			return rc;
 		
-		rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(*call), addr,
+		rc = ip_get_route_req_local(IP_GET_PROTOCOL(*call), addr,
 		    (socklen_t) addrlen, &device_id, &header, &headerlen);
 		if (rc != EOK)
@@ -1975,10 +1982,10 @@
 	
 	case NET_IP_SEND:
-		rc = packet_translate_remote(ip_globals.net_phone, &packet,
+		rc = packet_translate_remote(ip_globals.net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
 			return rc;
 		
-		return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
+		return ip_send_msg_local(IPC_GET_DEVICE(*call), packet, 0,
 		    IPC_GET_ERROR(*call));
 	}
Index: uspace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/il/ip/ip.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -38,4 +38,5 @@
 #define NET_IP_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
@@ -98,6 +99,6 @@
 	/** Packet dimension. */
 	packet_dimension_t packet_dimension;
-	/** Netif module phone. */
-	int phone;
+	/** Netif module session. */
+	async_sess_t *sess;
 	/** Routing table. */
 	ip_routes_t routes;
@@ -112,6 +113,6 @@
 /** IP protocol specific data. */
 struct ip_proto {
-	/** Protocol module phone. */
-	int phone;
+	/** Protocol module session. */
+	async_sess_t *sess;
 	/** Protocol number. */
 	int protocol;
@@ -142,6 +143,6 @@
 	/** Known support modules. */
 	modules_t modules;
-	/** Networking module phone. */
-	int net_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
 	/** Registered network interfaces. */
 	ip_netifs_t netifs;
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/net/net.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -36,6 +36,4 @@
  */
 
-#include "net.h"
-
 #include <async.h>
 #include <ctype.h>
@@ -46,5 +44,5 @@
 #include <str.h>
 #include <str_error.h>
-
+#include <ns.h>
 #include <ipc/services.h>
 #include <ipc/net.h>
@@ -52,18 +50,16 @@
 #include <ipc/il.h>
 #include <ipc/nil.h>
-
 #include <net/modules.h>
 #include <net/packet.h>
 #include <net/device.h>
-
 #include <adt/char_map.h>
 #include <adt/generic_char_map.h>
 #include <adt/measured_strings.h>
 #include <adt/module_map.h>
-
 #include <netif_remote.h>
 #include <nil_remote.h>
 #include <net_interface.h>
 #include <ip_interface.h>
+#include "net.h"
 
 /** Networking module name. */
@@ -339,5 +335,5 @@
 		goto out;
 	
-	rc = async_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, NULL);
+	rc = service_register(SERVICE_NETWORKING);
 	if (rc != EOK)
 		goto out;
@@ -393,5 +389,5 @@
 }
 
-int net_get_conf_req(int net_phone, measured_string_t **configuration,
+static int net_get_conf_req_local(measured_string_t **configuration,
     size_t count, uint8_t **data)
 {
@@ -402,5 +398,5 @@
 }
 
-int net_get_device_conf_req(int net_phone, device_id_t device_id,
+static int net_get_device_conf_req_local(device_id_t device_id,
     measured_string_t **configuration, size_t count, uint8_t **data)
 {
@@ -478,5 +474,5 @@
 	uintptr_t io = setting ? strtol((char *) setting->value, NULL, 16) : 0;
 	
-	rc = netif_probe_req(netif->driver->phone, netif->id, irq, (void *) io);
+	rc = netif_probe_req(netif->driver->sess, netif->id, irq, (void *) io);
 	if (rc != EOK)
 		return rc;
@@ -491,6 +487,5 @@
 		
 		int mtu = setting ? strtol((char *) setting->value, NULL, 10) : 0;
-		
-		rc = nil_device_req(netif->nil->phone, netif->id, mtu,
+		rc = nil_device_req(netif->nil->sess, netif->id, mtu,
 		    netif->driver->service);
 		if (rc != EOK)
@@ -502,16 +497,9 @@
 	
 	/* Inter-network layer startup */
-	switch (netif->il->service) {
-	case SERVICE_IP:
-		rc = ip_device_req(netif->il->phone, netif->id,
-		    internet_service);
-		if (rc != EOK)
-			return rc;
-		break;
-	default:
-		return ENOENT;
-	}
-	
-	return netif_start_req(netif->driver->phone, netif->id);
+	rc = ip_device_req(netif->il->sess, netif->id, internet_service);
+	if (rc != EOK)
+		return rc;
+	
+	return netif_start_req(netif->driver->sess, netif->id);
 }
 
@@ -638,7 +626,9 @@
 	
 	*answer_count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
 	case NET_NET_GET_DEVICE_CONF:
 		rc = measured_strings_receive(&strings, &data,
@@ -646,5 +636,5 @@
 		if (rc != EOK)
 			return rc;
-		net_get_device_conf_req(0, IPC_GET_DEVICE(*call), &strings,
+		net_get_device_conf_req_local(IPC_GET_DEVICE(*call), &strings,
 		    IPC_GET_COUNT(*call), NULL);
 		
@@ -660,5 +650,5 @@
 		if (rc != EOK)
 			return rc;
-		net_get_conf_req(0, &strings, IPC_GET_COUNT(*call), NULL);
+		net_get_conf_req_local(&strings, IPC_GET_COUNT(*call), NULL);
 		
 		/* Strings should not contain received data anymore */
@@ -677,9 +667,11 @@
 /** Default thread for new connections.
  *
- * @param[in] iid The initial message identifier.
+ * @param[in] iid   The initial message identifier.
  * @param[in] icall The initial message call structure.
- *
- */
-static void net_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in] arg   Local argument.
+ *
+ */
+static void net_client_connection(ipc_callid_t iid, ipc_call_t *icall,
+    void *arg)
 {
 	/*
@@ -703,5 +695,5 @@
 		
 		/* End if told to either by the message or the processing result */
-		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
+		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
 			return;
 		
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/netif/lo/lo.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -39,4 +39,5 @@
 #include <stdio.h>
 #include <str.h>
+#include <ns.h>
 #include <ipc/services.h>
 #include <ipc/nil.h>
@@ -147,5 +148,4 @@
 	null_device_stats((device_stats_t *) (*device)->specific);
 	(*device)->device_id = device_id;
-	(*device)->nil_phone = -1;
 	(*device)->state = NETIF_STOPPED;
 	int index = netif_device_map_add(&netif_globals.device_map,
@@ -164,5 +164,5 @@
 int netif_initialize(void)
 {
-	return async_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, NULL);
+	return service_register(SERVICE_LO);
 }
 
@@ -201,8 +201,8 @@
 	} while (next);
 	
-	int phone = device->nil_phone;
+	async_sess_t *nil_sess = netif_globals.nil_sess;
 	fibril_rwlock_write_unlock(&netif_globals.lock);
 	
-	nil_received_msg(phone, device_id, packet, sender);
+	nil_received_msg(nil_sess, device_id, packet, sender);
 	
 	fibril_rwlock_write_lock(&netif_globals.lock);
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/nil/eth/eth.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -59,5 +59,4 @@
 #include <packet_remote.h>
 #include <nil_skel.h>
-
 #include "eth.h"
 
@@ -168,5 +167,5 @@
 INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
 
-int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
+int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
 {
 	int index;
@@ -177,6 +176,6 @@
 	    index--) {
 		proto = eth_protos_get_index(&eth_globals.protos, index);
-		if (proto && proto->phone) {
-			il_device_state_msg(proto->phone, device_id, state,
+		if ((proto) && (proto->sess)) {
+			il_device_state_msg(proto->sess, device_id, state,
 			    proto->service);
 		}
@@ -187,5 +186,5 @@
 }
 
-int nil_initialize(int net_phone)
+int nil_initialize(async_sess_t *sess)
 {
 	int rc;
@@ -196,5 +195,5 @@
 	fibril_rwlock_write_lock(&eth_globals.devices_lock);
 	fibril_rwlock_write_lock(&eth_globals.protos_lock);
-	eth_globals.net_phone = net_phone;
+	eth_globals.net_sess = sess;
 
 	eth_globals.broadcast_addr =
@@ -223,11 +222,13 @@
 }
 
-/** Processes IPC messages from the registered device driver modules in an
+/** Process IPC messages from the registered device driver modules in an
  * infinite loop.
  *
- * @param[in] iid	The message identifier.
- * @param[in,out] icall	The message parameters.
- */
-static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     iid   Message identifier.
+ * @param[in,out] icall Message parameters.
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void eth_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -237,14 +238,14 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_NIL_DEVICE_STATE:
-			nil_device_state_msg_local(0, IPC_GET_DEVICE(*icall),
+			nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
 			    IPC_GET_STATE(*icall));
 			async_answer_0(iid, EOK);
 			break;
 		case NET_NIL_RECEIVED:
-			rc = packet_translate_remote(eth_globals.net_phone,
+			rc = packet_translate_remote(eth_globals.net_sess,
 			    &packet, IPC_GET_PACKET(*icall));
 			if (rc == EOK)
-				rc = nil_received_msg_local(0,
-				    IPC_GET_DEVICE(*icall), packet, 0);
+				rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
+				    packet, 0);
 			
 			async_answer_0(iid, (sysarg_t) rc);
@@ -322,6 +323,6 @@
 			proto = eth_protos_get_index(&eth_globals.protos,
 			    index);
-			if (proto->phone) {
-				il_mtu_changed_msg(proto->phone,
+			if (proto->sess) {
+				il_mtu_changed_msg(proto->sess,
 				    device->device_id, device->mtu,
 				    proto->service);
@@ -347,5 +348,5 @@
 
 	configuration = &names[0];
-	rc = net_get_device_conf_req(eth_globals.net_phone, device->device_id,
+	rc = net_get_device_conf_req(eth_globals.net_sess, device->device_id,
 	    &configuration, count, &data);
 	if (rc != EOK) {
@@ -376,14 +377,14 @@
 	
 	/* Bind the device driver */
-	device->phone = netif_bind_service(device->service, device->device_id,
+	device->sess = netif_bind_service(device->service, device->device_id,
 	    SERVICE_ETHERNET, eth_receiver);
-	if (device->phone < 0) {
+	if (device->sess == NULL) {
 		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
 		free(device);
-		return device->phone;
+		return ENOENT;
 	}
 	
 	/* Get hardware address */
-	rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,
+	rc = netif_get_addr_req(device->sess, device->device_id, &device->addr,
 	    &device->addr_data);
 	if (rc != EOK) {
@@ -505,6 +506,6 @@
 }
 
-int nil_received_msg_local(int nil_phone, device_id_t device_id,
-    packet_t *packet, services_t target)
+int nil_received_msg_local(device_id_t device_id, packet_t *packet,
+    services_t target)
 {
 	eth_proto_t *proto;
@@ -528,9 +529,9 @@
 		proto = eth_process_packet(flags, packet);
 		if (proto) {
-			il_received_msg(proto->phone, device_id, packet,
+			il_received_msg(proto->sess, device_id, packet,
 			    proto->service);
 		} else {
 			/* Drop invalid/unknown */
-			pq_release_remote(eth_globals.net_phone,
+			pq_release_remote(eth_globals.net_sess,
 			    packet_get_id(packet));
 		}
@@ -611,15 +612,17 @@
 }
 
-/** Registers receiving module service.
- *
- * Passes received packets for this service.
- *
- * @param[in] service	The module service.
- * @param[in] phone	The service phone.
- * @return		EOK on success.
- * @return		ENOENT if the service is not known.
- * @return		ENOMEM if there is not enough memory left.
- */
-static int eth_register_message(services_t service, int phone)
+/** Register receiving module service.
+ *
+ * Pass received packets for this service.
+ *
+ * @param[in] service Module service.
+ * @param[in] sess    Service session.
+ *
+ * @return EOK on success.
+ * @return ENOENT if the service is not known.
+ * @return ENOMEM if there is not enough memory left.
+ *
+ */
+static int eth_register_message(services_t service, async_sess_t *sess)
 {
 	eth_proto_t *proto;
@@ -634,5 +637,5 @@
 	proto = eth_protos_find(&eth_globals.protos, protocol);
 	if (proto) {
-		proto->phone = phone;
+		proto->sess = sess;
 		fibril_rwlock_write_unlock(&eth_globals.protos_lock);
 		return EOK;
@@ -646,5 +649,5 @@
 		proto->service = service;
 		proto->protocol = protocol;
-		proto->phone = phone;
+		proto->sess = sess;
 
 		index = eth_protos_add(&eth_globals.protos, protocol, proto);
@@ -656,6 +659,6 @@
 	}
 	
-	printf("%s: Protocol registered (protocol: %d, service: %d, phone: "
-	    "%d)\n", NAME, proto->protocol, proto->service, proto->phone);
+	printf("%s: Protocol registered (protocol: %d, service: %d)\n",
+	    NAME, proto->protocol, proto->service);
 	
 	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
@@ -795,5 +798,5 @@
 	ethertype = htons(protocol_map(SERVICE_ETHERNET, sender));
 	if (!ethertype) {
-		pq_release_remote(eth_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
 		return EINVAL;
 	}
@@ -816,5 +819,5 @@
 			if (next == packet)
 				packet = tmp;
-			pq_release_remote(eth_globals.net_phone,
+			pq_release_remote(eth_globals.net_sess,
 			    packet_get_id(next));
 			next = tmp;
@@ -826,5 +829,5 @@
 	/* Send packet queue */
 	if (packet) {
-		netif_send_msg(device->phone, device_id, packet,
+		netif_send_msg(device->sess, device_id, packet,
 		    SERVICE_ETHERNET);
 	}
@@ -846,13 +849,19 @@
 	
 	*answer_count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return eth_register_message(NIL_GET_PROTO(*call), callback);
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
 	case NET_NIL_DEVICE:
 		return eth_device_message(IPC_GET_DEVICE(*call),
 		    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
 	case NET_NIL_SEND:
-		rc = packet_translate_remote(eth_globals.net_phone, &packet,
+		rc = packet_translate_remote(eth_globals.net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -883,7 +892,4 @@
 			return EOK;
 		return measured_strings_reply(address, 1);
-	case IPC_M_CONNECT_TO_ME:
-		return eth_register_message(NIL_GET_PROTO(*call),
-		    IPC_GET_PHONE(*call));
 	}
 	
Index: uspace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/nil/eth/eth.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -38,7 +38,7 @@
 #define NET_ETH_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <adt/measured_strings.h>
@@ -223,6 +223,6 @@
 	/** Device driver service. */
 	services_t service;
-	/** Driver phone. */
-	int phone;
+	/** Driver session. */
+	async_sess_t *sess;
 	/** Maximal transmission unit. */
 	size_t mtu;
@@ -248,12 +248,12 @@
 	/** Protocol identifier. */
 	int protocol;
-	/** Protocol module phone. */
-	int phone;
+	/** Protocol module session. */
+	async_sess_t *sess;
 };
 
 /** Ethernet global data. */
 struct eth_globals {
-	/** Networking module phone. */
-	int net_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
 	/** Safety lock for devices. */
 	fibril_rwlock_t devices_lock;
@@ -265,5 +265,5 @@
 	/**
 	 * Protocol map.
-	 * Service phone map for each protocol.
+	 * Service map for each protocol.
 	 */
 	eth_protos_t protos;
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -44,5 +44,4 @@
 #include <ipc/net.h>
 #include <ipc/services.h>
-
 #include <net/modules.h>
 #include <net/device.h>
@@ -53,5 +52,4 @@
 #include <netif_remote.h>
 #include <nil_skel.h>
-
 #include "nildummy.h"
 
@@ -67,9 +65,9 @@
 DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
 
-int nil_device_state_msg_local(int nil_phone, device_id_t device_id, int state)
+int nil_device_state_msg_local(device_id_t device_id, sysarg_t state)
 {
 	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-	if (nildummy_globals.proto.phone)
-		il_device_state_msg(nildummy_globals.proto.phone, device_id,
+	if (nildummy_globals.proto.sess)
+		il_device_state_msg(nildummy_globals.proto.sess, device_id,
 		    state, nildummy_globals.proto.service);
 	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
@@ -78,5 +76,5 @@
 }
 
-int nil_initialize(int net_phone)
+int nil_initialize(async_sess_t *sess)
 {
 	fibril_rwlock_initialize(&nildummy_globals.devices_lock);
@@ -85,6 +83,6 @@
 	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
 	
-	nildummy_globals.net_phone = net_phone;
-	nildummy_globals.proto.phone = 0;
+	nildummy_globals.net_sess = sess;
+	nildummy_globals.proto.sess = NULL;
 	int rc = nildummy_devices_initialize(&nildummy_globals.devices);
 	
@@ -99,7 +97,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     arg    Local argument.
+ *
+ */
+static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -109,15 +108,15 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_NIL_DEVICE_STATE:
-			rc = nil_device_state_msg_local(0,
-			    IPC_GET_DEVICE(*icall), IPC_GET_STATE(*icall));
+			rc = nil_device_state_msg_local(IPC_GET_DEVICE(*icall),
+			    IPC_GET_STATE(*icall));
 			async_answer_0(iid, (sysarg_t) rc);
 			break;
 		
 		case NET_NIL_RECEIVED:
-			rc = packet_translate_remote(nildummy_globals.net_phone,
+			rc = packet_translate_remote(nildummy_globals.net_sess,
 			    &packet, IPC_GET_PACKET(*icall));
 			if (rc == EOK)
-				rc = nil_received_msg_local(0,
-				    IPC_GET_DEVICE(*icall), packet, 0);
+				rc = nil_received_msg_local(IPC_GET_DEVICE(*icall),
+				    packet, 0);
 			
 			async_answer_0(iid, (sysarg_t) rc);
@@ -177,6 +176,6 @@
 		/* Notify the upper layer module */
 		fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-		if (nildummy_globals.proto.phone) {
-			il_mtu_changed_msg(nildummy_globals.proto.phone,
+		if (nildummy_globals.proto.sess) {
+			il_mtu_changed_msg(nildummy_globals.proto.sess,
 			    device->device_id, device->mtu,
 			    nildummy_globals.proto.service);
@@ -200,14 +199,14 @@
 
 	/* Bind the device driver */
-	device->phone = netif_bind_service(device->service, device->device_id,
+	device->sess = netif_bind_service(device->service, device->device_id,
 	    SERVICE_ETHERNET, nildummy_receiver);
-	if (device->phone < 0) {
+	if (device->sess == NULL) {
 		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
 		free(device);
-		return device->phone;
+		return ENOENT;
 	}
 	
 	/* Get hardware address */
-	int rc = netif_get_addr_req(device->phone, device->device_id,
+	int rc = netif_get_addr_req(device->sess, device->device_id,
 	    &device->addr, &device->addr_data);
 	if (rc != EOK) {
@@ -304,13 +303,13 @@
 }
 
-int nil_received_msg_local(int nil_phone, device_id_t device_id,
-    packet_t *packet, services_t target)
+int nil_received_msg_local(device_id_t device_id, packet_t *packet,
+    services_t target)
 {
 	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
 	
-	if (nildummy_globals.proto.phone) {
+	if (nildummy_globals.proto.sess) {
 		do {
 			packet_t *next = pq_detach(packet);
-			il_received_msg(nildummy_globals.proto.phone, device_id,
+			il_received_msg(nildummy_globals.proto.sess, device_id,
 			    packet, nildummy_globals.proto.service);
 			packet = next;
@@ -328,5 +327,5 @@
  *
  * @param[in] service Module service.
- * @param[in] phone   Service phone.
+ * @param[in] sess    Service session.
  *
  * @return EOK on success.
@@ -335,12 +334,12 @@
  *
  */
-static int nildummy_register_message(services_t service, int phone)
+static int nildummy_register_message(services_t service, async_sess_t *sess)
 {
 	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
 	nildummy_globals.proto.service = service;
-	nildummy_globals.proto.phone = phone;
-	
-	printf("%s: Protocol registered (service: %d, phone: %d)\n",
-	    NAME, nildummy_globals.proto.service, nildummy_globals.proto.phone);
+	nildummy_globals.proto.sess = sess;
+	
+	printf("%s: Protocol registered (service: %d)\n",
+	    NAME, nildummy_globals.proto.service);
 	
 	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
@@ -373,5 +372,5 @@
 	/* Send packet queue */
 	if (packet)
-		netif_send_msg(device->phone, device_id, packet,
+		netif_send_msg(device->sess, device_id, packet,
 		    SERVICE_NILDUMMY);
 	
@@ -393,8 +392,14 @@
 	
 	*answer_count = 0;
+	
+	if (!IPC_GET_IMETHOD(*call))
+		return EOK;
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return nildummy_register_message(NIL_GET_PROTO(*call), callback);
+	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_PHONE_HUNGUP:
-		return EOK;
-	
 	case NET_NIL_DEVICE:
 		return nildummy_device_message(IPC_GET_DEVICE(*call),
@@ -402,5 +407,5 @@
 	
 	case NET_NIL_SEND:
-		rc = packet_translate_remote(nildummy_globals.net_phone,
+		rc = packet_translate_remote(nildummy_globals.net_sess,
 		    &packet, IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -432,8 +437,4 @@
 			return rc;
 		return measured_strings_reply(address, 1);
-	
-	case IPC_M_CONNECT_TO_ME:
-		return nildummy_register_message(NIL_GET_PROTO(*call),
-		    IPC_GET_PHONE(*call));
 	}
 	
Index: uspace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -38,7 +38,7 @@
 #define NET_NILDUMMY_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <ipc/services.h>
-
 #include <net/device.h>
 #include <adt/measured_strings.h>
@@ -81,6 +81,6 @@
 	services_t service;
 	
-	/** Driver phone. */
-	int phone;
+	/** Driver session. */
+	async_sess_t *sess;
 	
 	/** Maximal transmission unit. */
@@ -99,12 +99,12 @@
 	services_t service;
 	
-	/** Protocol module phone. */
-	int phone;
+	/** Protocol module session. */
+	async_sess_t *sess;
 };
 
 /** Dummy nil global data. */
 struct nildummy_globals {
-	/** Networking module phone. */
-	int net_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
 	
 	/** Lock for devices. */
Index: uspace/srv/net/tl/icmp/Makefile
===================================================================
--- uspace/srv/net/tl/icmp/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/tl/icmp/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -32,4 +32,5 @@
 EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
 BINARY = icmp
+STATIC_ONLY = y
 
 SOURCES = \
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -118,6 +118,6 @@
 
 /** Global data */
-static int phone_net = -1;
-static int phone_ip = -1;
+static async_sess_t *net_sess = NULL;
+static async_sess_t *ip_sess = NULL;
 static bool error_reporting = true;
 static bool echo_replying = true;
@@ -173,5 +173,5 @@
 static void icmp_release(packet_t *packet)
 {
-	pq_release_remote(phone_net, packet_get_id(packet));
+	pq_release_remote(net_sess, packet_get_id(packet));
 }
 
@@ -225,5 +225,5 @@
 	}
 	
-	return ip_send_msg(phone_ip, -1, packet, SERVICE_ICMP, error);
+	return ip_send_msg(ip_sess, -1, packet, SERVICE_ICMP, error);
 }
 
@@ -297,5 +297,5 @@
 	size_t length = (size_t) addrlen;
 	
-	packet_t *packet = packet_get_4_remote(phone_net, size,
+	packet_t *packet = packet_get_4_remote(net_sess, size,
 	    icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
 	    icmp_dimension.suffix);
@@ -595,5 +595,5 @@
 	case ICMP_SKIP:
 	case ICMP_PHOTURIS:
-		ip_received_error_msg(phone_ip, -1, packet,
+		ip_received_error_msg(ip_sess, -1, packet,
 		    SERVICE_IP, SERVICE_ICMP);
 		return EOK;
@@ -608,16 +608,19 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
-{
-	bool loop = true;
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
 	packet_t *packet;
 	int rc;
 	
-	while (loop) {
+	while (true) {
+		if (!IPC_GET_IMETHOD(*icall))
+			break;
+		
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(phone_net, &packet,
+			rc = packet_translate_remote(net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK) {
@@ -629,7 +632,4 @@
 			async_answer_0(iid, (sysarg_t) rc);
 			break;
-		case IPC_M_PHONE_HUNGUP:
-			loop = false;
-			continue;
 		default:
 			async_answer_0(iid, (sysarg_t) ENOTSUP);
@@ -642,5 +642,5 @@
 /** Initialize the ICMP module.
  *
- * @param[in] net_phone Network module phone.
+ * @param[in] sess Network module session.
  *
  * @return EOK on success.
@@ -648,5 +648,5 @@
  *
  */
-int tl_initialize(int net_phone)
+int tl_initialize(async_sess_t *sess)
 {
 	measured_string_t names[] = {
@@ -670,11 +670,11 @@
 	atomic_set(&icmp_client, 0);
 	
-	phone_net = net_phone;
-	phone_ip = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
+	net_sess = sess;
+	ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
 	    icmp_receiver);
-	if (phone_ip < 0)
-		return phone_ip;
-	
-	int rc = ip_packet_size_req(phone_ip, -1, &icmp_dimension);
+	if (ip_sess == NULL)
+		return ENOENT;
+	
+	int rc = ip_packet_size_req(ip_sess, -1, &icmp_dimension);
 	if (rc != EOK)
 		return rc;
@@ -685,5 +685,5 @@
 	/* Get configuration */
 	configuration = &names[0];
-	rc = net_get_conf_req(phone_net, &configuration, count, &data);
+	rc = net_get_conf_req(net_sess, &configuration, count, &data);
 	if (rc != EOK)
 		return rc;
@@ -763,5 +763,5 @@
 	
 	case NET_ICMP_DEST_UNREACH:
-		rc = packet_translate_remote(phone_net, &packet,
+		rc = packet_translate_remote(net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -772,5 +772,5 @@
 	
 	case NET_ICMP_SOURCE_QUENCH:
-		rc = packet_translate_remote(phone_net, &packet,
+		rc = packet_translate_remote(net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -780,5 +780,5 @@
 	
 	case NET_ICMP_TIME_EXCEEDED:
-		rc = packet_translate_remote(phone_net, &packet,
+		rc = packet_translate_remote(net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
@@ -788,5 +788,5 @@
 	
 	case NET_ICMP_PARAMETERPROB:
-		rc = packet_translate_remote(phone_net, &packet,
+		rc = packet_translate_remote(net_sess, &packet,
 		    IPC_GET_PACKET(*call));
 		if (rc != EOK)
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -206,5 +206,6 @@
 
 static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t);
-static int tcp_process_client_messages(ipc_callid_t, ipc_call_t);
+static int tcp_process_client_messages(async_sess_t *, ipc_callid_t,
+    ipc_call_t);
 
 static int tcp_listen_message(socket_cores_t *, int, int);
@@ -324,7 +325,7 @@
 
 	if (!socket) {
-		if (tl_prepare_icmp_packet(tcp_globals.net_phone,
-		    tcp_globals.icmp_phone, packet, error) == EOK) {
-			icmp_destination_unreachable_msg(tcp_globals.icmp_phone,
+		if (tl_prepare_icmp_packet(tcp_globals.net_sess,
+		    tcp_globals.icmp_sess, packet, error) == EOK) {
+			icmp_destination_unreachable_msg(tcp_globals.icmp_sess,
 			    ICMP_PORT_UNREACH, 0, packet);
 		}
@@ -397,9 +398,9 @@
 		fibril_rwlock_write_unlock(socket_data->local_lock);
 
-		rc = tl_prepare_icmp_packet(tcp_globals.net_phone,
-		    tcp_globals.icmp_phone, packet, error);
+		rc = tl_prepare_icmp_packet(tcp_globals.net_sess,
+		    tcp_globals.icmp_sess, packet, error);
 		if (rc == EOK) {
 			/* Checksum error ICMP */
-			icmp_parameter_problem_msg(tcp_globals.icmp_phone,
+			icmp_parameter_problem_msg(tcp_globals.icmp_sess,
 			    ICMP_PARAM_POINTER,
 			    ((size_t) ((void *) &header->checksum)) -
@@ -439,5 +440,5 @@
 		break;
 	default:
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 	}
 
@@ -476,5 +477,5 @@
 	old_incoming = socket_data->next_incoming;
 
-	if (header->finalize) {
+	if (GET_TCP_HEADER_FINALIZE(header)) {
 		socket_data->fin_incoming = new_sequence_number +
 		    total_length - TCP_HEADER_LENGTH(header);
@@ -502,5 +503,5 @@
 			/* Release the acknowledged packets */
 			next_packet = pq_next(packet);
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(packet));
 			packet = next_packet;
@@ -561,5 +562,5 @@
 			next_packet = pq_next(next_packet);
 			pq_insert_after(tmp_packet, next_packet);
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(tmp_packet));
 		}
@@ -598,5 +599,5 @@
 				if (packet == socket_data->incoming)
 					socket_data->incoming = next_packet;
-				pq_release_remote(tcp_globals.net_phone,
+				pq_release_remote(tcp_globals.net_sess,
 				    packet_get_id(packet));
 				packet = next_packet;
@@ -621,5 +622,5 @@
 				if (length <= 0) {
 					/* Remove the empty packet */
-					pq_release_remote(tcp_globals.net_phone,
+					pq_release_remote(tcp_globals.net_sess,
 					    packet_get_id(packet));
 					packet = next_packet;
@@ -668,5 +669,5 @@
 				}
 				/* Remove the duplicit or corrupted packet */
-				pq_release_remote(tcp_globals.net_phone,
+				pq_release_remote(tcp_globals.net_sess,
 				    packet_get_id(packet));
 				packet = next_packet;
@@ -695,7 +696,7 @@
 		if (rc != EOK) {
 			/* Remove the corrupted packets */
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(packet));
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(next_packet));
 		} else {
@@ -708,10 +709,10 @@
 				    new_sequence_number, length);
 				if (rc != EOK) {
-					pq_release_remote(tcp_globals.net_phone,
+					pq_release_remote(tcp_globals.net_sess,
 					    packet_get_id(next_packet));
 				}
 				rc = pq_insert_after(packet, next_packet);
 				if (rc != EOK) {
-					pq_release_remote(tcp_globals.net_phone,
+					pq_release_remote(tcp_globals.net_sess,
 					    packet_get_id(next_packet));
 				}
@@ -722,5 +723,5 @@
 		printf("unexpected\n");
 		/* Release duplicite or restricted */
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		forced_ack = true;
 	}
@@ -790,5 +791,5 @@
 	if (rc != EOK)
 		return tcp_release_and_return(packet, rc);
-	rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+	rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 	    &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
 	if (rc != EOK)
@@ -799,9 +800,10 @@
 
 	/* Notify the destination socket */
-	async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
-	    (sysarg_t) socket->socket_id,
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
 	    ((packet_dimension->content < socket_data->data_fragment_size) ?
 	    packet_dimension->content : socket_data->data_fragment_size), 0, 0,
 	    (sysarg_t) fragments);
+	async_exchange_end(exch);
 
 	return EOK;
@@ -820,8 +822,8 @@
 
 	/* Notify the destination socket */
-	async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
-	    (sysarg_t) socket->socket_id,
-	    0, 0, 0,
-	    (sysarg_t) 0 /* 0 fragments == no more data */);
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
+	    0, 0, 0, (sysarg_t) 0 /* 0 fragments == no more data */);
+	async_exchange_end(exch);
 }
 
@@ -838,5 +840,5 @@
 	assert(packet);
 
-	if (!header->synchronize)
+	if (!GET_TCP_HEADER_SYNCHRONIZE(header))
 		return tcp_release_and_return(packet, EINVAL);
 	
@@ -849,5 +851,5 @@
 	next_packet = pq_detach(packet);
 	if (next_packet) {
-		pq_release_remote(tcp_globals.net_phone,
+		pq_release_remote(tcp_globals.net_sess,
 		    packet_get_id(next_packet));
 	}
@@ -903,5 +905,5 @@
 	assert(packet);
 
-	if (!header->synchronize)
+	if (!GET_TCP_HEADER_SYNCHRONIZE(header))
 		return tcp_release_and_return(packet, EINVAL);
 
@@ -936,5 +938,5 @@
 	/* Create a socket */
 	socket_id = -1;
-	rc = socket_create(socket_data->local_sockets, listening_socket->phone,
+	rc = socket_create(socket_data->local_sockets, listening_socket->sess,
 	    socket_data, &socket_id);
 	if (rc != EOK) {
@@ -989,5 +991,5 @@
 	fibril_rwlock_write_unlock(&tcp_globals.lock);
 	if (rc != EOK) {
-		socket_destroy(tcp_globals.net_phone, socket->socket_id,
+		socket_destroy(tcp_globals.net_sess, socket->socket_id,
 		    socket_data->local_sockets, &tcp_globals.sockets,
 		    tcp_free_socket_data);
@@ -1001,5 +1003,5 @@
 	next_packet = pq_detach(packet);
 	if (next_packet) {
-		pq_release_remote(tcp_globals.net_phone,
+		pq_release_remote(tcp_globals.net_sess,
 		    packet_get_id(next_packet));
 	}
@@ -1010,5 +1012,5 @@
 		    packet_get_data_length(packet) - sizeof(*header));
 		if (rc != EOK) {
-			socket_destroy(tcp_globals.net_phone, socket->socket_id,
+			socket_destroy(tcp_globals.net_sess, socket->socket_id,
 			    socket_data->local_sockets, &tcp_globals.sockets,
 			    tcp_free_socket_data);
@@ -1021,5 +1023,5 @@
 	rc = tcp_queue_packet(socket, socket_data, packet, 1);
 	if (rc != EOK) {
-		socket_destroy(tcp_globals.net_phone, socket->socket_id,
+		socket_destroy(tcp_globals.net_sess, socket->socket_id,
 		    socket_data->local_sockets, &tcp_globals.sockets,
 		    tcp_free_socket_data);
@@ -1029,5 +1031,5 @@
 	packet = tcp_get_packets_to_send(socket, socket_data);
 	if (!packet) {
-		socket_destroy(tcp_globals.net_phone, socket->socket_id,
+		socket_destroy(tcp_globals.net_sess, socket->socket_id,
 		    socket_data->local_sockets, &tcp_globals.sockets,
 		    tcp_free_socket_data);
@@ -1057,5 +1059,5 @@
 	assert(packet);
 
-	if (!header->acknowledge)
+	if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
 		return tcp_release_and_return(packet, EINVAL);
 
@@ -1064,5 +1066,5 @@
 
 	socket_data->next_incoming = ntohl(header->sequence_number); /* + 1; */
-	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 	socket_data->state = TCP_SOCKET_ESTABLISHED;
 	listening_socket = socket_cores_find(socket_data->local_sockets,
@@ -1078,8 +1080,10 @@
 		if (rc == EOK) {
 			/* Notify the destination socket */
-			async_msg_5(socket->phone, NET_SOCKET_ACCEPTED,
+			async_exch_t *exch = async_exchange_begin(socket->sess);
+			async_msg_5(exch, NET_SOCKET_ACCEPTED,
 			    (sysarg_t) listening_socket->socket_id,
 			    socket_data->data_fragment_size, TCP_HEADER_SIZE,
 			    0, (sysarg_t) socket->socket_id);
+			async_exchange_end(exch);
 
 			fibril_rwlock_write_unlock(socket_data->local_lock);
@@ -1126,5 +1130,5 @@
 	assert(header);
 
-	if (!header->acknowledge)
+	if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
 		return;
 
@@ -1177,5 +1181,5 @@
 				/* Add to acknowledged or release */
 				if (pq_add(&acknowledged, packet, 0, 0) != EOK)
-					pq_release_remote(tcp_globals.net_phone,
+					pq_release_remote(tcp_globals.net_sess,
 					    packet_get_id(packet));
 				packet = next;
@@ -1186,5 +1190,5 @@
 		/* Release acknowledged */
 		if (acknowledged) {
-			pq_release_remote(tcp_globals.net_phone,
+			pq_release_remote(tcp_globals.net_sess,
 			    packet_get_id(acknowledged));
 		}
@@ -1230,11 +1234,12 @@
 	assert(answer);
 	assert(answer_count);
-
+	
 	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_CONNECT_TO_ME:
-		return tcp_process_client_messages(callid, *call);
-	}
-
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return tcp_process_client_messages(callback, callid, *call);
+	
 	return ENOTSUP;
 }
@@ -1266,10 +1271,9 @@
 }
 
-int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
+int tcp_process_client_messages(async_sess_t *sess, ipc_callid_t callid,
+    ipc_call_t call)
 {
 	int res;
-	bool keep_on_going = true;
 	socket_cores_t local_sockets;
-	int app_phone = IPC_GET_PHONE(call);
 	struct sockaddr *addr;
 	int socket_id;
@@ -1293,5 +1297,5 @@
 	fibril_rwlock_initialize(&lock);
 
-	while (keep_on_going) {
+	while (true) {
 
 		/* Answer the call */
@@ -1301,12 +1305,12 @@
 		/* Get the next call */
 		callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			res = EHANGUP;
+			break;
+		}
 
 		/* Process the call */
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			keep_on_going = false;
-			res = EHANGUP;
-			break;
-
 		case NET_SOCKET:
 			socket_data =
@@ -1322,5 +1326,5 @@
 			fibril_rwlock_write_lock(&lock);
 			socket_id = SOCKET_GET_SOCKET_ID(call);
-			res = socket_create(&local_sockets, app_phone,
+			res = socket_create(&local_sockets, sess,
 			    socket_data, &socket_id);
 			SOCKET_SET_SOCKET_ID(answer, socket_id);
@@ -1330,5 +1334,5 @@
 				break;
 			}
-			if (tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+			if (tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 			    &tcp_globals.dimensions, DEVICE_INVALID_ID,
 			    &packet_dimension) == EOK) {
@@ -1505,10 +1509,10 @@
 	}
 
-	/* Release the application phone */
-	async_hangup(app_phone);
+	/* Release the application session */
+	async_hangup(sess);
 
 	printf("release\n");
 	/* Release all local sockets */
-	socket_cores_release(tcp_globals.net_phone, &local_sockets,
+	socket_cores_release(tcp_globals.net_sess, &local_sockets,
 	    &tcp_globals.sockets, tcp_free_socket_data);
 
@@ -1618,5 +1622,5 @@
 			local_lock = socket_data->local_lock;
 			fibril_rwlock_write_lock(local_lock);
-			socket_destroy(tcp_globals.net_phone,
+			socket_destroy(tcp_globals.net_sess,
 			    timeout->socket_id, timeout->local_sockets,
 			    &tcp_globals.sockets, tcp_free_socket_data);
@@ -1751,5 +1755,5 @@
 	}
 
-	rc = ip_get_route_req(tcp_globals.ip_phone, IPPROTO_TCP,
+	rc = ip_get_route_req(tcp_globals.ip_sess, IPPROTO_TCP,
 	    addr, addrlen, &socket_data->device_id,
 	    &socket_data->pseudo_header, &socket_data->headerlen);
@@ -1833,5 +1837,5 @@
 
 	/* Remember the outgoing FIN */
-	if (header->finalize) 
+	if (GET_TCP_HEADER_FINALIZE(header))
 		socket_data->fin_outgoing = socket_data->next_outgoing;
 	
@@ -1899,5 +1903,5 @@
 			rc = pq_insert_after(previous, copy);
 			if (rc != EOK) {
-				pq_release_remote(tcp_globals.net_phone,
+				pq_release_remote(tcp_globals.net_sess,
 				    packet_get_id(copy));
 				return sending;
@@ -1936,5 +1940,5 @@
 	    socket_data->headerlen, packet_get_data_length(packet));
 	if (rc != EOK) {
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		return NULL;
 	}
@@ -1943,5 +1947,5 @@
 	header = (tcp_header_t *) packet_get_data(packet);
 	if (!header) {
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		return NULL;
 	}
@@ -1952,5 +1956,5 @@
 		header->acknowledgement_number =
 		    htonl(socket_data->next_incoming);
-		header->acknowledge = 1;
+		SET_TCP_HEADER_ACKNOWLEDGE(header, 1);
 	}
 	header->window = htons(socket_data->window);
@@ -1968,5 +1972,5 @@
 	rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
 	if (rc != EOK) {
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		return NULL;
 	}
@@ -1975,5 +1979,5 @@
 	    sequence_number, socket_data->state, socket_data->timeout, true);
 	if (rc != EOK) {
-		pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+		pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 		return NULL;
 	}
@@ -1992,5 +1996,5 @@
 
 	/* Make a copy of the packet */
-	copy = packet_get_copy(tcp_globals.net_phone, packet);
+	copy = packet_get_copy(tcp_globals.net_sess, packet);
 	if (!copy)
 		return NULL;
@@ -2006,5 +2010,5 @@
 	while (packet) {
 		next = pq_detach(packet);
-		ip_send_msg(tcp_globals.ip_phone, device_id, packet,
+		ip_send_msg(tcp_globals.ip_sess, device_id, packet,
 		    SERVICE_TCP, 0);
 		packet = next;
@@ -2024,7 +2028,8 @@
 	header->source_port = htons(socket->port);
 	header->source_port = htons(socket_data->dest_port);
-	header->header_length = TCP_COMPUTE_HEADER_LENGTH(sizeof(*header));
-	header->synchronize = synchronize;
-	header->finalize = finalize;
+	SET_TCP_HEADER_LENGTH(header,
+	    TCP_COMPUTE_HEADER_LENGTH(sizeof(*header)));
+	SET_TCP_HEADER_SYNCHRONIZE(header, synchronize);
+	SET_TCP_HEADER_FINALIZE(header, finalize);
 }
 
@@ -2118,5 +2123,5 @@
 		return NO_DATA;
 
-	rc = packet_translate_remote(tcp_globals.net_phone, &packet, packet_id);
+	rc = packet_translate_remote(tcp_globals.net_sess, &packet, packet_id);
 	if (rc != EOK)
 		return rc;
@@ -2129,5 +2134,5 @@
 	/* Release the packet */
 	dyn_fifo_pop(&socket->received);
-	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 
 	/* Return the total length */
@@ -2167,5 +2172,5 @@
 		return ENOTCONN;
 
-	rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+	rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 	    &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
 	if (rc != EOK)
@@ -2178,5 +2183,5 @@
 	for (index = 0; index < fragments; index++) {
 		/* Read the data fragment */
-		result = tl_socket_read_packet_data(tcp_globals.net_phone,
+		result = tl_socket_read_packet_data(tcp_globals.net_sess,
 		    &packet, TCP_HEADER_SIZE, packet_dimension,
 		    socket_data->addr, socket_data->addrlen);
@@ -2241,5 +2246,5 @@
 	default:
 		/* Just destroy */
-		rc = socket_destroy(tcp_globals.net_phone, socket_id,
+		rc = socket_destroy(tcp_globals.net_sess, socket_id,
 		    local_sockets, &tcp_globals.sockets,
 		    tcp_free_socket_data);
@@ -2289,5 +2294,5 @@
 
 	/* Get the device packet dimension */
-	rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+	rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 	    &tcp_globals.dimensions, socket_data->device_id, &packet_dimension);
 	if (rc != EOK)
@@ -2295,5 +2300,5 @@
 
 	/* Get a new packet */
-	*packet = packet_get_4_remote(tcp_globals.net_phone, TCP_HEADER_SIZE,
+	*packet = packet_get_4_remote(tcp_globals.net_sess, TCP_HEADER_SIZE,
 	    packet_dimension->addr_len, packet_dimension->prefix,
 	    packet_dimension->suffix);
@@ -2358,5 +2363,5 @@
 			if (rc != EOK)
 				return rc;
-			rc = tl_get_ip_packet_dimension(tcp_globals.ip_phone,
+			rc = tl_get_ip_packet_dimension(tcp_globals.ip_sess,
 			    &tcp_globals.dimensions, socket_data->device_id,
 			    &packet_dimension);
@@ -2430,5 +2435,5 @@
 int tcp_release_and_return(packet_t *packet, int result)
 {
-	pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(tcp_globals.net_sess, packet_get_id(packet));
 	return result;
 }
@@ -2438,7 +2443,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
+ * @param[in]     arg   Local argument.
  *
  */
-static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -2448,5 +2454,5 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(tcp_globals.net_phone, &packet,
+			rc = packet_translate_remote(tcp_globals.net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK)
@@ -2466,5 +2472,5 @@
 /** Initialize the TCP module.
  *
- * @param[in] net_phone Network module phone.
+ * @param[in] sess Network module session.
  *
  * @return EOK on success.
@@ -2472,17 +2478,17 @@
  *
  */
-int tl_initialize(int net_phone)
+int tl_initialize(async_sess_t *sess)
 {
 	fibril_rwlock_initialize(&tcp_globals.lock);
 	fibril_rwlock_write_lock(&tcp_globals.lock);
 	
-	tcp_globals.net_phone = net_phone;
+	tcp_globals.net_sess = sess;
 	
-	tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
-	tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
+	tcp_globals.icmp_sess = icmp_connect_module();
+	tcp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
 	    SERVICE_TCP, tcp_receiver);
-	if (tcp_globals.ip_phone < 0) {
+	if (tcp_globals.ip_sess == NULL) {
 		fibril_rwlock_write_unlock(&tcp_globals.lock);
-		return tcp_globals.ip_phone;
+		return ENOENT;
 	}
 	
Index: uspace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/tl/tcp/tcp.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -38,6 +38,6 @@
 #define NET_TCP_H_
 
+#include <async.h>
 #include <fibril_synch.h>
-
 #include <net/packet.h>
 #include <net/device.h>
@@ -284,10 +284,10 @@
 /** TCP global data. */
 struct tcp_globals {
-	/** Networking module phone. */
-	int net_phone;
-	/** IP module phone. */
-	int ip_phone;
-	/** ICMP module phone. */
-	int icmp_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
+	/** IP module session. */
+	async_sess_t *ip_sess;
+	/** ICMP module session. */
+	async_sess_t *icmp_sess;
 	/** Last used free port. */
 	int last_used_port;
Index: uspace/srv/net/tl/tcp/tcp_header.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_header.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/tl/tcp/tcp_header.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -47,5 +47,5 @@
  * @param[in] header The TCP packet header.
  */
-#define TCP_HEADER_LENGTH(header)		((header)->header_length * 4U)
+#define TCP_HEADER_LENGTH(header)		(GET_TCP_HEADER_LENGTH(header) * 4U)
 
 /** Returns the TCP header length.
@@ -73,30 +73,63 @@
 	uint32_t sequence_number;
 	uint32_t acknowledgement_number;
-	
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t header_length:4;
-	uint8_t reserved1:4;
-#else
-	uint8_t reserved1:4;
-	uint8_t header_length:4;
-#endif
 
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t reserved2:2;
-	uint8_t urgent:1;
-	uint8_t acknowledge:1;
-	uint8_t push:1;
-	uint8_t reset:1;
-	uint8_t synchronize:1;
-	uint8_t finalize:1;
-#else
-	uint8_t finalize:1;
-	uint8_t synchronize:1;
-	uint8_t reset:1;
-	uint8_t push:1;
-	uint8_t acknowledge:1;
-	uint8_t urgent:1;
-	uint8_t reserved2:2;
-#endif
+	uint8_t hlr; /* header length, reserved1 */
+
+#define GET_TCP_HEADER_LENGTH(header) \
+	(((header)->hlr & 0xf0) >> 4)
+#define SET_TCP_HEADER_LENGTH(header, length) \
+	((header)->hlr = \
+	 ((length & 0x0f) << 4) | ((header)->hlr & 0x0f))
+
+#define GET_TCP_HEADER_RESERVED1(header) \
+	((header)->hlr & 0x0f)
+#define SET_TCP_HEADER_RESERVED1(header, reserved1) \
+	((header)->hlr = \
+	 (reserved1 & 0x0f) | ((header)->hlr & 0xf0))
+
+	/* reserved2, urgent, acknowledge, push, reset, synchronize, finalize */
+	uint8_t ruaprsf;  
+
+#define GET_TCP_HEADER_RESERVED2(header) \
+	(((header)->ruaprsf & 0xc0) >> 6)
+#define SET_TCP_HEADER_RESERVED2(header, reserved2) \
+	((header)->ruaprsf = \
+	 ((reserved2 & 0x03) << 6) | ((header)->ruaprsf & 0x3f))
+
+#define GET_TCP_HEADER_URGENT(header) \
+	(((header)->ruaprsf & 0x20) >> 5)
+#define SET_TCP_HEADER_URGENT(header, urgent) \
+	((header)->ruaprsf = \
+	 ((urgent & 0x01) << 5) | ((header)->ruaprsf & 0xdf))
+
+#define GET_TCP_HEADER_ACKNOWLEDGE(header) \
+	(((header)->ruaprsf & 0x10) >> 4)
+#define SET_TCP_HEADER_ACKNOWLEDGE(header, acknowledge) \
+	((header)->ruaprsf = \
+	 ((acknowledge & 0x01) << 4) | ((header)->ruaprsf & 0xef))
+
+#define GET_TCP_HEADER_PUSH(header) \
+	(((header)->ruaprsf & 0x08) >> 3)
+#define SET_TCP_HEADER_PUSH(header, push) \
+	((header)->ruaprsf = \
+	 ((push & 0x01) << 3) | ((header)->ruaprsf & 0xf7))
+
+#define GET_TCP_HEADER_RESET(header) \
+	(((header)->ruaprsf & 0x04) >> 2)
+#define SET_TCP_HEADER_RESET(header, reset) \
+	((header)->ruaprsf = \
+	 ((reset & 0x01) << 2) | ((header)->ruaprsf & 0xfb))
+
+#define GET_TCP_HEADER_SYNCHRONIZE(header) \
+	(((header)->ruaprsf & 0x02) >> 1)
+#define SET_TCP_HEADER_SYNCHRONIZE(header, synchronize) \
+	((header)->ruaprsf = \
+	 ((synchronize & 0x01) << 1) | ((header)->ruaprsf & 0xfd))
+
+#define GET_TCP_HEADER_FINALIZE(header) \
+	((header)->ruaprsf & 0x01)
+#define SET_TCP_HEADER_FINALIZE(header, finalize) \
+	((header)->ruaprsf = \
+	 (finalize & 0x01) | ((header)->ruaprsf & 0xfe))
 
 	uint16_t window;
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/tl/udp/udp.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -99,5 +99,5 @@
 static int udp_release_and_return(packet_t *packet, int result)
 {
-	pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
+	pq_release_remote(udp_globals.net_sess, packet_get_id(packet));
 	return result;
 }
@@ -192,7 +192,7 @@
 	    ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
 	if (!socket) {
-		if (tl_prepare_icmp_packet(udp_globals.net_phone,
-		    udp_globals.icmp_phone, packet, error) == EOK) {
-			icmp_destination_unreachable_msg(udp_globals.icmp_phone,
+		if (tl_prepare_icmp_packet(udp_globals.net_sess,
+		    udp_globals.icmp_sess, packet, error) == EOK) {
+			icmp_destination_unreachable_msg(udp_globals.icmp_sess,
 			    ICMP_PORT_UNREACH, 0, packet);
 		}
@@ -251,5 +251,5 @@
 			while (tmp_packet) {
 				next_packet = pq_detach(tmp_packet);
-				pq_release_remote(udp_globals.net_phone,
+				pq_release_remote(udp_globals.net_sess,
 				    packet_get_id(tmp_packet));
 				tmp_packet = next_packet;
@@ -274,9 +274,9 @@
 		if (flip_checksum(compact_checksum(checksum)) !=
 		    IP_CHECKSUM_ZERO) {
-			if (tl_prepare_icmp_packet(udp_globals.net_phone,
-			    udp_globals.icmp_phone, packet, error) == EOK) {
+			if (tl_prepare_icmp_packet(udp_globals.net_sess,
+			    udp_globals.icmp_sess, packet, error) == EOK) {
 				/* Checksum error ICMP */
 				icmp_parameter_problem_msg(
-				    udp_globals.icmp_phone, ICMP_PARAM_POINTER,
+				    udp_globals.icmp_sess, ICMP_PARAM_POINTER,
 				    ((size_t) ((void *) &header->checksum)) -
 				    ((size_t) ((void *) header)), packet);
@@ -292,5 +292,5 @@
 		return udp_release_and_return(packet, rc);
 		
-	rc = tl_get_ip_packet_dimension(udp_globals.ip_phone,
+	rc = tl_get_ip_packet_dimension(udp_globals.ip_sess,
 	    &udp_globals.dimensions, device_id, &packet_dimension);
 	if (rc != EOK)
@@ -299,7 +299,9 @@
 	/* Notify the destination socket */
 	fibril_rwlock_write_unlock(&udp_globals.lock);
-	async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
-	    (sysarg_t) socket->socket_id, packet_dimension->content, 0, 0,
-	    (sysarg_t) fragments);
+	
+	async_exch_t *exch = async_exchange_begin(socket->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
+	    packet_dimension->content, 0, 0, (sysarg_t) fragments);
+	async_exchange_end(exch);
 
 	return EOK;
@@ -337,7 +339,8 @@
  * @param[in]     iid   Message identifier.
  * @param[in,out] icall Message parameters.
- *
- */
-static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall)
+ * @param[in]     arg   Local argument.
+ *
+ */
+static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
 	packet_t *packet;
@@ -347,5 +350,5 @@
 		switch (IPC_GET_IMETHOD(*icall)) {
 		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(udp_globals.net_phone, &packet,
+			rc = packet_translate_remote(udp_globals.net_sess, &packet,
 			    IPC_GET_PACKET(*icall));
 			if (rc == EOK)
@@ -365,5 +368,5 @@
 /** Initialize the UDP module.
  *
- * @param[in] net_phone Network module phone.
+ * @param[in] sess Network module session.
  *
  * @return EOK on success.
@@ -371,5 +374,5 @@
  *
  */
-int tl_initialize(int net_phone)
+int tl_initialize(async_sess_t *sess)
 {
 	measured_string_t names[] = {
@@ -390,17 +393,16 @@
 	fibril_rwlock_write_lock(&udp_globals.lock);
 	
-	udp_globals.net_phone = net_phone;
-	
-	udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
-	
-	udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
-	    SERVICE_UDP, udp_receiver);
-	if (udp_globals.ip_phone < 0) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return udp_globals.ip_phone;
+	udp_globals.net_sess = sess;
+	udp_globals.icmp_sess = icmp_connect_module();
+	
+	udp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
+	     SERVICE_UDP, udp_receiver);
+	if (udp_globals.ip_sess == NULL) {
+	    fibril_rwlock_write_unlock(&udp_globals.lock);
+	    return ENOENT;
 	}
 	
 	/* Read default packet dimensions */
-	int rc = ip_packet_size_req(udp_globals.ip_phone, -1,
+	int rc = ip_packet_size_req(udp_globals.ip_sess, -1,
 	    &udp_globals.packet_dimension);
 	if (rc != EOK) {
@@ -431,5 +433,5 @@
 	/* Get configuration */
 	configuration = &names[0];
-	rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,
+	rc = net_get_conf_req(udp_globals.net_sess, &configuration, count,
 	    &data);
 	if (rc != EOK) {
@@ -525,10 +527,10 @@
 
 	if (udp_globals.checksum_computing) {
-		rc = ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr,
+		rc = ip_get_route_req(udp_globals.ip_sess, IPPROTO_UDP, addr,
 		    addrlen, &device_id, &ip_header, &headerlen);
 		if (rc != EOK)
 			return rc;
 		/* Get the device packet dimension */
-//		rc = tl_get_ip_packet_dimension(udp_globals.ip_phone,
+//		rc = tl_get_ip_packet_dimension(udp_globals.ip_sess,
 //		    &udp_globals.dimensions, device_id, &packet_dimension);
 //		if (rc != EOK)
@@ -537,5 +539,5 @@
 //	} else {
 		/* Do not ask all the time */
-		rc = ip_packet_size_req(udp_globals.ip_phone, -1,
+		rc = ip_packet_size_req(udp_globals.ip_sess, -1,
 		    &udp_globals.packet_dimension);
 		if (rc != EOK)
@@ -555,5 +557,5 @@
 
 	/* Read the first packet fragment */
-	result = tl_socket_read_packet_data(udp_globals.net_phone, &packet,
+	result = tl_socket_read_packet_data(udp_globals.net_sess, &packet,
 	    UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
 	if (result < 0)
@@ -576,5 +578,5 @@
 	/* Read the rest of the packet fragments */
 	for (index = 1; index < fragments; index++) {
-		result = tl_socket_read_packet_data(udp_globals.net_phone,
+		result = tl_socket_read_packet_data(udp_globals.net_sess,
 		    &next_packet, 0, packet_dimension, addr, addrlen);
 		if (result < 0)
@@ -628,5 +630,5 @@
 
 	/* Send the packet */
-	ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);
+	ip_send_msg(udp_globals.ip_sess, device_id, packet, SERVICE_UDP, 0);
 
 	return EOK;
@@ -675,5 +677,5 @@
 		return NO_DATA;
 	
-	rc = packet_translate_remote(udp_globals.net_phone, &packet, packet_id);
+	rc = packet_translate_remote(udp_globals.net_sess, &packet, packet_id);
 	if (rc != EOK) {
 		(void) dyn_fifo_pop(&socket->received);
@@ -735,20 +737,22 @@
 }
 
-/** Processes the socket client messages.
- *
- * Runs until the client module disconnects.
- *
- * @param[in] callid 	The message identifier.
- * @param[in] call	The message parameters.
- * @return		EOK on success.
- *
- * @see	socket.h
- */
-static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
+/** Process the socket client messages.
+ *
+ * Run until the client module disconnects.
+ *
+ * @see socket.h
+ *
+ * @param[in] sess   Callback session.
+ * @param[in] callid Message identifier.
+ * @param[in] call   Message parameters.
+ *
+ * @return EOK on success.
+ *
+ */
+static int udp_process_client_messages(async_sess_t *sess, ipc_callid_t callid,
+    ipc_call_t call)
 {
 	int res;
-	bool keep_on_going = true;
 	socket_cores_t local_sockets;
-	int app_phone = IPC_GET_PHONE(call);
 	struct sockaddr *addr;
 	int socket_id;
@@ -773,5 +777,5 @@
 	socket_cores_initialize(&local_sockets);
 
-	while (keep_on_going) {
+	while (true) {
 
 		/* Answer the call */
@@ -785,13 +789,13 @@
 
 		/* Process the call */
-		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			keep_on_going = false;
+		if (!IPC_GET_IMETHOD(call)) {
 			res = EHANGUP;
 			break;
-
+		}
+		
+		switch (IPC_GET_IMETHOD(call)) {
 		case NET_SOCKET:
 			socket_id = SOCKET_GET_SOCKET_ID(call);
-			res = socket_create(&local_sockets, app_phone, NULL,
+			res = socket_create(&local_sockets, sess, NULL,
 			    &socket_id);
 			SOCKET_SET_SOCKET_ID(answer, socket_id);
@@ -801,5 +805,5 @@
 			
 			size = MAX_UDP_FRAGMENT_SIZE;
-			if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
+			if (tl_get_ip_packet_dimension(udp_globals.ip_sess,
 			    &udp_globals.dimensions, DEVICE_INVALID_ID,
 			    &packet_dimension) == EOK) {
@@ -865,5 +869,5 @@
 		case NET_SOCKET_CLOSE:
 			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = socket_destroy(udp_globals.net_phone,
+			res = socket_destroy(udp_globals.net_sess,
 			    SOCKET_GET_SOCKET_ID(call), &local_sockets,
 			    &udp_globals.sockets, NULL);
@@ -879,9 +883,9 @@
 	}
 
-	/* Release the application phone */
-	async_hangup(app_phone);
+	/* Release the application session */
+	async_hangup(sess);
 
 	/* Release all local sockets */
-	socket_cores_release(udp_globals.net_phone, &local_sockets,
+	socket_cores_release(udp_globals.net_sess, &local_sockets,
 	    &udp_globals.sockets, NULL);
 
@@ -913,10 +917,10 @@
 {
 	*answer_count = 0;
-
-	switch (IPC_GET_IMETHOD(*call)) {
-	case IPC_M_CONNECT_TO_ME:
-		return udp_process_client_messages(callid, *call);
-	}
-
+	
+	async_sess_t *callback =
+	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return udp_process_client_messages(callback, callid, *call);
+	
 	return ENOTSUP;
 }
Index: uspace/srv/net/tl/udp/udp.h
===================================================================
--- uspace/srv/net/tl/udp/udp.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/net/tl/udp/udp.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -38,4 +38,5 @@
 #define NET_UDP_H_
 
+#include <async.h>
 #include <fibril_synch.h>
 #include <socket_core.h>
@@ -49,10 +50,10 @@
 /** UDP global data. */
 struct udp_globals {
-	/** Networking module phone. */
-	int net_phone;
-	/** IP module phone. */
-	int ip_phone;
-	/** ICMP module phone. */
-	int icmp_phone;
+	/** Networking module session. */
+	async_sess_t *net_sess;
+	/** IP module session. */
+	async_sess_t *ip_sess;
+	/** ICMP module session. */
+	async_sess_t *icmp_sess;
 	/** Packet dimension. */
 	packet_dimension_t packet_dimension;
Index: uspace/srv/ns/Makefile
===================================================================
--- uspace/srv/ns/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/ns/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../..
 BINARY = ns
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/ns/clonable.c
===================================================================
--- uspace/srv/ns/clonable.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/ns/clonable.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -52,5 +52,5 @@
 
 /** List of clonable-service connection requests. */
-static link_t cs_req;
+static list_t cs_req;
 
 int clonable_init(void)
@@ -76,5 +76,8 @@
     ipc_callid_t callid)
 {
-	if (list_empty(&cs_req)) {
+	link_t *req_link;
+
+	req_link = list_first(&cs_req);
+	if (req_link == NULL) {
 		/* There was no pending connection request. */
 		printf("%s: Unexpected clonable server.\n", NAME);
@@ -83,6 +86,6 @@
 	}
 	
-	cs_req_t *csr = list_get_instance(cs_req.next, cs_req_t, link);
-	list_remove(&csr->link);
+	cs_req_t *csr = list_get_instance(req_link, cs_req_t, link);
+	list_remove(req_link);
 	
 	/* Currently we can only handle a single type of clonable service. */
Index: uspace/srv/ns/service.c
===================================================================
--- uspace/srv/ns/service.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/ns/service.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -123,5 +123,5 @@
 } pending_conn_t;
 
-static link_t pending_conn;
+static list_t pending_conn;
 
 int service_init(void)
@@ -141,8 +141,6 @@
 void process_pending_conn(void)
 {
-	link_t *cur;
-	
 loop:
-	for (cur = pending_conn.next; cur != &pending_conn; cur = cur->next) {
+	list_foreach(pending_conn, cur) {
 		pending_conn_t *pr = list_get_instance(cur, pending_conn_t, link);
 		
Index: uspace/srv/ns/task.c
===================================================================
--- uspace/srv/ns/task.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/ns/task.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -189,5 +189,5 @@
 } pending_wait_t;
 
-static link_t pending_wait;
+static list_t pending_wait;
 
 int task_init(void)
@@ -212,9 +212,8 @@
 void process_pending_wait(void)
 {
-	link_t *cur;
 	task_exit_t texit;
 	
 loop:
-	for (cur = pending_wait.next; cur != &pending_wait; cur = cur->next) {
+	list_foreach(pending_wait, cur) {
 		pending_wait_t *pr = list_get_instance(cur, pending_wait_t, link);
 		
Index: uspace/srv/taskmon/taskmon.c
===================================================================
--- uspace/srv/taskmon/taskmon.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/taskmon/taskmon.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -92,14 +92,15 @@
 int main(int argc, char *argv[])
 {
-	printf(NAME ": Task Monitoring Service\n");
-
+	printf("%s: Task Monitoring Service\n", NAME);
+	
 	if (event_subscribe(EVENT_FAULT, 0) != EOK) {
-		printf(NAME ": Error registering fault notifications.\n");
+		printf("%s: Error registering fault notifications.\n", NAME);
 		return -1;
 	}
-
+	
 	async_set_interrupt_received(fault_event);
+	task_retval(0);
 	async_manager();
-
+	
 	return 0;
 }
Index: uspace/srv/vfs/Makefile
===================================================================
--- uspace/srv/vfs/Makefile	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/vfs/Makefile	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -30,4 +30,5 @@
 USPACE_PREFIX = ../..
 BINARY = vfs
+STATIC_NEEDED = y
 
 SOURCES = \
Index: uspace/srv/vfs/vfs.c
===================================================================
--- uspace/srv/vfs/vfs.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/vfs/vfs.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -37,5 +37,5 @@
 
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <errno.h>
@@ -49,8 +49,8 @@
 #define NAME  "vfs"
 
-static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall)
+static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	bool keep_on_going = true;
-
+	bool cont = true;
+	
 	/*
 	 * The connection was opened via the IPC_CONNECT_ME_TO call.
@@ -59,15 +59,15 @@
 	async_answer_0(iid, EOK);
 	
-	while (keep_on_going) {
+	while (cont) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
 		
+		if (!IPC_GET_IMETHOD(call))
+			break;
+		
 		switch (IPC_GET_IMETHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			keep_on_going = false;
-			break;
 		case VFS_IN_REGISTER:
 			vfs_register(callid, &call);
-			keep_on_going = false;
+			cont = false;
 			break;
 		case VFS_IN_MOUNT:
@@ -123,5 +123,5 @@
 		}
 	}
-
+	
 	/*
 	 * Open files for this client will be cleaned up when its last
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/vfs/vfs.h	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -53,5 +53,5 @@
 	vfs_info_t vfs_info;
 	fs_handle_t fs_handle;
-	async_sess_t session;
+	async_sess_t *sess;
 } fs_info_t;
 
@@ -145,7 +145,7 @@
 extern fibril_mutex_t nodes_mutex;
 
-extern fibril_condvar_t fs_head_cv;
-extern fibril_mutex_t fs_head_lock;
-extern link_t fs_head;		/**< List of registered file systems. */
+extern fibril_condvar_t fs_list_cv;
+extern fibril_mutex_t fs_list_lock;
+extern list_t fs_list;		/**< List of registered file systems. */
 
 extern vfs_pair_t rootfs;	/**< Root file system. */
@@ -158,7 +158,7 @@
 } plb_entry_t;
 
-extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_head. */
+extern fibril_mutex_t plb_mutex;/**< Mutex protecting plb and plb_entries. */
 extern uint8_t *plb;		/**< Path Lookup Buffer */
-extern link_t plb_head;		/**< List of active PLB entries. */
+extern list_t plb_entries;	/**< List of active PLB entries. */
 
 #define MAX_MNTOPTS_LEN		256
@@ -167,6 +167,6 @@
 extern fibril_rwlock_t namespace_rwlock;
 
-extern int vfs_grab_phone(fs_handle_t);
-extern void vfs_release_phone(fs_handle_t, int);
+extern async_exch_t *vfs_exchange_grab(fs_handle_t);
+extern void vfs_exchange_release(async_exch_t *);
 
 extern fs_handle_t fs_name_to_handle(char *, bool);
@@ -176,5 +176,4 @@
     vfs_pair_t *, ...);
 extern int vfs_open_node_internal(vfs_lookup_res_t *);
-extern int vfs_close_internal(vfs_file_t *);
 
 extern bool vfs_nodes_init(void);
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/vfs/vfs_file.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -45,5 +45,5 @@
 #include "vfs.h"
 
-#define VFS_DATA	((vfs_client_data_t *) async_client_data_get())
+#define VFS_DATA	((vfs_client_data_t *) async_get_client_data())
 #define FILES		(VFS_DATA->files)
 
@@ -79,5 +79,4 @@
 	for (i = 0; i < MAX_OPEN_FILES; i++) {
 		if (FILES[i]) {
-			(void) vfs_close_internal(FILES[i]);
 			(void) vfs_fd_free(i);
 		}
@@ -108,4 +107,23 @@
 }
 
+/** Close the file in the endpoint FS server. */
+static int vfs_file_close_remote(vfs_file_t *file)
+{
+	assert(!file->refcnt);
+	
+	async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle);
+	
+	ipc_call_t answer;
+	aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->devmap_handle,
+	    file->node->index, &answer);
+	
+	vfs_exchange_release(exch);
+	
+	sysarg_t rc;
+	async_wait_for(msg, &rc);
+	
+	return IPC_GET_ARG1(answer);
+}
+
 /** Increment reference count of VFS file structure.
  *
@@ -125,16 +143,21 @@
  *			decremented.
  */
-static void vfs_file_delref(vfs_file_t *file)
-{
+static int vfs_file_delref(vfs_file_t *file)
+{
+	int rc = EOK;
+
 	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
 
 	if (file->refcnt-- == 1) {
 		/*
-		 * Lost the last reference to a file, need to drop our reference
-		 * to the underlying VFS node.
+		 * Lost the last reference to a file, need to close it in the
+		 * endpoint FS and drop our reference to the underlying VFS node.
 		 */
+		rc = vfs_file_close_remote(file);
 		vfs_node_delref(file->node);
 		free(file);
 	}
+
+	return rc;
 }
 
@@ -201,4 +224,6 @@
 int vfs_fd_free(int fd)
 {
+	int rc;
+
 	if (!vfs_files_init())
 		return ENOMEM;
@@ -210,9 +235,9 @@
 	}
 	
-	vfs_file_delref(FILES[fd]);
+	rc = vfs_file_delref(FILES[fd]);
 	FILES[fd] = NULL;
 	fibril_mutex_unlock(&VFS_DATA->lock);
 	
-	return EOK;
+	return rc;
 }
 
Index: uspace/srv/vfs/vfs_lookup.c
===================================================================
--- uspace/srv/vfs/vfs_lookup.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/vfs/vfs_lookup.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -50,5 +50,5 @@
 
 FIBRIL_MUTEX_INITIALIZE(plb_mutex);
-LIST_INITIALIZE(plb_head);	/**< PLB entry ring buffer. */
+LIST_INITIALIZE(plb_entries);	/**< PLB entry ring buffer. */
 uint8_t *plb = NULL;
 
@@ -102,12 +102,12 @@
 	size_t last;	/* the last free index */
 
-	if (list_empty(&plb_head)) {
+	if (list_empty(&plb_entries)) {
 		first = 0;
 		last = PLB_SIZE - 1;
 	} else {
-		plb_entry_t *oldest = list_get_instance(plb_head.next,
-		    plb_entry_t, plb_link);
-		plb_entry_t *newest = list_get_instance(plb_head.prev,
-		    plb_entry_t, plb_link);
+		plb_entry_t *oldest = list_get_instance(
+		    list_first(&plb_entries), plb_entry_t, plb_link);
+		plb_entry_t *newest = list_get_instance(
+		    list_last(&plb_entries), plb_entry_t, plb_link);
 
 		first = (newest->index + newest->len) % PLB_SIZE;
@@ -145,5 +145,5 @@
 	 * buffer.
 	 */
-	list_append(&entry.plb_link, &plb_head);
+	list_append(&entry.plb_link, &plb_entries);
 	
 	fibril_mutex_unlock(&plb_mutex);
@@ -159,6 +159,6 @@
 
 	ipc_call_t answer;
-	int phone = vfs_grab_phone(root->fs_handle);
-	aid_t req = async_send_5(phone, VFS_OUT_LOOKUP, (sysarg_t) first,
+	async_exch_t *exch = vfs_exchange_grab(root->fs_handle);
+	aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first,
 	    (sysarg_t) (first + len - 1) % PLB_SIZE,
 	    (sysarg_t) root->devmap_handle, (sysarg_t) lflag, (sysarg_t) index,
@@ -167,5 +167,5 @@
 	sysarg_t rc;
 	async_wait_for(req, &rc);
-	vfs_release_phone(root->fs_handle, phone);
+	vfs_exchange_release(exch);
 	
 	fibril_mutex_lock(&plb_mutex);
@@ -208,8 +208,8 @@
 int vfs_open_node_internal(vfs_lookup_res_t *result)
 {
-	int phone = vfs_grab_phone(result->triplet.fs_handle);
+	async_exch_t *exch = vfs_exchange_grab(result->triplet.fs_handle);
 	
 	ipc_call_t answer;
-	aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE,
+	aid_t req = async_send_2(exch, VFS_OUT_OPEN_NODE,
 	    (sysarg_t) result->triplet.devmap_handle,
 	    (sysarg_t) result->triplet.index, &answer);
@@ -217,5 +217,5 @@
 	sysarg_t rc;
 	async_wait_for(req, &rc);
-	vfs_release_phone(result->triplet.fs_handle, phone);
+	vfs_exchange_release(exch);
 	
 	if (rc == EOK) {
Index: uspace/srv/vfs/vfs_node.c
===================================================================
--- uspace/srv/vfs/vfs_node.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/vfs/vfs_node.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -104,11 +104,14 @@
 	bool free_vfs_node = false;
 	bool free_fs_node = false;
-
-	fibril_mutex_lock(&nodes_mutex);
+	
+	fibril_mutex_lock(&nodes_mutex);
+	
 	if (node->refcnt-- == 1) {
+		
 		/*
 		 * We are dropping the last reference to this node.
 		 * Remove it from the VFS node hash table.
 		 */
+		
 		unsigned long key[] = {
 			[KEY_FS_HANDLE] = node->fs_handle,
@@ -116,23 +119,29 @@
 			[KEY_INDEX] = node->index
 		};
+		
 		hash_table_remove(&nodes, key, 3);
 		free_vfs_node = true;
+		
 		if (!node->lnkcnt)
 			free_fs_node = true;
 	}
-	fibril_mutex_unlock(&nodes_mutex);
-
+	
+	fibril_mutex_unlock(&nodes_mutex);
+	
 	if (free_fs_node) {
-		/* 
+		
+		/*
 		 * The node is not visible in the file system namespace.
 		 * Free up its resources.
 		 */
-		int phone = vfs_grab_phone(node->fs_handle);
-		sysarg_t rc;
-		rc = async_req_2_0(phone, VFS_OUT_DESTROY,
-		    (sysarg_t)node->devmap_handle, (sysarg_t)node->index);
+		
+		async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
+		sysarg_t rc = async_req_2_0(exch, VFS_OUT_DESTROY,
+		    (sysarg_t) node->devmap_handle, (sysarg_t)node->index);
+		
 		assert(rc == EOK);
-		vfs_release_phone(node->fs_handle, phone);
+		vfs_exchange_release(exch);
 	}
+	
 	if (free_vfs_node)
 		free(node);
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/vfs/vfs_ops.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -76,8 +76,8 @@
 	vfs_node_t *mr_node;
 	fs_index_t rindex;
-	size_t rsize;
+	aoff64_t rsize;
 	unsigned rlnkcnt;
+	async_exch_t *exch;
 	sysarg_t rc;
-	int phone;
 	aid_t msg;
 	ipc_call_t answer;
@@ -123,13 +123,14 @@
 			
 			/* Tell the mountee that it is being mounted. */
-			phone = vfs_grab_phone(fs_handle);
-			msg = async_send_1(phone, VFS_OUT_MOUNTED,
+			exch = vfs_exchange_grab(fs_handle);
+			msg = async_send_1(exch, VFS_OUT_MOUNTED,
 			    (sysarg_t) devmap_handle, &answer);
-			/* send the mount options */
-			rc = async_data_write_start(phone, (void *)opts,
+			/* Send the mount options */
+			rc = async_data_write_start(exch, (void *)opts,
 			    str_size(opts));
+			vfs_exchange_release(exch);
+			
 			if (rc != EOK) {
 				async_wait_for(msg, NULL);
-				vfs_release_phone(fs_handle, phone);
 				fibril_rwlock_write_unlock(&namespace_rwlock);
 				async_answer_0(rid, rc);
@@ -137,5 +138,4 @@
 			}
 			async_wait_for(msg, &rc);
-			vfs_release_phone(fs_handle, phone);
 			
 			if (rc != EOK) {
@@ -146,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;
@@ -182,9 +182,9 @@
 	 */
 	
-	int mountee_phone = vfs_grab_phone(fs_handle);
-	assert(mountee_phone >= 0);
-
-	phone = vfs_grab_phone(mp_res.triplet.fs_handle);
-	msg = async_send_4(phone, VFS_OUT_MOUNT,
+	async_exch_t *mountee_exch = vfs_exchange_grab(fs_handle);
+	assert(mountee_exch);
+	
+	exch = vfs_exchange_grab(mp_res.triplet.fs_handle);
+	msg = async_send_4(exch, VFS_OUT_MOUNT,
 	    (sysarg_t) mp_res.triplet.devmap_handle,
 	    (sysarg_t) mp_res.triplet.index,
@@ -192,40 +192,45 @@
 	    (sysarg_t) devmap_handle, &answer);
 	
-	/* send connection */
-	rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone);
-	if (rc != EOK) {
+	/* Send connection */
+	rc = async_exchange_clone(exch, mountee_exch);
+	vfs_exchange_release(mountee_exch);
+	
+	if (rc != EOK) {
+		vfs_exchange_release(exch);
 		async_wait_for(msg, NULL);
-		vfs_release_phone(fs_handle, mountee_phone);
-		vfs_release_phone(mp_res.triplet.fs_handle, phone);
+		
 		/* Mount failed, drop reference to mp_node. */
 		if (mp_node)
 			vfs_node_put(mp_node);
-		async_answer_0(rid, rc);
-		fibril_rwlock_write_unlock(&namespace_rwlock);
-		return;
-	}
-
-	vfs_release_phone(fs_handle, mountee_phone);
+		
+		async_answer_0(rid, rc);
+		fibril_rwlock_write_unlock(&namespace_rwlock);
+		return;
+	}
 	
 	/* send the mount options */
-	rc = async_data_write_start(phone, (void *)opts, str_size(opts));
-	if (rc != EOK) {
+	rc = async_data_write_start(exch, (void *) opts, str_size(opts));
+	if (rc != EOK) {
+		vfs_exchange_release(exch);
 		async_wait_for(msg, NULL);
-		vfs_release_phone(mp_res.triplet.fs_handle, phone);
+		
 		/* Mount failed, drop reference to mp_node. */
 		if (mp_node)
 			vfs_node_put(mp_node);
-		fibril_rwlock_write_unlock(&namespace_rwlock);
-		async_answer_0(rid, rc);
-		return;
-	}
+		
+		fibril_rwlock_write_unlock(&namespace_rwlock);
+		async_answer_0(rid, rc);
+		return;
+	}
+	
+	vfs_exchange_release(exch);
 	async_wait_for(msg, &rc);
-	vfs_release_phone(mp_res.triplet.fs_handle, phone);
 	
 	if (rc == EOK) {
 		rindex = (fs_index_t) IPC_GET_ARG1(answer);
-		rsize = (size_t) IPC_GET_ARG2(answer);
-		rlnkcnt = (unsigned) IPC_GET_ARG3(answer);
-	
+		rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer),
+		    IPC_GET_ARG3(answer));
+		rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
+		
 		mr_res.triplet.fs_handle = fs_handle;
 		mr_res.triplet.devmap_handle = devmap_handle;
@@ -234,5 +239,5 @@
 		mr_res.lnkcnt = rlnkcnt;
 		mr_res.type = VFS_NODE_DIRECTORY;
-	
+		
 		/* Add reference to the mounted root. */
 		mr_node = vfs_node_get(&mr_res); 
@@ -243,5 +248,5 @@
 			vfs_node_put(mp_node);
 	}
-
+	
 	async_answer_0(rid, rc);
 	fibril_rwlock_write_unlock(&namespace_rwlock);
@@ -303,10 +308,10 @@
 	
 	/*
-	 * Wait for IPC_M_PING so that we can return an error if we don't know
+	 * Wait for VFS_IN_PING so that we can return an error if we don't know
 	 * fs_name.
 	 */
 	ipc_call_t data;
 	ipc_callid_t callid = async_get_call(&data);
-	if (IPC_GET_IMETHOD(data) != IPC_M_PING) {
+	if (IPC_GET_IMETHOD(data) != VFS_IN_PING) {
 		async_answer_0(callid, ENOTSUP);
 		async_answer_0(rid, ENOTSUP);
@@ -321,5 +326,5 @@
 	 * This will also give us its file system handle.
 	 */
-	fibril_mutex_lock(&fs_head_lock);
+	fibril_mutex_lock(&fs_list_lock);
 	fs_handle_t fs_handle;
 recheck:
@@ -327,9 +332,9 @@
 	if (!fs_handle) {
 		if (flags & IPC_FLAG_BLOCKING) {
-			fibril_condvar_wait(&fs_head_cv, &fs_head_lock);
+			fibril_condvar_wait(&fs_list_cv, &fs_list_lock);
 			goto recheck;
 		}
 		
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		async_answer_0(callid, ENOENT);
 		async_answer_0(rid, ENOENT);
@@ -339,5 +344,5 @@
 		return;
 	}
-	fibril_mutex_unlock(&fs_head_lock);
+	fibril_mutex_unlock(&fs_list_lock);
 	
 	/* Acknowledge that we know fs_name. */
@@ -358,6 +363,6 @@
 	vfs_lookup_res_t mr_res;
 	vfs_node_t *mr_node;
-	int phone;
-
+	async_exch_t *exch;
+	
 	/*
 	 * Receive the mount point path.
@@ -367,5 +372,5 @@
 	if (rc != EOK)
 		async_answer_0(rid, rc);
-
+	
 	/*
 	 * Taking the namespace lock will do two things for us. First, it will
@@ -395,5 +400,5 @@
 		return;
 	}
-
+	
 	/*
 	 * Count the total number of references for the mounted file system. We
@@ -411,7 +416,7 @@
 		return;
 	}
-
+	
 	if (str_cmp(mp, "/") == 0) {
-
+		
 		/*
 		 * Unmounting the root file system.
@@ -420,10 +425,12 @@
 		 * VFS_OUT_UNMOUNTED directly to the mounted file system.
 		 */
-
+		
 		free(mp);
-		phone = vfs_grab_phone(mr_node->fs_handle);
-		rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
+		
+		exch = vfs_exchange_grab(mr_node->fs_handle);
+		rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED,
 		    mr_node->devmap_handle);
-		vfs_release_phone(mr_node->fs_handle, phone);
+		vfs_exchange_release(exch);
+		
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
@@ -432,8 +439,9 @@
 			return;
 		}
+		
 		rootfs.fs_handle = 0;
 		rootfs.devmap_handle = 0;
 	} else {
-
+		
 		/*
 		 * Unmounting a non-root file system.
@@ -442,5 +450,5 @@
 		 * file system, so we delegate the operation to it.
 		 */
-
+		
 		rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
 		free(mp);
@@ -451,4 +459,5 @@
 			return;
 		}
+		
 		vfs_node_t *mp_node = vfs_node_get(&mp_res);
 		if (!mp_node) {
@@ -458,9 +467,10 @@
 			return;
 		}
-
-		phone = vfs_grab_phone(mp_node->fs_handle);
-		rc = async_req_2_0(phone, VFS_OUT_UNMOUNT,
+		
+		exch = vfs_exchange_grab(mp_node->fs_handle);
+		rc = async_req_2_0(exch, VFS_OUT_UNMOUNT,
 		    mp_node->devmap_handle, mp_node->index);
-		vfs_release_phone(mp_node->fs_handle, phone);
+		vfs_exchange_release(exch);
+		
 		if (rc != EOK) {
 			fibril_rwlock_write_unlock(&namespace_rwlock);
@@ -470,5 +480,5 @@
 			return;
 		}
-
+		
 		/* Drop the reference we got above. */
 		vfs_node_put(mp_node);
@@ -476,6 +486,5 @@
 		vfs_node_put(mp_node);
 	}
-
-
+	
 	/*
 	 * All went well, the mounted file system was successfully unmounted.
@@ -483,5 +492,5 @@
 	 */
 	vfs_node_forget(mr_node);
-
+	
 	fibril_rwlock_write_unlock(&namespace_rwlock);
 	async_answer_0(rid, EOK);
@@ -698,75 +707,28 @@
 	 */
 	fibril_mutex_lock(&file->lock);
-	int fs_phone = vfs_grab_phone(file->node->fs_handle);
+	async_exch_t *fs_exch = vfs_exchange_grab(file->node->fs_handle);
 	
 	/* Make a VFS_OUT_SYMC request at the destination FS server. */
 	aid_t msg;
 	ipc_call_t answer;
-	msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->devmap_handle,
+	msg = async_send_2(fs_exch, VFS_OUT_SYNC, file->node->devmap_handle,
 	    file->node->index, &answer);
-
+	
+	vfs_exchange_release(fs_exch);
+	
 	/* Wait for reply from the FS server. */
 	sysarg_t rc;
 	async_wait_for(msg, &rc);
 	
-	vfs_release_phone(file->node->fs_handle, fs_phone);
 	fibril_mutex_unlock(&file->lock);
-
+	
 	vfs_file_put(file);
 	async_answer_0(rid, rc);
 }
 
-int vfs_close_internal(vfs_file_t *file)
-{
-	/*
-	 * Lock the open file structure so that no other thread can manipulate
-	 * the same open file at a time.
-	 */
-	fibril_mutex_lock(&file->lock);
-	
-	if (file->refcnt <= 1) {
-		/* Only close the file on the destination FS server
-		   if there are no more file descriptors (except the
-		   present one) pointing to this file. */
-		
-		int fs_phone = vfs_grab_phone(file->node->fs_handle);
-		
-		/* Make a VFS_OUT_CLOSE request at the destination FS server. */
-		aid_t msg;
-		ipc_call_t answer;
-		msg = async_send_2(fs_phone, VFS_OUT_CLOSE,
-		    file->node->devmap_handle, file->node->index, &answer);
-		
-		/* Wait for reply from the FS server. */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		
-		vfs_release_phone(file->node->fs_handle, fs_phone);
-		fibril_mutex_unlock(&file->lock);
-		
-		return IPC_GET_ARG1(answer);
-	}
-	
-	fibril_mutex_unlock(&file->lock);
-	return EOK;
-}
-
 void vfs_close(ipc_callid_t rid, ipc_call_t *request)
 {
 	int fd = IPC_GET_ARG1(*request);
-	
-	/* Lookup the file structure corresponding to the file descriptor. */
-	vfs_file_t *file = vfs_file_get(fd);
-	if (!file) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
-	
-	int ret = vfs_close_internal(file);
-	if (ret != EOK)
-		async_answer_0(rid, ret);
-	
-	vfs_file_put(file);
-	ret = vfs_fd_free(fd);
+	int ret = vfs_fd_free(fd);
 	async_answer_0(rid, ret);
 }
@@ -774,6 +736,4 @@
 static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read)
 {
-	vfs_info_t *vi;
-
 	/*
 	 * The following code strongly depends on the fact that the files data
@@ -785,5 +745,5 @@
 	 * open files supports parallel access!
 	 */
-
+	
 	int fd = IPC_GET_ARG1(*request);
 	
@@ -800,8 +760,8 @@
 	 */
 	fibril_mutex_lock(&file->lock);
-
-	vi = fs_handle_to_info(file->node->fs_handle);
-	assert(vi);
-
+	
+	vfs_info_t *fs_info = fs_handle_to_info(file->node->fs_handle);
+	assert(fs_info);
+	
 	/*
 	 * Lock the file's node so that no other client can read/write to it at
@@ -809,9 +769,10 @@
 	 * write implementation does not modify the file size.
 	 */
-	if (read || (vi->concurrent_read_write && vi->write_retains_size))
+	if ((read) ||
+	    ((fs_info->concurrent_read_write) && (fs_info->write_retains_size)))
 		fibril_rwlock_read_lock(&file->node->contents_rwlock);
 	else
 		fibril_rwlock_write_lock(&file->node->contents_rwlock);
-
+	
 	if (file->node->type == VFS_NODE_DIRECTORY) {
 		/*
@@ -823,5 +784,5 @@
 	}
 	
-	int fs_phone = vfs_grab_phone(file->node->fs_handle);
+	async_exch_t *fs_exch = vfs_exchange_grab(file->node->fs_handle);
 	
 	/*
@@ -835,17 +796,17 @@
 	ipc_call_t answer;
 	if (read) {
-		rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ,
-		    file->node->devmap_handle, file->node->index, file->pos,
-		    &answer);
+		rc = async_data_read_forward_4_1(fs_exch, VFS_OUT_READ,
+		    file->node->devmap_handle, file->node->index,
+		    LOWER32(file->pos), UPPER32(file->pos), &answer);
 	} else {
 		if (file->append)
 			file->pos = file->node->size;
 		
-		rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE,
-		    file->node->devmap_handle, file->node->index, file->pos,
-		    &answer);
-	}
-	
-	vfs_release_phone(file->node->fs_handle, fs_phone);
+		rc = async_data_write_forward_4_1(fs_exch, VFS_OUT_WRITE,
+		    file->node->devmap_handle, file->node->index,
+		    LOWER32(file->pos), UPPER32(file->pos), &answer);
+	}
+	
+	vfs_exchange_release(fs_exch);
 	
 	size_t bytes = IPC_GET_ARG1(answer);
@@ -855,10 +816,12 @@
 	
 	/* Unlock the VFS node. */
-	if (read || (vi->concurrent_read_write && vi->write_retains_size))
+	if ((read) ||
+	    ((fs_info->concurrent_read_write) && (fs_info->write_retains_size)))
 		fibril_rwlock_read_unlock(&file->node->contents_rwlock);
 	else {
 		/* Update the cached version of node's size. */
 		if (rc == EOK)
-			file->node->size = IPC_GET_ARG2(answer); 
+			file->node->size = MERGE_LOUP32(IPC_GET_ARG2(answer),
+			    IPC_GET_ARG3(answer));
 		fibril_rwlock_write_unlock(&file->node->contents_rwlock);
 	}
@@ -975,12 +938,11 @@
     fs_index_t index, aoff64_t size)
 {
-	sysarg_t rc;
-	int fs_phone;
-	
-	fs_phone = vfs_grab_phone(fs_handle);
-	rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (sysarg_t) devmap_handle,
-	    (sysarg_t) index, LOWER32(size), UPPER32(size));
-	vfs_release_phone(fs_handle, fs_phone);
-	return (int)rc;
+	async_exch_t *exch = vfs_exchange_grab(fs_handle);
+	sysarg_t rc = async_req_4_0(exch, VFS_OUT_TRUNCATE,
+	    (sysarg_t) devmap_handle, (sysarg_t) index, LOWER32(size),
+	    UPPER32(size));
+	vfs_exchange_release(exch);
+	
+	return (int) rc;
 }
 
@@ -1032,13 +994,15 @@
 	fibril_mutex_lock(&file->lock);
 
-	int fs_phone = vfs_grab_phone(file->node->fs_handle);
+	async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle);
 	
 	aid_t msg;
-	msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->devmap_handle,
+	msg = async_send_3(exch, VFS_OUT_STAT, file->node->devmap_handle,
 	    file->node->index, true, NULL);
-	async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	
+	vfs_exchange_release(exch);
+	
 	async_wait_for(msg, &rc);
-	vfs_release_phone(file->node->fs_handle, fs_phone);
-
+	
 	fibril_mutex_unlock(&file->lock);
 	vfs_file_put(file);
@@ -1083,13 +1047,15 @@
 	fibril_rwlock_read_unlock(&namespace_rwlock);
 
-	int fs_phone = vfs_grab_phone(node->fs_handle);
+	async_exch_t *exch = vfs_exchange_grab(node->fs_handle);
+	
 	aid_t msg;
-	msg = async_send_3(fs_phone, VFS_OUT_STAT, node->devmap_handle,
+	msg = async_send_3(exch, VFS_OUT_STAT, node->devmap_handle,
 	    node->index, false, NULL);
-	async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
+	
+	vfs_exchange_release(exch);
 	
 	sysarg_t rv;
 	async_wait_for(msg, &rv);
-	vfs_release_phone(node->fs_handle, fs_phone);
 
 	async_answer_0(rid, rv);
@@ -1369,27 +1335,6 @@
 	fibril_mutex_lock(&oldfile->lock);
 	
-	/* Lookup an open file structure possibly corresponding to newfd. */
-	vfs_file_t *newfile = vfs_file_get(newfd);
-	if (newfile) {
-		/* Close the originally opened file. */
-		int ret = vfs_close_internal(newfile);
-		if (ret != EOK) {
-			fibril_mutex_unlock(&oldfile->lock);
-			vfs_file_put(oldfile);
-			vfs_file_put(newfile);
-			async_answer_0(rid, ret);
-			return;
-		}
-		
-		ret = vfs_fd_free(newfd);
-		if (ret != EOK) {
-			fibril_mutex_unlock(&oldfile->lock);
-			vfs_file_put(oldfile);
-			vfs_file_put(newfile);
-			async_answer_0(rid, ret);
-			return;
-		}
-		vfs_file_put(newfile);
-	}
+	/* Make sure newfd is closed. */
+	(void) vfs_fd_free(newfd);
 	
 	/* Assign the old file to newfd. */
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 52a79081375224a3ebc071ecbc731350c060da53)
+++ uspace/srv/vfs/vfs_register.c	(revision a33f0a6ce7a627f4c6fcdb892ee61a9214fbbed3)
@@ -52,7 +52,7 @@
 #include "vfs.h"
 
-FIBRIL_CONDVAR_INITIALIZE(fs_head_cv);
-FIBRIL_MUTEX_INITIALIZE(fs_head_lock);
-LIST_INITIALIZE(fs_head);
+FIBRIL_CONDVAR_INITIALIZE(fs_list_cv);
+FIBRIL_MUTEX_INITIALIZE(fs_list_lock);
+LIST_INITIALIZE(fs_list);
 
 atomic_t fs_handle_next = {
@@ -62,12 +62,13 @@
 /** Verify the VFS info structure.
  *
- * @param info		Info structure to be verified.
- *
- * @return		Non-zero if the info structure is sane, zero otherwise.
+ * @param info Info structure to be verified.
+ *
+ * @return Non-zero if the info structure is sane, zero otherwise.
+ *
  */
 static bool vfs_info_sane(vfs_info_t *info)
 {
 	int i;
-
+	
 	/*
 	 * Check if the name is non-empty and is composed solely of ASCII
@@ -78,4 +79,5 @@
 		return false;
 	}
+	
 	for (i = 1; i < FS_NAME_MAXLEN; i++) {
 		if (!(islower(info->name[i]) || isdigit(info->name[i])) &&
@@ -90,4 +92,5 @@
 		}
 	}
+	
 	/*
 	 * This check is not redundant. It ensures that the name is
@@ -104,11 +107,10 @@
 /** VFS_REGISTER protocol function.
  *
- * @param rid		Hash of the call with the request.
- * @param request	Call structure with the request.
+ * @param rid     Hash of the call with the request.
+ * @param request Call structure with the request.
+ *
  */
 void vfs_register(ipc_callid_t rid, ipc_call_t *request)
 {
-	int phone;
-	
 	dprintf("Processing VFS_REGISTER request received from %p.\n",
 	    request->in_phone_hash);
@@ -147,5 +149,5 @@
 	}
 	
-	fibril_mutex_lock(&fs_head_lock);
+	fibril_mutex_lock(&fs_list_lock);
 	
 	/*
@@ -157,5 +159,5 @@
 		 */
 		dprintf("FS is already registered.\n");
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
 		free(fs_info);
 		async_answer_0(rid, EEXISTS);
@@ -167,5 +169,5 @@
 	 */
 	dprintf("Inserting FS into the list of registered file systems.\n");
-	list_append(&fs_info->fs_link, &fs_head);
+	list_append(&fs_info->fs_link, &fs_list);
 	
 	/*
@@ -174,20 +176,14 @@
 	 * which to forward VFS requests to it.
 	 */
-	ipc_call_t call;
-	ipc_callid_t callid = async_get_call(&call);
-	if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
-		dprintf("Unexpected call, method = %d\n", IPC_GET_IMETHOD(call));
+	fs_info->sess = async_callback_receive(EXCHANGE_PARALLEL);
+	if (!fs_info->sess) {
+		dprintf("Callback connection expected\n");
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
-		free(fs_info);
-		async_answer_0(callid, EINVAL);
+		fibril_mutex_unlock(&fs_list_lock);
+		free(fs_info);
 		async_answer_0(rid, EINVAL);
 		return;
 	}
 	
-	phone = IPC_GET_ARG5(call);
-	async_session_create(&fs_info->session, phone, 0);
-	async_answer_0(callid, EOK);
-	
 	dprintf("Callback connection to FS created.\n");
 	
@@ -197,10 +193,10 @@
 	
 	size_t size;
+	ipc_callid_t callid;
 	if (!async_share_in_receive(&callid, &size)) {
 		dprintf("Unexpected call, method = %d\n", IPC_GET_IMETHOD(call));
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
-		async_session_destroy(&fs_info->session);
-		async_hangup(phone);
+		fibril_mutex_unlock(&fs_list_lock);
+		async_hangup(fs_info->sess);
 		free(fs_info);
 		async_answer_0(callid, EINVAL);
@@ -215,7 +211,6 @@
 		dprintf("Client suggests wrong size of PFB, size = %d\n", size);
 		list_remove(&fs_info->fs_link);
-		fibril_mutex_unlock(&fs_head_lock);
-		async_session_destroy(&fs_info->session);
-		async_hangup(phone);
+		fibril_mutex_unlock(&fs_list_lock);
+		async_hangup(fs_info->sess);
 		free(fs_info);
 		async_answer_0(callid, EINVAL);
@@ -240,6 +235,6 @@
 	async_answer_1(rid, EOK, (sysarg_t) fs_info->fs_handle);
 	
-	fibril_condvar_broadcast(&fs_head_cv);
-	fibril_mutex_unlock(&fs_head_lock);
+	fibril_condvar_broadcast(&fs_list_cv);
+	fibril_mutex_unlock(&fs_list_lock);
 	
 	dprintf("\"%.*s\" filesystem successfully registered, handle=%d.\n",
@@ -247,69 +242,58 @@
 }
 
-/** For a given file system handle, implement policy for allocating a phone.
- *
- * @param handle	File system handle.
- *
- * @return		Phone over which a multi-call request can be safely
- *			sent. Return 0 if no phone was found.
- */
-int vfs_grab_phone(fs_handle_t handle)
-{
-	link_t *cur;
-	fs_info_t *fs;
-	int phone;
-
-	/*
-	 * For now, we don't try to be very clever and very fast.  We simply
-	 * lookup the phone in the fs_head list and duplicate it.  The duplicate
-	 * phone will be returned to the client and the client will use it for
-	 * communication.  In the future, we should cache the connections so
-	 * that they do not have to be reestablished over and over again.
-	 */
-	fibril_mutex_lock(&fs_head_lock);
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
-		fs = list_get_instance(cur, fs_info_t, fs_link);
+/** Begin an exchange for a given file system handle
+ *
+ * @param handle File system handle.
+ *
+ * @return Exchange for a multi-call request.
+ * @return NULL if no such file exists.
+ *
+ */
+async_exch_t *vfs_exchange_grab(fs_handle_t handle)
+{
+	/*
+	 * For now, we don't try to be very clever and very fast.
+	 * We simply lookup the session in fs_list and
+	 * begin an exchange.
+	 */
+	fibril_mutex_lock(&fs_list_lock);
+	
+	list_foreach(fs_list, cur) {
+		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
+		
 		if (fs->fs_handle == handle) {
-			fibril_mutex_unlock(&fs_head_lock);
-			phone = async_exchange_begin(&fs->session);
-
-			assert(phone > 0);
-			return phone;
+			fibril_mutex_unlock(&fs_list_lock);
+			
+			assert(fs->sess);
+			async_exch_t *exch = async_exchange_begin(fs->sess);
+			
+			assert(exch);
+			return exch;
 		}
 	}
-	fibril_mutex_unlock(&fs_head_lock);
-	return 0;
-}
-
-/** Tell VFS that the phone is not needed anymore.
- *
- * @param phone		Phone to FS task.
- */
-void vfs_release_phone(fs_handle_t handle, int phone)
-{
-	link_t *cur;
-	fs_info_t *fs;
-
-	fibril_mutex_lock(&fs_head_lock);
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
-		fs = list_get_instance(cur, fs_info_t, fs_link);
-		if (fs->fs_handle == handle) {
-			fibril_mutex_unlock(&fs_head_lock);
-			async_exchange_end(&fs->session, phone);
-			return;
-		}
-	}
-	/* should not really get here */
-	abort();
-	fibril_mutex_unlock(&fs_head_lock);
+	
+	fibril_mutex_unlock(&fs_list_lock);
+	
+	return NULL;
+}
+
+/** End VFS server exchange.
+ *
+ * @param exch   VFS server exchange.
+ *
+ */
+void vfs_exchange_release(async_exch_t *exch)
+{
+	async_exchange_end(exch);
 }
 
 /** Convert file system name to its handle.
  *
- * @param name		File system name.
- * @param lock		If true, the function will lock and unlock the
- * 			fs_head_lock.
- *
- * @return		File system handle or zero if file system not found.
+ * @param name File system name.
+ * @param lock If true, the function will lock and unlock the
+ *             fs_list_lock.
+ *
+ * @return File system handle or zero if file system not found.
+ *
  */
 fs_handle_t fs_name_to_handle(char *name, bool lock)
@@ -318,7 +302,7 @@
 	
 	if (lock)
-		fibril_mutex_lock(&fs_head_lock);
-	link_t *cur;
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+		fibril_mutex_lock(&fs_list_lock);
+	
+	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
 		if (str_cmp(fs->vfs_info.name, name) == 0) { 
@@ -327,6 +311,8 @@
 		}
 	}
+	
 	if (lock)
-		fibril_mutex_unlock(&fs_head_lock);
+		fibril_mutex_unlock(&fs_list_lock);
+	
 	return handle;
 }
@@ -334,14 +320,15 @@
 /** Find the VFS info structure.
  *
- * @param handle	FS handle for which the VFS info structure is sought.
- * @return		VFS info structure on success or NULL otherwise.
+ * @param handle FS handle for which the VFS info structure is sought.
+ *
+ * @return VFS info structure on success or NULL otherwise.
+ *
  */
 vfs_info_t *fs_handle_to_info(fs_handle_t handle)
 {
 	vfs_info_t *info = NULL;
-	link_t *cur;
-
-	fibril_mutex_lock(&fs_head_lock);
-	for (cur = fs_head.next; cur != &fs_head; cur = cur->next) {
+	
+	fibril_mutex_lock(&fs_list_lock);
+	list_foreach(fs_list, cur) {
 		fs_info_t *fs = list_get_instance(cur, fs_info_t, fs_link);
 		if (fs->fs_handle == handle) { 
@@ -350,6 +337,6 @@
 		}
 	}
-	fibril_mutex_unlock(&fs_head_lock);
-
+	fibril_mutex_unlock(&fs_list_lock);
+	
 	return info;
 }
@@ -357,3 +344,3 @@
 /**
  * @}
- */ 
+ */
