Index: fb/fb.c
===================================================================
--- fb/fb.c	(revision 68623380e3732a68190ac74156fb28aa5c6e86b4)
+++ fb/fb.c	(revision a2cd19407aeaebd9dfe9f73276a585bee5a22adc)
@@ -1,184 +1,4 @@
 /*
  * Copyright (C) 2006 Jakub Vana
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <ddi.h>
-#include <task.h>
-#include <stdlib.h>
-#include <ddi.h>
-#include <sysinfo.h>
-#include <align.h>
-#include <as.h>
-#include <ipc/fb.h>
-
-
-#include <ipc/ipc.h>
-#include <ipc/services.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <ipc/ns.h>
-
-#include <kernel/errno.h>
-#include <async.h>
-
-#include "fb.h"
-
-#define EFB (-1)
-
-#define DEFAULT_BGCOLOR		0x000080
-#define DEFAULT_FGCOLOR		0xffff00
-#define DEFAULT_LOGOCOLOR	0x0000ff
-
-#define MAIN_BGCOLOR		0x404000
-#define MAIN_FGCOLOR		0x000000
-#define MAIN_LOGOCOLOR	0x404000
-
-#define SPACING (2)
-
-#define H_NO_VFBS 3
-#define V_NO_VFBS 3
-
-
-static void fb_putchar(int item,char ch);
-int create_window(int item,unsigned int x, unsigned int y,unsigned int x_size, unsigned int y_size,
-	unsigned int BGCOLOR,unsigned int FGCOLOR,unsigned int LOGOCOLOR);
-void fb_init(int item,__address addr, unsigned int x, unsigned int y, unsigned int bpp, unsigned int scan,
-	unsigned int BGCOLOR,unsigned int FGCOLOR,unsigned int LOGOCOLOR);
-
-
-unsigned int mod_col(unsigned int col,int mod);
-
-
-
-static int init_fb(void)
-{
-	__address fb_ph_addr;
-	unsigned int fb_width;
-	unsigned int fb_height;
-	unsigned int fb_bpp;
-	unsigned int fb_scanline;
-	__address fb_addr;
-	int a=0;
-	int i,j,k;
-	int w;
-	char text[]="HelenOS Framebuffer driver\non Virtual Framebuffer\nVFB ";
-
-	fb_ph_addr=sysinfo_value("fb.address.physical");
-	fb_width=sysinfo_value("fb.width");
-	fb_height=sysinfo_value("fb.height");
-	fb_bpp=sysinfo_value("fb.bpp");
-	fb_scanline=sysinfo_value("fb.scanline");
-
-	fb_addr=ALIGN_UP(((__address)set_maxheapsize(USER_ADDRESS_SPACE_SIZE_ARCH>>1)),PAGE_SIZE);
-
-
-	
-	map_physmem(task_get_id(),(void *)((__address)fb_ph_addr),(void *)fb_addr,
-		    (fb_scanline*fb_height+PAGE_SIZE-1)>>PAGE_WIDTH,1);
-	
-	fb_init(0,fb_addr, fb_width, fb_height, fb_bpp, fb_scanline,
-		MAIN_BGCOLOR,MAIN_FGCOLOR,MAIN_LOGOCOLOR);
-
-	fb_putchar(0,'\n');
-	fb_putchar(0,' ');
-
-	for(i=0;i<H_NO_VFBS;i++)
-		for(j=0;j<V_NO_VFBS;j++) {
-			w = create_window(0,(fb_width/H_NO_VFBS)*i+SPACING,
-					  (fb_height/V_NO_VFBS)*j+SPACING,(fb_width/H_NO_VFBS)-2*SPACING ,
-					  (fb_height/V_NO_VFBS)-2*SPACING,mod_col(DEFAULT_BGCOLOR,/*i+j*H_NO_VFBS*/0),
-					  mod_col(DEFAULT_FGCOLOR,/*i+j*H_NO_VFBS*/0),
-					  mod_col(DEFAULT_LOGOCOLOR,/*i+j*H_NO_VFBS)*/0));
-			
-			if( w== EFB)
-				return -1;
-			
-			for(k=0;text[k];k++) 
-				fb_putchar(w,text[k]);
-			fb_putchar(w,w+'0');
-			fb_putchar(w,'\n');
-		}
-	return 0;
-}
-
-int vfb_no = 1;
-void client_connection(ipc_callid_t iid, ipc_call_t *icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	int vfb = vfb_no++;
-
-	if (vfb > 9) {
-		ipc_answer_fast(iid, ELIMIT, 0,0);
-		return;
-	}
-	ipc_answer_fast(iid, 0, 0, 0);
-
-	while (1) {
-		callid = async_get_call(&call);
-		switch (IPC_GET_METHOD(call)) {
-		case IPC_M_PHONE_HUNGUP:
-			ipc_answer_fast(callid,0,0,0);
-			return; /* Exit thread */
-
-		case FB_PUTCHAR:
-			ipc_answer_fast(callid,0,0,0);
-			fb_putchar(vfb,IPC_GET_ARG2(call));
-			break;
-		default:
-			ipc_answer_fast(callid,ENOENT,0,0);
-		}
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	ipc_call_t call;
-	ipc_callid_t callid;
-	char connected = 0;
-	int res;
-	int c;
-	ipcarg_t phonead;
-	
-	ipcarg_t retval, arg1, arg2;
-
-	if(!sysinfo_value("fb")) return -1;
-
-
-	if ((res = ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, &phonead)) != 0) 
-		return -1;
-	
-	init_fb();
-
-	async_manager();
-	/* Never reached */
-	return 0;
-}
-/*
  * Copyright (C) 2006 Ondrej Palkovsky
  * All rights reserved.
@@ -208,12 +28,162 @@
  */
 
+#include <stdio.h>
+#include <ddi.h>
+#include <task.h>
+#include <stdlib.h>
+#include <ddi.h>
+#include <sysinfo.h>
+#include <align.h>
+#include <as.h>
+#include <ipc/fb.h>
+
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ipc/ns.h>
+
+#include <kernel/errno.h>
+#include <async.h>
+
+
 #include "font-8x16.h"
 #include <string.h>
 
 #include "helenos.xbm"
-
-
-
-
+#include "fb.h"
+
+#define EFB (-1)
+
+#define DEFAULT_BGCOLOR		0x000080
+#define DEFAULT_FGCOLOR		0xffff00
+#define DEFAULT_LOGOCOLOR	0x0000ff
+
+#define MAIN_BGCOLOR		0x404000
+#define MAIN_FGCOLOR		0x000000
+#define MAIN_LOGOCOLOR	0x404000
+
+#define SPACING (2)
+
+#define H_NO_VFBS 3
+#define V_NO_VFBS 3
+
+
+static void fb_putchar(int item,char ch);
+int create_window(int item,unsigned int x, unsigned int y,unsigned int x_size, unsigned int y_size,
+	unsigned int BGCOLOR,unsigned int FGCOLOR,unsigned int LOGOCOLOR);
+void fb_init(int item,__address addr, unsigned int x, unsigned int y, unsigned int bpp, unsigned int scan,
+	unsigned int BGCOLOR,unsigned int FGCOLOR,unsigned int LOGOCOLOR);
+
+
+unsigned int mod_col(unsigned int col,int mod);
+
+
+
+static int init_fb(void)
+{
+	__address fb_ph_addr;
+	unsigned int fb_width;
+	unsigned int fb_height;
+	unsigned int fb_bpp;
+	unsigned int fb_scanline;
+	__address fb_addr;
+	int a=0;
+	int i,j,k;
+	int w;
+	char text[]="HelenOS Framebuffer driver\non Virtual Framebuffer\nVFB ";
+
+	fb_ph_addr=sysinfo_value("fb.address.physical");
+	fb_width=sysinfo_value("fb.width");
+	fb_height=sysinfo_value("fb.height");
+	fb_bpp=sysinfo_value("fb.bpp");
+	fb_scanline=sysinfo_value("fb.scanline");
+
+	fb_addr=ALIGN_UP(((__address)set_maxheapsize(USER_ADDRESS_SPACE_SIZE_ARCH>>1)),PAGE_SIZE);
+
+
+	
+	map_physmem(task_get_id(),(void *)((__address)fb_ph_addr),(void *)fb_addr,
+		    (fb_scanline*fb_height+PAGE_SIZE-1)>>PAGE_WIDTH,1);
+	
+	fb_init(0,fb_addr, fb_width, fb_height, fb_bpp, fb_scanline,
+		MAIN_BGCOLOR,MAIN_FGCOLOR,MAIN_LOGOCOLOR);
+
+	fb_putchar(0,'\n');
+	fb_putchar(0,' ');
+
+	for(i=0;i<H_NO_VFBS;i++)
+		for(j=0;j<V_NO_VFBS;j++) {
+			w = create_window(0,(fb_width/H_NO_VFBS)*i+SPACING,
+					  (fb_height/V_NO_VFBS)*j+SPACING,(fb_width/H_NO_VFBS)-2*SPACING ,
+					  (fb_height/V_NO_VFBS)-2*SPACING,mod_col(DEFAULT_BGCOLOR,/*i+j*H_NO_VFBS*/0),
+					  mod_col(DEFAULT_FGCOLOR,/*i+j*H_NO_VFBS*/0),
+					  mod_col(DEFAULT_LOGOCOLOR,/*i+j*H_NO_VFBS)*/0));
+			
+			if( w== EFB)
+				return -1;
+			
+			for(k=0;text[k];k++) 
+				fb_putchar(w,text[k]);
+			fb_putchar(w,w+'0');
+			fb_putchar(w,'\n');
+		}
+	return 0;
+}
+
+int vfb_no = 1;
+void client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	int vfb = vfb_no++;
+
+	if (vfb > 9) {
+		ipc_answer_fast(iid, ELIMIT, 0,0);
+		return;
+	}
+	ipc_answer_fast(iid, 0, 0, 0);
+
+	while (1) {
+		callid = async_get_call(&call);
+		switch (IPC_GET_METHOD(call)) {
+		case IPC_M_PHONE_HUNGUP:
+			ipc_answer_fast(callid,0,0,0);
+			return; /* Exit thread */
+
+		case FB_PUTCHAR:
+			ipc_answer_fast(callid,0,0,0);
+			fb_putchar(vfb,IPC_GET_ARG2(call));
+			break;
+		default:
+			ipc_answer_fast(callid,ENOENT,0,0);
+		}
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	ipc_call_t call;
+	ipc_callid_t callid;
+	char connected = 0;
+	int res;
+	int c;
+	ipcarg_t phonead;
+	
+	ipcarg_t retval, arg1, arg2;
+
+	if(!sysinfo_value("fb")) return -1;
+
+
+	if ((res = ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, &phonead)) != 0) 
+		return -1;
+	
+	init_fb();
+
+	async_manager();
+	/* Never reached */
+	return 0;
+}
 
 
Index: libc/generic/async.c
===================================================================
--- libc/generic/async.c	(revision 68623380e3732a68190ac74156fb28aa5c6e86b4)
+++ libc/generic/async.c	(revision a2cd19407aeaebd9dfe9f73276a585bee5a22adc)
@@ -74,4 +74,6 @@
  *       ....
  * }
+ *
+ * TODO: Detaching/joining dead psthreads? */
  */
 #include <futex.h>
@@ -100,5 +102,4 @@
 	pstid_t ptid;                /**< Thread associated with this connection */
 	int active;                     /**< If this thread is currently active */
-	int opened;                    /* If the connection was accepted */
 	/* Structures for connection opening packet */
 	ipc_callid_t callid;
@@ -110,10 +111,10 @@
 /* Hash table functions */
 
-#define ASYNC_HASH_TABLE_CHAINS	32
+#define CONN_HASH_TABLE_CHAINS	32
 
 static hash_index_t conn_hash(unsigned long *key)
 {
 	assert(key);
-	return ((*key) >> 4) % ASYNC_HASH_TABLE_CHAINS;
+	return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS;
 }
 
@@ -175,4 +176,5 @@
 }
 
+/** Return new incoming message for current(thread-local) connection */
 ipc_callid_t async_get_call(ipc_call_t *call)
 {
@@ -200,21 +202,42 @@
 }
 
+/** Thread function that gets created on new connection
+ *
+ * This function is defined as a weak symbol - to be redefined in
+ * user code.
+ */
 void client_connection(ipc_callid_t callid, ipc_call_t *call)
 {
-	printf("Got connection - no handler.\n");
-	_exit(1);
-}
-
+	ipc_answer_fast(callid, ENOENT, 0, 0);
+}
+
+/** Wrapper for client connection thread
+ *
+ * When new connection arrives, thread with this function is created.
+ * It calls client_connection and does final cleanup.
+ *
+ * @parameter arg Connection structure pointer
+ */
 static int connection_thread(void  *arg)
 {
+	unsigned long key;
+	msg_t *msg;
+
 	/* Setup thread local connection pointer */
 	PS_connection = (connection_t *)arg;
 	client_connection(PS_connection->callid, &PS_connection->call);
 
+	/* Remove myself from connection hash table */
 	futex_down(&conn_futex);
-	/* TODO: remove myself from connection hash table */
+	key = PS_connection->in_phone_hash;
+	hash_table_remove(&conn_hash_table, &key, 1);
 	futex_up(&conn_futex);
-	/* TODO: answer all unanswered messages in queue with
-	 *       EHANGUP */
+	/* Answer all remaining messages with ehangup */
+	while (!list_empty(&PS_connection->msg_queue)) {
+		msg = list_get_instance(PS_connection->msg_queue.next, msg_t, link);
+		list_remove(&msg->link);
+		ipc_answer_fast(msg->callid, EHANGUP, 0, 0);
+		free(msg);
+	}
 }
 
@@ -239,5 +262,4 @@
 	conn->in_phone_hash = IPC_GET_ARG3(*call);
 	list_initialize(&conn->msg_queue);
-	conn->opened = 0;
 	conn->ptid = psthread_create(connection_thread, conn);
 	conn->callid = callid;
@@ -298,4 +320,11 @@
 }
 
+/** Function to start async_manager as a standalone thread 
+ * 
+ * When more kernel threads are used, one async manager should
+ * exist per thread. The particular implementation may change,
+ * currently one async_manager is started automatically per kernel
+ * thread except main thread. 
+ */
 static int async_manager_thread(void *arg)
 {
@@ -323,5 +352,5 @@
 int _async_init(void)
 {
-	if (!hash_table_create(&conn_hash_table, ASYNC_HASH_TABLE_CHAINS, 1, &conn_hash_table_ops)) {
+	if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, &conn_hash_table_ops)) {
 		printf("%s: cannot create hash table\n", "async");
 		return ENOMEM;
