Index: uspace/lib/libc/generic/ddi.c
===================================================================
--- uspace/lib/libc/generic/ddi.c	(revision 953bc1efafe8161834d87acae8f871ef640154a5)
+++ uspace/lib/libc/generic/ddi.c	(revision cfe7716bf85413141220c5c75d82d669b65455dc)
@@ -105,14 +105,24 @@
 }
 
-/** Enable/disable interrupt.
+/** Enable an interrupt.
  * 
  * @param irq the interrupt.
- * @param enable 1 - enable interrupt, 0 - disable interrupt.
  * 
  * @return Zero on success, negative error code otherwise. 
  */
-int interrupt_enable(int irq, int enable) 
+int interrupt_enable(int irq) 
 {
-	return __SYSCALL2(SYS_INTERRUPT_ENABLE, (sysarg_t) irq, (sysarg_t) enable);
+	return __SYSCALL2(SYS_INTERRUPT_ENABLE, (sysarg_t) irq, 1);
+}
+
+/** Disable an interrupt.
+ * 
+ * @param irq the interrupt.
+ * 
+ * @return Zero on success, negative error code otherwise. 
+ */
+int interrupt_disable(int irq) 
+{
+	return __SYSCALL2(SYS_INTERRUPT_ENABLE, (sysarg_t) irq, 0);
 }
 
Index: uspace/lib/libc/include/ddi.h
===================================================================
--- uspace/lib/libc/include/ddi.h	(revision 953bc1efafe8161834d87acae8f871ef640154a5)
+++ uspace/lib/libc/include/ddi.h	(revision cfe7716bf85413141220c5c75d82d669b65455dc)
@@ -43,5 +43,6 @@
 extern int preemption_control(int);
 extern int pio_enable(void *, size_t, void **);
-extern int interrupt_enable(int, int);
+extern int interrupt_enable(int);
+extern int interrupt_disable(int);
 
 #endif
Index: uspace/lib/libdrv/include/driver.h
===================================================================
--- uspace/lib/libdrv/include/driver.h	(revision 953bc1efafe8161834d87acae8f871ef640154a5)
+++ uspace/lib/libdrv/include/driver.h	(revision cfe7716bf85413141220c5c75d82d669b65455dc)
@@ -41,4 +41,8 @@
 #include <device/hw_res.h>
 #include <assert.h>
+#include <ddi.h>
+#include <libarch/ddi.h>
+#include <fibril_synch.h>
+#include <malloc.h>
 
 struct device;
@@ -159,4 +163,110 @@
 int child_device_register(device_t *child, device_t *parent);
 
+// interrupts
+
+static irq_cmd_t default_cmds[] = {
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+static irq_code_t default_pseudocode = {
+	sizeof(default_cmds) / sizeof(irq_cmd_t),
+	default_cmds
+};
+
+typedef void interrupt_handler_t(device_t *dev, ipc_callid_t iid, ipc_call_t *icall);
+
+typedef struct interrupt_context {
+	int id;
+	device_t *dev;
+	int irq;
+	interrupt_handler_t *handler;
+	link_t link;
+} interrupt_context_t;
+
+typedef struct interrupt_context_list {
+	int curr_id;
+	link_t contexts;
+	fibril_mutex_t mutex;
+} interrupt_context_list_t;
+
+static inline interrupt_context_t * create_interrupt_context()
+{ 
+	interrupt_context_t *ctx = (interrupt_context_t *)malloc(sizeof(interrupt_context_t));
+	if (NULL != ctx) {
+		memset(ctx, 0, sizeof(interrupt_context_t));
+	}
+	return ctx;
+}
+
+static inline void delete_interrupt_context(interrupt_context_t *ctx)
+{
+	if (NULL != ctx) {
+		free(ctx);
+	}
+}
+
+static inline void init_interrupt_context_list(interrupt_context_list_t *list)
+{
+	memset(list, 0, sizeof(interrupt_context_list_t));
+	fibril_mutex_initialize(&list->mutex);
+	list_initialize(&list->contexts);	
+}
+
+static inline void add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
+{
+	fibril_mutex_lock(&list->mutex);
+	
+	ctx->id = list->curr_id++;
+	list_append(&ctx->link, &list->contexts);
+	
+	fibril_mutex_unlock(&list->mutex);
+}
+
+static inline void remove_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)
+{
+	fibril_mutex_lock(&list->mutex);
+	
+	list_remove(&ctx->link);
+	
+	fibril_mutex_unlock(&list->mutex);
+}
+
+static inline interrupt_context_t *find_interrupt_context_by_id(interrupt_context_list_t *list, int id) 
+{
+	fibril_mutex_lock(&list->mutex);	
+	link_t *link = list->contexts.next;
+	interrupt_context_t *ctx;
+	
+	while (link != &list->contexts) {
+		ctx = list_get_instance(link, interrupt_context_t, link);
+		if (id == ctx->id) {
+			fibril_mutex_unlock(&list->mutex);
+			return ctx;
+		}
+		link = link->next;
+	}	
+	fibril_mutex_unlock(&list->mutex);	
+	return NULL;
+}
+
+static inline interrupt_context_t *find_interrupt_context(interrupt_context_list_t *list, device_t *dev, int irq) 
+{
+	fibril_mutex_lock(&list->mutex);	
+	link_t *link = list->contexts.next;
+	interrupt_context_t *ctx;
+	
+	while (link != &list->contexts) {
+		ctx = list_get_instance(link, interrupt_context_t, link);
+		if (irq == ctx->irq && dev == ctx->dev) {
+			fibril_mutex_unlock(&list->mutex);
+			return ctx;
+		}
+		link = link->next;
+	}	
+	fibril_mutex_unlock(&list->mutex);	
+	return NULL;
+}
 
 #endif
Index: uspace/srv/drivers/serial/serial.c
===================================================================
--- uspace/srv/drivers/serial/serial.c	(revision 953bc1efafe8161834d87acae8f871ef640154a5)
+++ uspace/srv/drivers/serial/serial.c	(revision cfe7716bf85413141220c5c75d82d669b65455dc)
@@ -238,4 +238,33 @@
 }
 
+static int serial_interrupt_enable(device_t *dev)
+{
+	serial_dev_data_t *data = (serial_dev_data_t *)dev->driver_data;
+	
+	// enable interrupt globally	
+	enable_interrupt(data->irq);
+	
+	// enable interrupt on the serial port
+	pio_write_8(data->port + 1 , 0x01);   // Interrupt when data received
+	pio_write_8(data->port + 4, 0x0B);
+	
+	return EOK;
+}
+
+static void serial_initialize_port(device_t *dev)
+{
+	serial_dev_data_t *data = (serial_dev_data_t *)dev->driver_data;
+	ioport8_t *port = data->port;
+	
+	pio_write_8(port + 1, 0x00);    // Disable all interrupts
+	pio_write_8(port + 3, 0x80);    // Enable DLAB (set baud rate divisor)
+	pio_write_8(port + 0, 0x60);    // Set divisor to 96 (lo byte) 1200 baud
+	pio_write_8(port + 1, 0x00);    //                   (hi byte)
+	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 - needed for interrupts	
+}
+
 static int serial_add_device(device_t *dev) 
 {
@@ -250,7 +279,7 @@
 		serial_dev_cleanup(dev);
 		return EADDRNOTAVAIL;
-	}
-	
-	
+	}	
+	
+	// find out whether the device is present
 	if (!serial_dev_probe(dev)) {
 		serial_dev_cleanup(dev);
@@ -258,5 +287,14 @@
 	}	
 	
-	// TODO interrupt and serial port initialization (baud rate etc.)
+	// serial port initialization (baud rate etc.)
+	serial_initialize_port(dev);
+	
+	// TODO register interrupt handler
+	
+	// enable interrupt
+	if (0 != (res = serial_interrupt_enable(dev))) {
+		serial_dev_cleanup(dev);
+		return res;
+	}		
 	
 	return EOK;
