Index: console/console.c
===================================================================
--- console/console.c	(revision 3993b3d0b46275e928586a8893675056e87e7cf1)
+++ console/console.c	(revision c1d2c9dd2e8ed998a195ce76e6c2cb87a660d0d7)
@@ -41,10 +41,4 @@
 #include <screenbuffer.h>
 
-static void sysput(char c)
-{
-	__SYSCALL3(SYS_IO, 1, &c, 1);
-}
-
-//#define CONSOLE_COUNT VFB_CONNECTIONS
 #define CONSOLE_COUNT 8
 #define MAX_KEYREQUESTS_BUFFERED 32
@@ -103,5 +97,6 @@
 	int retval;
 	int i, j;
-	char c;
+	char c,d;
+	connection_t *conn;
 
 	/* Ignore parameters, the connection is alread opened */
@@ -118,21 +113,23 @@
 			retval = 0;
 			c = IPC_GET_ARG1(call);
-//			ipc_call_sync_2(connections[3].vfb_phone, FB_PUTCHAR, 0, c,NULL,NULL);
-		
 			/* switch to another virtual console */
 			
+			conn = &connections[active_console];
 			if ((c >= KBD_KEY_F1) && (c < KBD_KEY_F1 + CONSOLE_COUNT)) {
 				/*FIXME: draw another console content from buffer */
 
 				active_console = c - KBD_KEY_F1;
+				conn = &connections[active_console];
+
+				ipc_call_async(fb_info.phone, FB_CURSOR_VISIBILITY, 0, NULL, NULL); 
 				ipc_call_async_2(fb_info.phone, FB_CLEAR, 0, 0, NULL, NULL);
-				ipc_call_sync_3(fb_info.phone, FB_PUTCHAR, 'a', 0, 0,NULL,NULL, NULL);
-				
-				for (i = 0; i < connections[active_console].screenbuffer.size_x; i++)
-					for (j = 0; j < connections[active_console].screenbuffer.size_y; j++) {
-					
-					ipc_call_async_3(fb_info.phone, FB_PUTCHAR, get_field_at(&(connections[active_console].screenbuffer),\
-								i, j)->character, j, i, NULL, NULL, NULL);
-				}
+				for (i = 0; i < conn->screenbuffer.size_x; i++)
+					for (j = 0; j < conn->screenbuffer.size_y; j++) {
+						d = get_field_at(&(conn->screenbuffer),i, j)->character;
+						if (d && d != ' ')
+							ipc_call_async_3(fb_info.phone, FB_PUTCHAR, d, j, i, NULL, NULL);
+					}
+				ipc_call_async_2(fb_info.phone, FB_CURSOR_GOTO, conn->screenbuffer.position_y, conn->screenbuffer.position_x, NULL, NULL); 
+				ipc_call_async(fb_info.phone, FB_CURSOR_VISIBILITY, 1, NULL, NULL); 
 
 				break;
@@ -140,17 +137,13 @@
 			
 			/* if client is awaiting key, send it */
-			if (connections[active_console].keyrequest_counter > 0) {		
-				connections[active_console].keyrequest_counter--;
-				ipc_answer_fast(fifo_pop(connections[active_console].keyrequests), 0, c, 0);
+			if (conn->keyrequest_counter > 0) {		
+				conn->keyrequest_counter--;
+				ipc_answer_fast(fifo_pop(conn->keyrequests), 0, c, 0);
 				break;
 			}
 			
 			/*FIXME: else store key to its buffer */
-			keybuffer_push(&(connections[active_console].keybuffer), c);
-			
-			/* Send it to first FB, DEBUG */
-//			ipc_call_async_2(connections[0].vfb_phone, FB_PUTCHAR, 0, IPC_GET_ARG1(call),NULL,NULL);
-//			ipc_call_sync_2(connections[4].vfb_phone, FB_PUTCHAR, 0, c,NULL,NULL);
-
+			keybuffer_push(&conn->keybuffer, c);
+			
 			break;
 		default:
@@ -192,6 +185,6 @@
 			/* Send message to fb */
 			if (consnum == active_console) {
-				ipc_call_sync_3(fb_info.phone, FB_PUTCHAR, IPC_GET_ARG2(call), connections[consnum].screenbuffer.position_y, \
-						connections[consnum].screenbuffer.position_x, NULL, NULL, NULL); 
+				ipc_call_async_3(fb_info.phone, FB_PUTCHAR, IPC_GET_ARG2(call), connections[consnum].screenbuffer.position_y, \
+						connections[consnum].screenbuffer.position_x, NULL, NULL); 
 			}
 			
@@ -226,5 +219,4 @@
 			};
 			keybuffer_pop(&(connections[consnum].keybuffer), (char *)&arg1);
-//			ipc_call_sync_2(connections[6].vfb_phone, FB_PUTCHAR, 0, arg1,NULL,NULL);
 			
 			break;
@@ -258,13 +250,11 @@
 	}
 	
-	ipc_call_sync_3(fb_info.phone, FB_PUTCHAR, '1', 0, 0,NULL,NULL, NULL);
 	ipc_call_sync_2(fb_info.phone, FB_GET_CSIZE, 0, 0, &(fb_info.rows), &(fb_info.cols)); 
+	ipc_call_sync(fb_info.phone, FB_CURSOR_VISIBILITY, 1, NULL); 
 	
 	/* Init virtual consoles */
 	for (i = 0; i < CONSOLE_COUNT; i++) {
-		ipc_call_sync_3(fb_info.phone, FB_PUTCHAR, '$', 2*i, 1,NULL,NULL, NULL);
 		connections[i].used = 0;
 		keybuffer_init(&(connections[i].keybuffer));
-		ipc_call_sync_3(fb_info.phone, FB_PUTCHAR, '>', 2*i+1, 1,NULL,NULL, NULL);
 		
 		connections[i].keyrequests.head = connections[i].keyrequests.tail = 0;
@@ -272,5 +262,4 @@
 		connections[i].keyrequest_counter = 0;
 		
-		ipc_call_sync_3(fb_info.phone, FB_PUTCHAR, '?', 2*i+1, 1,NULL,NULL, NULL);
 		if (screenbuffer_init(&(connections[i].screenbuffer), fb_info.cols, fb_info.rows ) == NULL) {
 			/*FIXME: handle error */
@@ -283,5 +272,4 @@
 	};
 	
-	ipc_call_sync_3(fb_info.phone, FB_PUTCHAR, 'M', 3, 3,NULL,NULL, NULL);
 	async_manager();
 
Index: fb/fb.c
===================================================================
--- fb/fb.c	(revision 3993b3d0b46275e928586a8893675056e87e7cf1)
+++ fb/fb.c	(revision c1d2c9dd2e8ed998a195ce76e6c2cb87a660d0d7)
@@ -269,5 +269,5 @@
 
 /** Invert character at given position */
-static void invert_char(int vp,unsigned int col, unsigned int row)
+static void invert_char(int vp,unsigned int row, unsigned int col)
 {
 	unsigned int x;
@@ -334,4 +334,8 @@
 	viewports[i].fgcolor = DEFAULT_FGCOLOR;
 	
+	viewports[i].cur_col = 0;
+	viewports[i].cur_row = 0;
+	viewports[i].cursor_active = 0;
+
 	viewports[i].initialized = 1;
 
@@ -416,23 +420,25 @@
 }
 
-static void draw_char(int vp, char c, unsigned int col, unsigned int row)
+static void draw_char(int vp, char c, unsigned int row, unsigned int col)
 {
 	viewport_t *vport = &viewports[vp];
 
 	if (vport->cursor_active && (vport->cur_col != col || vport->cur_row != row))
-		invert_char(vp, vport->cur_col,vport->cur_row);
-	
-	draw_glyph(vp, c, col, row);
-	
-	if (vport->cursor_active) {
-		vport->cur_col++;
-		if (vport->cur_col>= vport->cols) {
-			vport->cur_col = 0;
-			vport->cur_row++;
-			if (vport->cur_row >= vport->rows)
-				vport->cur_row--;
-		}
-		invert_char(vp, vport->cur_col,vport->cur_row);
+		invert_char(vp, vport->cur_row, vport->cur_col);
+	
+	draw_glyph(vp, c, row, col);
+
+	vport->cur_col = col;
+	vport->cur_row = row;
+
+	vport->cur_col++;
+	if (vport->cur_col>= vport->cols) {
+		vport->cur_col = 0;
+		vport->cur_row++;
+		if (vport->cur_row >= vport->rows)
+			vport->cur_row--;
 	}
+	if (vport->cursor_active)
+		invert_char(vp, vport->cur_row, vport->cur_col);
 }
 
@@ -481,5 +487,5 @@
 			clear_port(vp);
 			if (vport->cursor_active)
-				invert_char(vp, vport->cur_col,vport->cur_row);
+				invert_char(vp, vport->cur_row, vport->cur_col);
 			retval = 0;
 			break;
@@ -493,6 +499,6 @@
  			retval = 0;
 			if (viewports[vp].cursor_active) {
-				invert_char(vp, vport->cur_col,vport->cur_row);
-				invert_char(vp, col, row);
+				invert_char(vp, vport->cur_row, vport->cur_col);
+				invert_char(vp, row, col);
 			}
 			vport->cur_col = col;
@@ -506,5 +512,5 @@
 
 			vport->cursor_active = i;
-			invert_char(vp, vport->cur_col,vport->cur_row);
+			invert_char(vp, vport->cur_row, vport->cur_col);
 			break;
 		case FB_GET_CSIZE:
@@ -518,8 +524,8 @@
 			}
 			if (vport->cursor_active)
-				invert_char(vp, vport->cur_col,vport->cur_row);
+				invert_char(vp, vport->cur_row, vport->cur_col);
 			scroll_port(vp, i);
 			if (vport->cursor_active)
-				invert_char(vp, vport->cur_col,vport->cur_row);
+				invert_char(vp, vport->cur_row, vport->cur_col);
 			retval = 0;
 			break;
Index: init/init.c
===================================================================
--- init/init.c	(revision 3993b3d0b46275e928586a8893675056e87e7cf1)
+++ init/init.c	(revision c1d2c9dd2e8ed998a195ce76e6c2cb87a660d0d7)
@@ -446,5 +446,5 @@
 //	test_async_kbd();
 //	test_fb();
-//	test_console();
+	test_console();
 
 	printf("\nBye.\n");
Index: libc/generic/ipc.c
===================================================================
--- libc/generic/ipc.c	(revision 3993b3d0b46275e928586a8893675056e87e7cf1)
+++ libc/generic/ipc.c	(revision c1d2c9dd2e8ed998a195ce76e6c2cb87a660d0d7)
@@ -116,15 +116,8 @@
 }
 
-/** Send asynchronous message
- *
- * - if fatal error, call callback handler with proper error code
- * - if message cannot be temporarily sent, add to queue
- */
-void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
-		      ipcarg_t arg2, void *private,
-		      ipc_async_callback_t callback)
+/** Prolog to ipc_async_send functions */
+static inline async_call_t *ipc_prepare_async(void *private, ipc_async_callback_t callback)
 {
 	async_call_t *call;
-	ipc_callid_t callid;
 
 	call = malloc(sizeof(*call));
@@ -132,9 +125,59 @@
 		if (callback)
 			callback(private, ENOMEM, NULL);
-		return;
-	}
-
+		return NULL;
+	}
 	call->callback = callback;
 	call->private = private;
+
+	return call;
+}
+
+/** Epilogue of ipc_async_send functions */
+static inline void ipc_finish_async(ipc_callid_t callid, int phoneid, async_call_t *call)
+{
+	if (callid == IPC_CALLRET_FATAL) {
+		futex_up(&ipc_futex);
+		/* Call asynchronous handler with error code */
+		if (call->callback)
+			call->callback(call->private, ENOENT, NULL);
+		free(call);
+		return;
+	}
+
+	if (callid == IPC_CALLRET_TEMPORARY) {
+		futex_up(&ipc_futex);
+
+		call->u.msg.phoneid = phoneid;
+
+		call->ptid = psthread_get_id();
+		futex_down(&async_futex);
+		list_append(&call->list, &queued_calls);
+
+		psthread_schedule_next_adv(PS_TO_MANAGER);
+		/* Async futex unlocked by previous call */
+		return;
+	}
+	call->u.callid = callid;
+	/* Add call to list of dispatched calls */
+	list_append(&call->list, &dispatched_calls);
+	futex_up(&ipc_futex);
+	
+}
+
+/** Send asynchronous message
+ *
+ * - if fatal error, call callback handler with proper error code
+ * - if message cannot be temporarily sent, add to queue
+ */
+void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
+		      ipcarg_t arg2, void *private,
+		      ipc_async_callback_t callback)
+{
+	async_call_t *call;
+	ipc_callid_t callid;
+
+	call = ipc_prepare_async(private, callback);
+	if (!call)
+		return;
 
 	/* We need to make sure that we get callid before
@@ -142,33 +185,39 @@
 	futex_down(&ipc_futex);
 	callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, arg2);
-	if (callid == IPC_CALLRET_FATAL) {
-		futex_up(&ipc_futex);
-		/* Call asynchronous handler with error code */
-		if (callback)
-			callback(private, ENOENT, NULL);
-		free(call);
-		return;
-	}
 
 	if (callid == IPC_CALLRET_TEMPORARY) {
-		futex_up(&ipc_futex);
-
-		call->u.msg.phoneid = phoneid;
 		IPC_SET_METHOD(call->u.msg.data, method);
 		IPC_SET_ARG1(call->u.msg.data, arg1);
 		IPC_SET_ARG2(call->u.msg.data, arg2);
-
-		call->ptid = psthread_get_id();
-		futex_down(&async_futex);
-		list_append(&call->list, &queued_calls);
-
-		psthread_schedule_next_adv(PS_TO_MANAGER);
-		/* Async futex unlocked by previous call */
+	}
+	ipc_finish_async(callid, phoneid, call);
+}
+
+/** Send asynchronous message
+ *
+ * - if fatal error, call callback handler with proper error code
+ * - if message cannot be temporarily sent, add to queue
+ */
+void ipc_call_async_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
+		      ipcarg_t arg2, ipcarg_t arg3, void *private,
+		      ipc_async_callback_t callback)
+{
+	async_call_t *call;
+	ipc_callid_t callid;
+
+	call = ipc_prepare_async(private, callback);
+	if (!call)
 		return;
-	}
-	call->u.callid = callid;
-	/* Add call to list of dispatched calls */
-	list_append(&call->list, &dispatched_calls);
-	futex_up(&ipc_futex);
+
+	IPC_SET_METHOD(call->u.msg.data, method);
+	IPC_SET_ARG1(call->u.msg.data, arg1);
+	IPC_SET_ARG2(call->u.msg.data, arg2);
+	IPC_SET_ARG3(call->u.msg.data, arg3);
+	/* We need to make sure that we get callid before
+	 * another thread accesses the queue again */
+	futex_down(&ipc_futex);
+	callid = _ipc_call_async(phoneid, &call->u.msg.data);
+
+	ipc_finish_async(callid, phoneid, call);
 }
 
Index: libc/include/ipc/ipc.h
===================================================================
--- libc/include/ipc/ipc.h	(revision 3993b3d0b46275e928586a8893675056e87e7cf1)
+++ libc/include/ipc/ipc.h	(revision c1d2c9dd2e8ed998a195ce76e6c2cb87a660d0d7)
@@ -71,4 +71,7 @@
 		      ipcarg_t arg2, void *private,
 		      ipc_async_callback_t callback);
+extern void ipc_call_async_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
+			     ipcarg_t arg2, ipcarg_t arg3, void *private,
+			     ipc_async_callback_t callback);
 extern int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phone);
 extern int ipc_connect_me_to(int phoneid, int arg1, int arg2);
