Index: boot/arch/ia32/Makefile.inc
===================================================================
--- boot/arch/ia32/Makefile.inc	(revision 8344d0a447c14dcaa3d5a68b0a5172624baea0fe)
+++ boot/arch/ia32/Makefile.inc	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -62,5 +62,6 @@
 	$(USPACEDIR)/app/bdsh/bdsh \
 	$(USPACEDIR)/app/lspci/lspci \
-	$(USPACEDIR)/app/shutters/shutters 
+	$(USPACEDIR)/app/shutters/shutters \
+	$(USPACEDIR)/app/test_serial/test_serial
 
 build: $(BASE)/image.iso
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 8344d0a447c14dcaa3d5a68b0a5172624baea0fe)
+++ kernel/generic/src/ipc/irq.c	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -149,4 +149,6 @@
 		(unative_t) devno
 	};
+	
+	printf("kernel ipc_irq_register() ... registering irq = %d\n", inr);
 	
 	if (ucode) {
@@ -202,4 +204,7 @@
 	
 	interrupts_restore(ipl);
+	
+	printf("kernel ipc_irq_register() ... registering irq = %d was successful \n", inr);
+
 	return EOK;
 }
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 8344d0a447c14dcaa3d5a68b0a5172624baea0fe)
+++ uspace/Makefile	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -54,4 +54,5 @@
 	app/tetris \
 	app/shutters \
+	app/test_serial \
 	app/tester \
 	app/trace \
Index: uspace/app/test_serial/Makefile
===================================================================
--- uspace/app/test_serial/Makefile	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
+++ uspace/app/test_serial/Makefile	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -0,0 +1,39 @@
+LIBC_PREFIX = ../../lib/libc
+SOFTINT_PREFIX = ../../lib/softint
+
+include $(LIBC_PREFIX)/Makefile.toolchain
+
+LIBS = $(LIBC_PREFIX)/libc.a
+
+OUTPUT = test_serial
+SOURCES = test_serial.c
+OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
+
+.PHONY: all clean depend disasm
+
+all: $(OUTPUT) $(OUTPUT).disasm
+
+-include Makefile.depend
+
+depend:
+	$(CC) $(DEFS) $(CFLAGS) -M $(SOURCES) > Makefile.depend
+
+$(OUTPUT): $(OBJECTS) $(LIBS)
+	$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
+
+clean:
+	-rm -f $(OUTPUT) $(OUTPUT).map $(OUTPUT).disasm Makefile.depend *.o
+
+disasm: $(OUTPUT).disasm
+
+$(OUTPUT).disasm: $(OUTPUT)
+	$(OBJDUMP) -d $< >$@
+
+%.o: %.S
+	$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
+
+%.o: %.s
+	$(AS) $(AFLAGS) $< -o $@
+
+%.o: %.c
+	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
Index: uspace/app/test_serial/test_serial.c
===================================================================
--- uspace/app/test_serial/test_serial.c	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
+++ uspace/app/test_serial/test_serial.c	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2009 Lenka Trochtova
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup test_serial
+ * @brief	test the serial port driver 
+ * @{
+ */ 
+/**
+ * @file
+ */
+
+#include <stdio.h>
+#include <ipc/ipc.h>
+#include <sys/types.h>
+#include <atomic.h>
+#include <ipc/devmap.h>
+#include <async.h>
+#include <ipc/services.h>
+#include <ipc/serial.h>
+#include <as.h>
+#include <sysinfo.h>
+#include <errno.h>
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include <string.h>
+
+#define NAME 		"test serial"
+#define MYROOM 		2
+#define UpSection1 	25
+#define DwnSection1 26
+#define UpSection2 	27
+#define DwnSection2 28
+
+static int device_get_handle(const char *name, dev_handle_t *handle);
+static void print_usage();
+static void move_shutters(const char * serial_dev_name, char room, char cmd);
+static char getcmd(bool wnd, bool up);
+static bool is_com_dev(const char *dev_name);
+
+static int device_get_handle(const char *name, dev_handle_t *handle)
+{
+	int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
+	if (phone < 0)
+		return phone;
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0, &answer);
+	
+	ipcarg_t retval = ipc_data_write_start(phone, name, str_length(name) + 1); 
+
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		ipc_hangup(phone);
+		return retval;
+	}
+
+	async_wait_for(req, &retval);
+
+	if (handle != NULL)
+		*handle = -1;
+	
+	if (retval == EOK) {
+		if (handle != NULL)
+			*handle = (dev_handle_t) IPC_GET_ARG1(answer);
+	}
+	
+	ipc_hangup(phone);
+	return retval;
+}
+
+static void print_usage()
+{
+	printf("Usage: \n test_serial comN count \n where 'comN' is a serial port and count is a number of characters to be read\n");	
+}
+
+
+/*
+ * The name of a serial device must be between 'com0' and 'com9'.
+ */ 
+static bool is_com_dev(const char *dev_name) 
+{
+	if (str_length(dev_name) != 4) {
+		return false;
+	}
+	
+	if (str_cmp("com0", dev_name) > 0) {
+		return false;
+	}
+	
+	if (str_cmp(dev_name, "com9") > 0) {
+		return false;
+	}
+	
+	return true;
+}
+
+
+int main(int argc, char *argv[])
+{
+	if (argc != 3) {
+		printf(NAME ": incorrect number of arguments.\n");
+		print_usage();
+		return 0;		
+	}	
+
+	
+	const char *serial_dev_name = argv[1];
+	long int cnt = strtol(argv[2], NULL, 10);
+	
+	if (!is_com_dev(serial_dev_name)) {
+		printf(NAME ": the first argument is not correct.\n");
+		print_usage();
+		return 0;	
+	}
+	
+	dev_handle_t serial_dev_handle = -1;
+	
+	if (device_get_handle(serial_dev_name, &serial_dev_handle) !=  EOK) {
+		printf(NAME ": could not get the handle of %s.\n", serial_dev_name);
+		return;
+	}
+	
+	printf(NAME ": got the handle of %s.\n", serial_dev_name);
+	
+	int dev_phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CONNECT_TO_DEVICE, serial_dev_handle);
+	if(dev_phone < 0) {
+		printf(NAME ": could not connect to %s device.\n", serial_dev_name);
+		return;
+	}
+	
+	printf("The application will read %d characters from %s: \n", cnt, serial_dev_name);
+	
+	int i, c;
+	for (i = 0; i < cnt; i++) {
+		async_req_0_1(dev_phone, SERIAL_GETCHAR, &c);
+		printf("%c", (char)c);
+	}
+	
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/pci/Makefile
===================================================================
--- uspace/srv/pci/Makefile	(revision 8344d0a447c14dcaa3d5a68b0a5172624baea0fe)
+++ uspace/srv/pci/Makefile	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -45,4 +45,5 @@
 SOURCES = \
 	main.c \
+	pic.c \
 	pci.c \
 	intel_piix3.c \
Index: uspace/srv/pci/main.c
===================================================================
--- uspace/srv/pci/main.c	(revision 8344d0a447c14dcaa3d5a68b0a5172624baea0fe)
+++ uspace/srv/pci/main.c	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -4,4 +4,5 @@
 
 #include "intel_piix3.h"
+#include "pic.h"
 #include "pci.h"
 #include "pci_bus.h"
@@ -10,7 +11,13 @@
 
 
+
 int main(int argc, char **argv) 
 {
 	printf("PCI bus driver\n");
+	
+	if (!pic_init()) {
+		printf("PIC initialization failed.\n");
+		return 1;
+	}
 	
 	if (!pci_bus_init()) {
@@ -22,6 +29,5 @@
 		printf("ISA bus initialization failed.\n");
 		return 1;
-	}
-	
+	}	
 	
 	// pci-to-isa bridge device
Index: uspace/srv/pci/pic.c
===================================================================
--- uspace/srv/pci/pic.c	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
+++ uspace/srv/pci/pic.c	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -0,0 +1,67 @@
+#include <unistd.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <stdio.h>
+
+#include "pic.h"
+
+#define PIC1		0x20		/* IO base address for master PIC */
+#define PIC2		0xA0		/* IO base address for slave PIC */
+#define REG_COUNT	2			/* command and data */
+
+#define NAME "PIC"
+
+static ioport8_t *pic1_cmd, *pic1_data, *pic2_cmd, *pic2_data;
+
+static int pic_enable_ports(void *base_phys_addr, ioport8_t **pic_cmd, ioport8_t **pic_data);
+
+
+int pic_init()
+{	
+	printf(NAME ": enabling ports 0x%x - 0x%x.\n", PIC1, PIC1 + 1);
+	if (!pic_enable_ports((void *)PIC1, &pic1_cmd, &pic1_data)) {
+		printf(NAME ": Error - master PIC initialization failed.\n");
+		return 0;
+	}
+	
+	printf(NAME ": enabling ports 0x%x - 0x%x.\n", PIC2, PIC2 + 1);
+	if (!pic_enable_ports((void *)PIC2, &pic2_cmd, &pic2_data)) {
+		printf(NAME ": Error - slave PIC initialization failed.");
+		return 0;
+	}
+	
+	printf(NAME ": initialization was successful.\n");
+	return 1;
+}
+
+static int pic_enable_ports(void *base_phys_addr, ioport8_t **pic_cmd, ioport8_t **pic_data)
+{
+	if (pio_enable(base_phys_addr, REG_COUNT, (void **)(pic_cmd))) {  // Gain control over port's registers.
+		printf(NAME ": Error - cannot gain the port %lx.\n", base_phys_addr);
+		return 0;
+	}
+	
+	*pic_data = *pic_cmd + 1;
+	return 1;
+}
+
+void pic_enable_interrupt(int irq)
+{
+	printf(NAME ": pic_enable_interrupt %d.", irq);
+	pic_enable_irqs(1 << irq);
+	printf(NAME ": interrupt %d enabled.", irq);
+}
+
+void pic_enable_irqs(uint16_t irqmask)
+{
+	uint8_t x;
+
+	if (irqmask & 0xff) {
+		x = pio_read_8(pic1_data);
+		pio_write_8(pic1_data, (uint8_t) (x & (~(irqmask & 0xff))));
+	}
+	if (irqmask >> 8) {
+		x = pio_read_8(pic2_data);
+		pio_write_8(pic2_data, (uint8_t) (x & (~(irqmask >> 8))));
+	}
+}
Index: uspace/srv/pci/pic.h
===================================================================
--- uspace/srv/pci/pic.h	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
+++ uspace/srv/pci/pic.h	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -0,0 +1,10 @@
+#ifndef PIC_H
+#define PIC_H
+
+#include <stdlib.h>
+
+int pic_init();
+void pic_enable_interrupt(int irq);
+void pic_enable_irqs(uint16_t irqmask);
+
+#endif
Index: uspace/srv/pci/serial.c
===================================================================
--- uspace/srv/pci/serial.c	(revision 8344d0a447c14dcaa3d5a68b0a5172624baea0fe)
+++ uspace/srv/pci/serial.c	(revision 86554e71a1dd77b66b874136837c0b9cd1957907)
@@ -18,4 +18,5 @@
 #include "isa.h"
 #include "serial.h"
+#include "pic.h"
 
 #define NAME "serial"
@@ -24,19 +25,80 @@
 
 #define MAX_NAME_LEN 8
+#define BUF_LEN 256  // the length of the input buffer
+
+struct cyclic_buffer {
+	uint8_t buf[BUF_LEN];  // cyclic buffer 
+	int start;
+	int cnt;
+};
+
+typedef struct cyclic_buffer cyclic_buffer_t;
+
+// returns false if the buffer is full
+static bool buf_push_back(cyclic_buffer_t *buf, uint8_t item) 
+{
+	if (buf->cnt >= BUF_LEN) {
+		return false;
+	}
+	
+	int pos = (buf->start + buf->cnt) % BUF_LEN;
+	buf->buf[pos] = item;
+	buf->cnt++;
+	return true;
+}
+
+static bool buf_is_empty(cyclic_buffer_t *buf) 
+{
+	return buf->cnt == 0;
+}
+
+// call it on non empty buffer!
+static uint8_t buf_pop_front(cyclic_buffer_t *buf) 
+{
+	assert(!buf_is_empty(buf));
+	
+	uint8_t res = buf->buf[buf->start];
+	buf->start = (buf->start + 1) % BUF_LEN;	
+	buf->cnt--;
+	return res;
+}
+
+static void buf_clear(cyclic_buffer_t *buf) 
+{
+	buf->cnt = 0;
+}
 
 struct serial_dev {
 	link_t link;
 	char name[MAX_NAME_LEN];
-	int handle;
+	int handle; // devmapper device handle
+	int devno; // unique device number; used in irq registration (cannot be handle used instead of it?) 
 	bool client_connected;
 	ioport8_t *port;
 	void *phys_addr;
+	int irq;
 	bridge_to_isa_t *parent;
+	cyclic_buffer_t input_buffer;
+	futex_t futex;
 };
 
 typedef struct serial_dev serial_dev_t;
 
+static irq_cmd_t serial_cmds[] = {
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t serial_pseudocode = {
+	sizeof(serial_cmds) / sizeof(irq_cmd_t),
+	serial_cmds
+};
+
 static void * serial_phys_addresses[] = { (void *)0x3F8, (void *)0x2F8 };
+static int serial_irqs[] = { 4, 3 }; // TODO - what about if there were more than two serial ports?
 static int serial_phys_addr_cnt = sizeof(serial_phys_addresses)/sizeof(void *);
+static int serial_irq_cnt = sizeof(serial_irqs)/sizeof(int);
+
 // number, which should be assigned to a newly found serial device - increment first, then assign to the device
 static int serial_idx = 0; 
@@ -61,4 +123,8 @@
 static void serial_getchar(serial_dev_t *dev, ipc_callid_t rid);
 static void serial_client_conn(ipc_callid_t iid, ipc_call_t *icall);
+static void serial_irq_handler(ipc_callid_t iid, ipc_call_t *icall);
+static serial_dev_t * serial_devno_to_dev(int devno);
+static serial_dev_t * serial_handle_to_dev(int handle);
+static void serial_enable_interrupt(serial_dev_t *dev);
 
 static isa_drv_ops_t serial_isa_ops = {
@@ -77,6 +143,10 @@
     if (serial_driver_phone < 0) {
 		printf(NAME ": Unable to register driver\n");
-		return false;
-	}
+		return 0;
+	}
+	
+	// register irq handler
+	printf(NAME ": Registering interrup notification callback function.\n");
+	async_set_interrupt_received(serial_irq_handler);
 	   
 	// register this driver by generic isa bus driver	
@@ -92,9 +162,5 @@
 static uint8_t serial_read_8(ioport8_t *port) 
 {
-	while (!serial_received(port)) 
-		;
-
-	uint8_t c = pio_read_8(port);
-	return c;
+	return pio_read_8(port);
 }
 
@@ -120,5 +186,17 @@
 	pio_write_8(port + 3, 0x07);    // 8 bits, no parity, two stop bits
 	pio_write_8(port + 2, 0xC7);    // Enable FIFO, clear them, with 14-byte threshold
-	pio_write_8(port + 4, 0x0B);    // RTS/DSR set (Request to Send and Data Terminal Ready lines enabled), Aux Output2 set 
+	pio_write_8(port + 4, 0x0B);    // RTS/DSR set (Request to Send and Data Terminal Ready lines enabled), 
+									// Aux Output2 set - needed for interrupts
+	 
+}
+
+static void serial_enable_interrupt(serial_dev_t *dev)
+{
+	futex_down(&(dev->futex));
+	// TODO do not call pic directly, do it more generally
+	pic_enable_interrupt(dev->irq);
+	pio_write_8(dev->port + 1 , 0x01);   // Interrupt when data received
+	pio_write_8(dev->port + 4, 0x0B);
+	futex_up(&(dev->futex));
 }
 
@@ -137,6 +215,9 @@
 	dev->parent = parent;
 	dev->phys_addr = dev->parent->ops->absolutize(serial_phys_addresses[idx % serial_phys_addr_cnt]);
+	dev->irq = serial_irqs[idx % serial_irq_cnt];
 	snprintf(dev->name, MAX_NAME_LEN, "com%d", idx + 1);
-	dev->client_connected = false;	
+	dev->devno = -1;
+	dev->client_connected = false;
+	futex_initialize(&(dev->futex), 1);
 }
 
@@ -145,5 +226,4 @@
 	assert(dev != NULL);
 	
-	printf(NAME " driver: probing %s \n", dev->name);
 	return (dev->port = (ioport8_t *)serial_probe_port(dev->phys_addr)) != NULL;	
 }
@@ -160,14 +240,24 @@
 	
 	int i;
-	for (i = 0; i < serial_phys_addr_cnt; i++) {		
+	for (i = 0; i < serial_phys_addr_cnt; i++) {			
 		serial_init_dev(dev, parent, serial_idx);
+		printf(NAME ": probing %s. \n", dev->name);
 		if (serial_probe_dev(dev)) {
 			printf(NAME " driver: initializing %s.\n", dev->name);
 			serial_init_port(dev->port);
 			if (EOK != serial_device_register(serial_driver_phone, dev->name, &(dev->handle))) {
-				printf(NAME ": Unable to register device %s\n", dev->name);
-			}	
-			list_append(&(dev->link), &serial_devices_list);
-			dev = serial_alloc_dev();
+				printf(NAME ": unable to register device %s\n", dev->name);
+			} else {
+				dev->devno = device_assign_devno();
+				
+				// 3rd argument called method is equal devno,this enables us to identify the device 
+				// which caused the interrupt in the irq notification callback function
+				printf(NAME ": registering irq = %d for %s.\n", dev->irq, dev->name);
+				ipc_register_irq(dev->irq, dev->devno, dev->devno, &serial_pseudocode);  
+				list_append(&(dev->link), &serial_devices_list);
+				printf(NAME ": enabling irq = %d for %s.\n", dev->irq, dev->name);
+				serial_enable_interrupt(dev);
+				dev = serial_alloc_dev();
+			}
 		} else {
 			printf(NAME " driver: %s is not present \n", dev->name);
@@ -210,5 +300,7 @@
 {
 	int c = IPC_GET_ARG1(*request);
+	futex_down(&(dev->futex));
 	serial_write_8(dev->port, (uint8_t)c);	
+	futex_up(&(dev->futex));
 	ipc_answer_0(rid, EOK);
 }
@@ -216,10 +308,23 @@
 static void serial_getchar(serial_dev_t *dev, ipc_callid_t rid)
 {
-	uint8_t c = serial_read_8(dev->port);	
+	uint8_t c;
+	printf(NAME ": trying to read from serial port %s\n", dev->name);
+	while (true) {  // TODO: fix it - the queue of requests to read ?
+		futex_down(&(dev->futex));
+		if (!buf_is_empty(&(dev->input_buffer))) {
+			c = buf_pop_front(&(dev->input_buffer));
+			futex_up(&(dev->futex));
+			break;
+		}
+		//printf(NAME "no data ready, trying to read again after some while.\n", dev->name);
+		futex_up(&(dev->futex));
+		async_usleep(10000);
+	}
+	printf(NAME ": serial_getchar: sending characer %c read from %s to client.\n", c, dev->name);
 	ipc_answer_1(rid, EOK, c);		
 }
 
-static serial_dev_t * serial_handle_to_dev(int handle) {
-	
+static serial_dev_t * serial_handle_to_dev(int handle) 
+{	
 	futex_down(&serial_futex);	
 	
@@ -230,4 +335,24 @@
 		dev = list_get_instance(item, serial_dev_t, link);
 		if (dev->handle == handle) {
+			futex_up(&serial_futex);
+			return dev;
+		}
+		item = item->next;
+	}
+	
+	futex_up(&serial_futex);
+	return NULL;
+}
+
+static serial_dev_t * serial_devno_to_dev(int devno)
+{		
+	futex_down(&serial_futex);	
+	
+	link_t *item = serial_devices_list.next;
+	serial_dev_t *dev = NULL; 
+	
+	while (item != &serial_devices_list) {
+		dev = list_get_instance(item, serial_dev_t, link);
+		if (dev->devno == devno) {
 			futex_up(&serial_futex);
 			return dev;
@@ -262,5 +387,6 @@
 		return;
 	}
-	
+		
+	buf_clear(&(dev->input_buffer));  // synchronization with interrupt service routine ?
 	dev->client_connected = true;
 	ipc_answer_0(iid, EOK);
@@ -310,6 +436,5 @@
 	while (phone < 0) {
 		usleep(10000);
-		phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
-		    DEVMAP_DRIVER, 0);
+		phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
 	}
 	
@@ -336,4 +461,8 @@
 	aid_t req;
 	ipc_call_t answer;
+	
+	if (handle != NULL) {
+		*handle = -1;
+	}
 
 	req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer);
@@ -347,7 +476,4 @@
 
 	async_wait_for(req, &retval);
-
-	if (handle != NULL)
-		*handle = -1;
 	
 	if (EOK == retval) {
@@ -358,2 +484,41 @@
 	return retval;
 }
+
+static void serial_read_from_device(serial_dev_t *dev)
+{	
+	bool cont = true;
+	
+	while (cont) {	
+		futex_down(&(dev->futex));
+		if (cont = serial_received(dev->port)) {
+			uint8_t val = serial_read_8(dev->port);
+			printf(NAME ": character %c read from %s.\n", val, dev->name);
+			if (dev->client_connected) {
+				if (!buf_push_back(&(dev->input_buffer), val)) {
+					printf(NAME ": buffer overflow on %s.\n", dev->name);
+				} else {
+					printf(NAME ": the character %c saved to the buffer of %s.\n", val, dev->name);
+				}
+			} else {
+				printf(NAME ": no client is connected to %s, discarding the character which was read.\n", dev->name);
+			}
+		}
+		futex_up(&(dev->futex));
+		usleep(10000);
+	}	
+}
+
+// TODO - this is the only irq handling function registered by this task.
+// (A task can register only one such function.)
+// If more drivers within the task needed to handle interrupts, 
+// there will have to be one generic handler redistributing
+// irq notification messages among them. 
+// Or the change of ansync framework will be needed.
+static void serial_irq_handler(ipc_callid_t iid, ipc_call_t *icall)
+{
+	printf(NAME ": irq handler\n");
+	int devno = IPC_GET_METHOD(*icall);
+	serial_dev_t *dev = serial_devno_to_dev(devno);
+	serial_read_from_device(dev);	
+}
+
