Index: arch/mips32/Makefile.inc
===================================================================
--- arch/mips32/Makefile.inc	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ arch/mips32/Makefile.inc	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -109,3 +109,4 @@
 	arch/$(ARCH)/src/fmath.c \
 	arch/$(ARCH)/src/drivers/arc.c \
-	arch/$(ARCH)/src/drivers/keyboard.c
+	arch/$(ARCH)/src/drivers/msim.c \
+	arch/$(ARCH)/src/drivers/serial.c
Index: arch/mips32/include/console.h
===================================================================
--- arch/mips32/include/console.h	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ arch/mips32/include/console.h	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -31,10 +31,4 @@
 
 
-#define VIDEORAM	0xB0000000
-
-#define SERIAL_PORT_BASE	((char *) 0xB80003f8 )
-#define SERIAL_LSR              ((char *) (SERIAL_PORT_BASE + 5))
-#define TRANSMIT_EMPTY_BIT      5          
-
 void console_init(void);
 
Index: arch/mips32/include/drivers/arc.h
===================================================================
--- arch/mips32/include/drivers/arc.h	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ arch/mips32/include/drivers/arc.h	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -31,4 +31,5 @@
 
 #include <arch/types.h>
+#include <console/chardev.h>
 
 #define ARC_BASE_ADDR 0x1000;
@@ -213,8 +214,7 @@
 extern void arc_print_memory_map(void);
 extern int arc_enabled(void);
-extern void arc_putchar(char ch);
 extern void arc_print_devices(void);
-extern int arc_getchar(void);
 void arc_frame_init(void);
+chardev_t * arc_console(void);
 
 #endif
Index: arch/mips32/include/drivers/keyboard.h
===================================================================
--- arch/mips32/include/drivers/keyboard.h	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ 	(revision )
@@ -1,42 +1,0 @@
-/*
- * Copyright (C) 2005 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.
- */
-
-#ifndef __mips32_KEYBOARD_H__
-#define __mips32_KEYBOARD_H__
-
-#include <arch/types.h>
-#include <arch/interrupt.h>
-
-/** Address of 'keyboard' device. */
-#define KEYBOARD_ADDRESS		0xB0000000
-
-extern void keyboard_init(void);
-extern void keyboard(void);
-extern void keyboard_poll(void);
-
-#endif
Index: arch/mips32/include/drivers/msim.h
===================================================================
--- arch/mips32/include/drivers/msim.h	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
+++ arch/mips32/include/drivers/msim.h	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef _MSIM_H_
+#define _MSIM_H_
+
+#include <console/chardev.h>
+
+#define MSIM_VIDEORAM            0xB0000000
+/** Address of 'keyboard' device. */
+#define MSIM_KBD_ADDRESS		0xB0000000
+#define MSIM_KBD_IRQ	2
+
+chardev_t * msim_console(void);
+
+#endif
Index: arch/mips32/include/drivers/serial.h
===================================================================
--- arch/mips32/include/drivers/serial.h	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
+++ arch/mips32/include/drivers/serial.h	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#ifndef __DRV_SERIAL_H__
+#define __DRV_SERIAL_H__
+
+#include <console/chardev.h>
+
+#define SERIAL_MAX        4
+#define SERIAL_COM1       0x3f8
+#define SERIAL_COM1_IRQ   4
+#define SERIAL_COM2       0x2f8
+#define SERIAL_COM2_IRQ   3
+
+#define P_WRITEB(where,what)     (*((volatile char *) (0xB8000000+where))=what)
+#define P_READB(where)           (*((volatile char *)(0xB8000000+where)))
+
+#define SERIAL_READ(x)           P_READB(x)
+#define SERIAL_WRITE(x,c)        P_WRITEB(x,c)
+/* Interrupt enable register */
+#define SERIAL_READ_IER(x)              (P_READB((x) + 1))
+#define SERIAL_WRITE_IER(x,c)           (P_WRITEB((x)+1,c))
+/* Interrupt identification register */
+#define SERIAL_READ_IIR(x)             (P_READB((x) + 2))
+/* Line status register */
+#define SERIAL_READ_LSR(x)             (P_READB((x) + 5))
+#define TRANSMIT_EMPTY_BIT      5          
+
+typedef struct {
+	int port;
+	int irq;
+}serial_t;
+
+chardev_t * serial_console(void);
+int serial_init(void);
+
+#endif
Index: arch/mips32/include/interrupt.h
===================================================================
--- arch/mips32/include/interrupt.h	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ arch/mips32/include/interrupt.h	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -32,12 +32,14 @@
 #include <arch/exception.h>
 
+#define IVT_ITEMS   32
+
 #define IRQ2	2
 #define IRQ3	3
 #define IRQ7	7
 
-#define KEYBOARD_IRQ	IRQ2
 #define TIMER_IRQ   	IRQ7
 
 extern void interrupt(struct exception_regdump *pstate);
+extern void interrupt_init(void);
 
 #endif
Index: arch/mips32/src/console.c
===================================================================
--- arch/mips32/src/console.c	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ arch/mips32/src/console.c	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -27,47 +27,22 @@
  */
 
-#include <putchar.h>
-#include <arch/types.h>
-#include <arch/cp0.h>
+#include <console/console.h>
 #include <arch/console.h>
-#include <arch.h>
 #include <arch/drivers/arc.h>
-#include <arch/arch.h>
-
-/** Putchar that works with MSIM & gxemul */
-static void cons_putchar(const char ch)
-{
-	*((char *) VIDEORAM) = ch;
-}
-
-/** Putchar that works with simics */
-static void serial_putchar(const char ch)
-{
-	int i;
-
-	if (ch=='\n')
-		putchar('\r');
-
-	/* Wait until transmit buffer empty */
-	while (! ((*SERIAL_LSR) & (1<<TRANSMIT_EMPTY_BIT)))
-		;
-	*(SERIAL_PORT_BASE) = ch;
-}
-
-static void (*putchar_func)(const char ch) = cons_putchar;
+#include <arch/drivers/serial.h>
+#include <arch/drivers/msim.h>
 
 void console_init(void)
 {
-	if (arc_enabled()) 
-		putchar_func = arc_putchar;
-	/* The LSR on the start usually contains this value */
-	else if (*SERIAL_LSR == 0x60)
-		putchar_func = serial_putchar;
-	else
-		putchar_func = cons_putchar;
+	chardev_t *console;
+
+	if (arc_enabled()) {
+		console = arc_console();
+	} else if (serial_init()) {
+		console = serial_console();
+	} else
+		console = msim_console();
+
+	stdin = console;
+	stdout = console;
 }
-
-void putchar(const char ch)
-{
-	putchar_func(ch);
-}
Index: arch/mips32/src/drivers/arc.c
===================================================================
--- arch/mips32/src/drivers/arc.c	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ arch/mips32/src/drivers/arc.c	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -34,4 +34,5 @@
 #include <arch/mm/frame.h>
 #include <mm/frame.h>
+#include <interrupt.h>
 
 /* This is a good joke, SGI HAS different types than NT bioses... */
@@ -98,23 +99,6 @@
 static arc_func_vector_t *arc_entry; 
 
-static void _arc_putchar(char ch);
-
-/** Initialize ARC structure
- *
- * @return 0 - ARC OK, -1 - ARC does not exist
- */
-int arc_init(void)
-{
-	if (sbp->signature != ARC_MAGIC) {
-		sbp = NULL;
-		return -1;
-	}
-	arc_entry = sbp->firmwarevector;
-
-	arc_putchar('A');
-	arc_putchar('R');
-	arc_putchar('C');
-	arc_putchar('\n');
-}
+
+static void arc_putchar(char ch);
 
 /** Return true if ARC is available */
@@ -130,6 +114,6 @@
 	printf("%s: ",ctypes[c->type]);
 	for (i=0;i < c->identifier_len;i++)
-		putchar(c->identifier[i]);
-	putchar('\n');
+		arc_putchar(c->identifier[i]);
+	arc_putchar('\n');
 }
 
@@ -175,5 +159,5 @@
 
 /** Print charactor to console */
-void arc_putchar(char ch)
+static void arc_putchar(char ch)
 {
 	__u32 cnt;
@@ -187,21 +171,85 @@
 }
 
+/** Initialize ARC structure
+ *
+ * @return 0 - ARC OK, -1 - ARC does not exist
+ */
+int arc_init(void)
+{
+	if (sbp->signature != ARC_MAGIC) {
+		sbp = NULL;
+		return -1;
+	}
+	arc_entry = sbp->firmwarevector;
+
+	arc_putchar('A');
+	arc_putchar('R');
+	arc_putchar('C');
+	arc_putchar('\n');
+}
+
+static int kbd_polling_enabled;
+static chardev_t console;
+
 /** Try to get character, return character or -1 if not available */
-int arc_getchar(void)
+static void arc_keyboard_poll(void)
 {
 	char ch;
 	__u32 count;
 	long result;
+	
+	if (! kbd_polling_enabled)
+		return;
 
 	if (arc_entry->getreadstatus(0))
-		return -1;
+		return;
 	result = arc_entry->read(0, &ch, 1, &count);
 	if (result || count!=1) {
-		cpu_halt();
-		return -1;
+		return;
 	}
 	if (ch == '\r')
-		return '\n';
-	return ch;
+		ch = '\n';
+
+	chardev_push_character(&console, ch);
+}
+
+static void arc_write(chardev_t *dev, const char ch)
+{
+	arc_putchar(ch);
+}
+
+static void arc_enable(chardev_t *dev)
+{
+	kbd_polling_enabled = 1;	
+}
+
+static void arc_disable(chardev_t *dev)
+{
+	kbd_polling_enabled = 0;
+}
+
+static chardev_operations_t arc_ops = {
+	.resume = arc_enable,
+	.suspend = arc_disable,
+	.write = arc_write
+};
+
+iroutine old_timer;
+/** Do polling on timer interrupt */
+static void timer_replace(int n, void *stack)
+{
+	arc_keyboard_poll();
+	old_timer(n, stack);
+	arc_keyboard_poll();
+}
+
+
+chardev_t * arc_console(void)
+{
+	kbd_polling_enabled = 1;
+	
+	chardev_initialize("arc_console", &console, &arc_ops);
+	old_timer = exc_register(TIMER_IRQ, "arc_kb_poll", timer_replace);
+	return &console;
 }
 
Index: arch/mips32/src/drivers/keyboard.c
===================================================================
--- arch/mips32/src/drivers/keyboard.c	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ 	(revision )
@@ -1,117 +1,0 @@
-/*
- * Copyright (C) 2003 Josef Cejka
- * Copyright (C) 2005 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.
- */
-
-#include <arch/drivers/keyboard.h>
-#include <console/chardev.h>
-#include <console/console.h>
-#include <arch/cp0.h>
-#include <putchar.h>
-#include <synch/spinlock.h>
-#include <synch/waitq.h>
-#include <typedefs.h>
-#include <arch/drivers/arc.h>
-
-static void keyboard_enable(void);
-static void keyboard_disable(void);
-static void arc_kb_disable(void);
-static void arc_kb_enable(void);
-
-static chardev_t kbrd;
-
-static chardev_operations_t arc_ops = {
-	.resume = arc_kb_enable,
-	.suspend = arc_kb_disable
-};
-
-static chardev_operations_t msim_ops = {
-	.resume = keyboard_enable,
-	.suspend = keyboard_disable
-};
-
-static int arc_kb_enabled;
-
-/** Initialize keyboard subsystem. */
-void keyboard_init(void)
-{
-	if (arc_enabled()) {
-		chardev_initialize(&kbrd, &arc_ops);
-		arc_kb_enabled = 1;
-	} else {
-		cp0_unmask_int(KEYBOARD_IRQ);
-		chardev_initialize(&kbrd, &msim_ops);
-	}
-	stdin = &kbrd;
-}
-
-/** Process keyboard interrupt. */
-void keyboard(void)
-{
-	char ch;
-
-	ch = *((char *) KEYBOARD_ADDRESS);
-	if (ch =='\r')
-		ch = '\n';
-	chardev_push_character(&kbrd, ch);
-}
-
-/* Called from getc(). */
-void keyboard_enable(void)
-{
-	cp0_unmask_int(KEYBOARD_IRQ);
-}
-
-/* Called from getc(). */
-void keyboard_disable(void)
-{
-	cp0_mask_int(KEYBOARD_IRQ);
-}
-
-/*****************************/
-/* Arc keyboard */
-
-void keyboard_poll(void)
-{
-	int ch;
-
-	if (!arc_enabled() || !arc_kb_enabled)
-		return;
-	while ((ch = arc_getchar()) != -1)
-		chardev_push_character(&kbrd, ch);		
-}
-
-static void arc_kb_enable(void)
-{
-	arc_kb_enabled = 1;
-}
-
-/* Called from getc(). */
-static void arc_kb_disable(void)
-{
-	arc_kb_enabled = 0;
-}
Index: arch/mips32/src/drivers/msim.c
===================================================================
--- arch/mips32/src/drivers/msim.c	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
+++ arch/mips32/src/drivers/msim.c	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#include <interrupt.h>
+#include <console/chardev.h>
+#include <arch/drivers/msim.h>
+#include <arch/cp0.h>
+
+static chardev_t console;
+
+static void msim_write(chardev_t *dev, const char ch);
+static void msim_enable(chardev_t *dev);
+static void msim_disable(chardev_t *dev);
+
+static chardev_operations_t msim_ops = {
+	.resume = msim_enable,
+	.suspend = msim_disable,
+	.write = msim_write
+};
+
+/** Putchar that works with MSIM & gxemul */
+void msim_write(chardev_t *dev, const char ch)
+{
+	*((char *) MSIM_VIDEORAM) = ch;
+}
+
+/* Called from getc(). */
+void msim_enable(chardev_t *dev)
+{
+	cp0_unmask_int(MSIM_KBD_IRQ);
+}
+
+/* Called from getc(). */
+void msim_disable(chardev_t *dev)
+{
+	cp0_mask_int(MSIM_KBD_IRQ);
+}
+
+/** Process keyboard interrupt. */
+static void msim_interrupt(int n, void *stack)
+{
+	char ch;
+
+	ch = *((char *) MSIM_KBD_ADDRESS);
+	if (ch =='\r')
+		ch = '\n';
+	chardev_push_character(&console, ch);
+}
+
+
+/* Return console object representing msim console */
+chardev_t * msim_console(void)
+{
+	chardev_initialize("msim_console", &console, &msim_ops);
+
+	exc_register(MSIM_KBD_IRQ, "msim_kbd", msim_interrupt);
+
+	cp0_unmask_int(MSIM_KBD_IRQ);
+
+	return &console;
+}
Index: arch/mips32/src/drivers/serial.c
===================================================================
--- arch/mips32/src/drivers/serial.c	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
+++ arch/mips32/src/drivers/serial.c	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#include <interrupt.h>
+#include <arch/cp0.h>
+#include <arch/drivers/serial.h>
+#include <console/chardev.h>
+#include <console/console.h>
+
+static chardev_t console;
+
+static serial_t sconf[SERIAL_MAX];
+
+static void serial_write(chardev_t *d, const char ch)
+{
+	int i;
+	serial_t *sd = (serial_t *)d->data;
+
+	if (ch == '\n')
+		serial_write(d, '\r');
+	/* Wait until transmit buffer empty */
+	while (! (SERIAL_READ_LSR(sd->port) & (1<<TRANSMIT_EMPTY_BIT)))
+		;
+	SERIAL_WRITE(sd->port, ch);
+}
+
+static void serial_enable(chardev_t *d)
+{
+}
+
+static void serial_disable(chardev_t *d)
+{
+}
+
+int serial_init(void)
+{
+	int i = 0;
+	if (SERIAL_READ_LSR(SERIAL_COM1) == 0x60) {
+		sconf[i].port = SERIAL_COM1;
+		sconf[i].irq = SERIAL_COM1_IRQ;
+		/* Enable interrupt on available data */
+		i++;
+	}
+	return i;
+}
+
+static chardev_operations_t serial_ops = {
+	.resume = serial_enable,
+	.suspend = serial_disable,
+	.write = serial_write
+};
+
+/** Process keyboard interrupt. Does not work in simics? */
+static void serial_interrupt(int n, void *stack)
+{
+	serial_t *sd = (serial_t *)console.data;
+	char ch;
+
+	if (!(SERIAL_READ_LSR(sd->port) & 1))
+		return;
+	ch = SERIAL_READ(sd->port);
+
+	if (ch =='\r')
+		ch = '\n';
+	chardev_push_character(&console, ch);
+}
+
+
+iroutine old_timer;
+/** Do polling on timer interrupt */
+static void timer_replace(int n, void *stack)
+{
+	old_timer(n, stack);
+	serial_interrupt(n, stack);
+}
+
+#include <print.h>
+chardev_t * serial_console(void)
+{
+	serial_t *sd = &sconf[0];
+
+
+	chardev_initialize("serial_console", &console, &serial_ops);
+	console.data = sd;
+
+//	exc_register(2, "serial_drvr", serial_interrupt);
+	/* I don't know why, but the serial interrupts simply
+	 * don't work on simics
+	 */
+	old_timer = exc_register(TIMER_IRQ, "serial_drvr_poll", timer_replace);
+	
+
+	return &console;
+	
+}
Index: arch/mips32/src/interrupt.c
===================================================================
--- arch/mips32/src/interrupt.c	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ arch/mips32/src/interrupt.c	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -27,4 +27,5 @@
  */
 
+#include <interrupt.h>
 #include <arch/interrupt.h>
 #include <arch/types.h>
@@ -36,5 +37,4 @@
 #include <symtab.h>
 #include <arch/drivers/arc.h>
-#include <arch/drivers/keyboard.h>
 
 static void print_regdump(struct exception_regdump *pstate)
@@ -94,4 +94,29 @@
 }
 
+static void unhandled_exception(int n, void *stack)
+{
+	struct exception_regdump *pstate = (struct exception_regdump *)stack;
+
+	print_regdump(pstate);
+	panic("unhandled interrupt %d\n", n);
+}
+
+static void timer_exception(int n, void *stack)
+{
+	cp0_compare_write(cp0_count_read() + cp0_compare_value); 
+	clock();
+}
+
+static void swint0(int n, void *stack)
+{
+	cp0_cause_write(cp0_cause_read() & ~(1 << 8)); /* clear SW0 interrupt */
+}
+
+static void swint1(int n, void *stack)
+{
+	cp0_cause_write(cp0_cause_read() & ~(1 << 9)); /* clear SW1 interrupt */
+}
+
+/** Basic exception handler */
 void interrupt(struct exception_regdump *pstate)
 {
@@ -102,33 +127,19 @@
 	cause = (cp0_cause_read() >> 8) &0xff;
 	
-	for (i = 0; i < 8; i++) {
-		if (cause & (1 << i)) {
-			switch (i) {
-				case 0: /* SW0 - Software interrupt 0 */
-					cp0_cause_write(cp0_cause_read() & ~(1 << 8)); /* clear SW0 interrupt */
-					break;
-				case 1: /* SW1 - Software interrupt 1 */
-					cp0_cause_write(cp0_cause_read() & ~(1 << 9)); /* clear SW1 interrupt */
-					break;
-				case KEYBOARD_IRQ:
-					keyboard();
-					break;
-			        case 3:
-				case 4: /* IRQ2 */
-				case 5: /* IRQ3 */
-				case 6: /* IRQ4 */
-				default:
-					print_regdump(pstate);
-					panic("unhandled interrupt %d\n", i);
-					break;
-				case TIMER_IRQ:
-					/* clear timer interrupt & set new */
-					cp0_compare_write(cp0_count_read() + cp0_compare_value); 
-					clock();
-					keyboard_poll();
-					break;
-			}
-		}
-	}
+	for (i = 0; i < 8; i++)
+		if (cause & (1 << i))
+			exc_dispatch(i, (void *)pstate);
+}
 
+/* Initialize basic tables for exception dispatching */
+void interrupt_init(void)
+{
+	int i;
+
+	for (i=0;i < IVT_ITEMS; i++)
+		exc_register(i, "undef", unhandled_exception);
+
+	exc_register(TIMER_IRQ, "timer", timer_exception);
+	exc_register(0, "swint0", swint0);
+	exc_register(1, "swint1", swint1);
 }
Index: arch/mips32/src/mips32.c
===================================================================
--- arch/mips32/src/mips32.c	(revision 705b4149822f194ae48b3897b40aa114729244e1)
+++ arch/mips32/src/mips32.c	(revision fcfac420803a43318bce80248d718b848e2bcaa3)
@@ -27,18 +27,22 @@
  */
 
+
 #include <arch.h>
 #include <arch/cp0.h>
 #include <arch/exception.h>
-#include <arch/asm/regname.h>
 #include <arch/asm.h>
 #include <mm/vm.h>
+
 #include <userspace.h>
 #include <arch/console.h>
 #include <memstr.h>
+#include <proc/thread.h>
+#include <print.h>
+
 #include <arch/interrupt.h>
 #include <arch/drivers/arc.h>
-#include <arch/drivers/keyboard.h>
-#include <proc/thread.h>
-#include <print.h>
+#include <console/chardev.h>
+
+#include <arch/asm/regname.h>
 
 /* Size of the code jumping to the exception handler code 
@@ -55,4 +59,7 @@
 	/* It is not assumed by default */
 	interrupts_disable();
+	
+	/* Initialize dispatch table */
+	interrupt_init();
 
 	arc_init();
@@ -84,5 +91,4 @@
 
 	console_init();
-	keyboard_init();
 	arc_print_memory_map();
 	arc_print_devices();
