Index: kernel/arch/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/amd64/src/amd64.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -198,8 +198,13 @@
 	 * module and connect it to i8042. Enable keyboard interrupts.
 	 */
-	indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
-	if (kbrdin) {
-		kbrd_init(kbrdin);
-		trap_virtual_enable_irqs(1 << IRQ_KBD);
+	i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
+	if (i8042_instance) {
+		kbrd_instance_t *kbrd_instance = kbrd_init();
+		if (kbrd_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
+			i8042_wire(i8042_instance, kbrd);
+			trap_virtual_enable_irqs(1 << IRQ_KBD);
+		}
 	}
 	
Index: kernel/arch/arm32/Makefile.inc
===================================================================
--- kernel/arch/arm32/Makefile.inc	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/arm32/Makefile.inc	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -52,5 +52,4 @@
 	arch/$(KARCH)/src/ddi/ddi.c \
 	arch/$(KARCH)/src/interrupt.c \
-	arch/$(KARCH)/src/console.c \
 	arch/$(KARCH)/src/exception.c \
 	arch/$(KARCH)/src/userspace.c \
Index: kernel/arch/arm32/include/console.h
===================================================================
--- kernel/arch/arm32/include/console.h	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ 	(revision )
@@ -1,42 +1,0 @@
-/*
- * Copyright (c) 2007 Michal Kebrt
- * 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 arm32	
- * @{
- */
-/** @file
- *  @brief Console.
- */
-
-#ifndef KERN_arm32_CONSOLE_H_
-#define KERN_arm32_CONSOLE_H_
-
-#endif
-
-/** @}
- */
Index: kernel/arch/arm32/src/arm32.c
===================================================================
--- kernel/arch/arm32/src/arm32.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/arm32/src/arm32.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -36,5 +36,4 @@
 #include <arch.h>
 #include <config.h>
-#include <arch/console.h>
 #include <genarch/fb/fb.h>
 #include <genarch/fb/visuals.h>
@@ -43,4 +42,5 @@
 #include <genarch/srln/srln.h>
 #include <sysinfo/sysinfo.h>
+#include <console/console.h>
 #include <ddi/irq.h>
 #include <arch/drivers/gxemul.h>
@@ -130,9 +130,16 @@
 	/*
 	 * Initialize the GXemul keyboard port. Then initialize the serial line
-	 * module and connect it to the GXemul keyboard. Enable keyboard interrupts.
+	 * module and connect it to the GXemul keyboard.
 	 */
-	indev_t *kbrdin = dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ);
-	if (kbrdin)
-		srln_init(kbrdin);
+	dsrlnin_instance_t *dsrlnin_instance
+	    = dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ);
+	if (dsrlnin_instance) {
+		srln_instance_t *srln_instance = srln_init();
+		if (srln_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *srln = srln_wire(srln_instance, sink);
+			dsrlnin_wire(dsrlnin_instance, srln);
+		}
+	}
 	
 	/*
@@ -202,4 +209,17 @@
 }
 
+/** Acquire console back for kernel. */
+void arch_grab_console(void)
+{
+#ifdef CONFIG_FB
+	fb_redraw();
+#endif
+}
+
+/** Return console to userspace. */
+void arch_release_console(void)
+{
+}
+
 /** @}
  */
Index: kernel/arch/arm32/src/console.c
===================================================================
--- kernel/arch/arm32/src/console.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2007 Michal Kebrt
- * 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 arm32
- * @{
- */
-/** @file
- *  @brief Console.
- */
-
-#include <console/console.h>
-#include <arch/console.h>
-#include <genarch/fb/fb.h>
-
-/** Acquire console back for kernel. */
-void arch_grab_console(void)
-{
-#ifdef CONFIG_FB
-	fb_redraw();
-#endif
-}
-
-/** Return console to userspace. */
-void arch_release_console(void)
-{
-}
-
-/** @}
- */
Index: kernel/arch/ia32/src/ia32.c
===================================================================
--- kernel/arch/ia32/src/ia32.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ia32/src/ia32.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -81,5 +81,5 @@
 {
 	/* Parse multiboot information obtained from the bootloader. */
-	multiboot_info_parse(signature, mi);	
+	multiboot_info_parse(signature, mi);
 	
 #ifdef CONFIG_SMP
@@ -156,8 +156,13 @@
 	 * module and connect it to i8042. Enable keyboard interrupts.
 	 */
-	indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
-	if (kbrdin) {
-		kbrd_init(kbrdin);
-		trap_virtual_enable_irqs(1 << IRQ_KBD);
+	i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
+	if (i8042_instance) {
+		kbrd_instance_t *kbrd_instance = kbrd_init();
+		if (kbrd_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
+			i8042_wire(i8042_instance, kbrd);
+			trap_virtual_enable_irqs(1 << IRQ_KBD);
+		}
 	}
 	
Index: kernel/arch/ia64/Makefile.inc
===================================================================
--- kernel/arch/ia64/Makefile.inc	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ia64/Makefile.inc	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -65,6 +65,5 @@
 
 ifeq ($(MACHINE),ski)
-	ARCH_SOURCES += arch/$(KARCH)/src/ski/ski.c
-	DEFS += -DSKI
+	ARCH_SOURCES += arch/$(KARCH)/src/drivers/ski.c
 	BFD = binary
 endif
Index: kernel/arch/ia64/include/arch.h
===================================================================
--- kernel/arch/ia64/include/arch.h	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ia64/include/arch.h	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ia64	
+/** @addtogroup ia64
  * @{
  */
@@ -38,5 +38,5 @@
 #define LOADED_PROG_STACK_PAGES_NO 2
 
-#include <arch/ski/ski.h>
+#include <arch/drivers/ski.h>
 
 extern void arch_pre_main(void);
Index: kernel/arch/ia64/include/drivers/ski.h
===================================================================
--- kernel/arch/ia64/include/drivers/ski.h	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
+++ kernel/arch/ia64/include/drivers/ski.h	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup ia64
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_ia64_SKI_H_
+#define KERN_ia64_SKI_H_
+
+#include <console/chardev.h>
+#include <proc/thread.h>
+
+typedef struct {
+	thread_t *thread;
+	indev_t *srlnin;
+} ski_instance_t;
+
+extern void skiout_init(void);
+
+extern ski_instance_t *skiin_init(void);
+extern void skiin_wire(ski_instance_t *, indev_t *);
+extern void ski_kbd_grab(void);
+extern void ski_kbd_release(void);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/ia64/include/ski/ski.h
===================================================================
--- kernel/arch/ia64/include/ski/ski.h	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ 	(revision )
@@ -1,52 +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.
- */
-
-/** @addtogroup ia64	
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_ia64_SKI_H_
-#define KERN_ia64_SKI_H_
-
-#include <console/chardev.h>
-
-#define SKI_INIT_CONSOLE	20
-#define SKI_GETCHAR		21
-#define SKI_PUTCHAR		31
-
-extern indev_t *skiin_init(void);
-extern void skiout_init(void);
-extern void ski_kbd_grab(void);
-extern void ski_kbd_release(void);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/ia64/src/drivers/ski.c
===================================================================
--- kernel/arch/ia64/src/drivers/ski.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
+++ kernel/arch/ia64/src/drivers/ski.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup ia64
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/drivers/ski.h>
+#include <console/console.h>
+#include <console/chardev.h>
+#include <sysinfo/sysinfo.h>
+#include <arch/types.h>
+#include <proc/thread.h>
+#include <synch/spinlock.h>
+#include <arch/asm.h>
+#include <arch/drivers/kbd.h>
+#include <string.h>
+#include <arch.h>
+
+#define POLL_INTERVAL  10000  /* 10 ms */
+
+#define SKI_INIT_CONSOLE  20
+#define SKI_GETCHAR       21
+#define SKI_PUTCHAR       31
+
+static void ski_putchar(outdev_t *, const wchar_t, bool);
+
+static outdev_operations_t skiout_ops = {
+	.write = ski_putchar
+};
+
+static outdev_t skiout;            /**< Ski output device. */
+static bool initialized = false;
+static bool kbd_disabled = false;
+
+/** Initialize debug console
+ *
+ * Issue SSC (Simulator System Call) to
+ * to open debug console.
+ *
+ */
+static void ski_init(void)
+{
+	if (initialized)
+		return;
+	
+	asm volatile (
+		"mov r15 = %0\n"
+		"break 0x80000\n"
+		:
+		: "i" (SKI_INIT_CONSOLE)
+		: "r15", "r8"
+	);
+	
+	initialized = true;
+}
+
+static void ski_do_putchar(const wchar_t ch)
+{
+	asm volatile (
+		"mov r15 = %[cmd]\n"
+		"mov r32 = %[ch]\n"   /* r32 is in0 */
+		"break 0x80000\n"     /* modifies r8 */
+		:
+		: [cmd] "i" (SKI_PUTCHAR), [ch] "r" (ch)
+		: "r15", "in0", "r8"
+	);
+}
+
+/** Display character on debug console
+ *
+ * Use SSC (Simulator System Call) to
+ * display character on debug console.
+ *
+ * @param dev    Character device.
+ * @param ch     Character to be printed.
+ * @param silent Whether the output should be silenced.
+ *
+ */
+static void ski_putchar(outdev_t *dev, const wchar_t ch, bool silent)
+{
+	if (!silent) {
+		if (ascii_check(ch)) {
+			if (ch == '\n')
+				ski_do_putchar('\r');
+			
+			ski_do_putchar(ch);
+		} else
+			ski_do_putchar(U_SPECIAL);
+	}
+}
+
+void skiout_init(void)
+{
+	ski_init();
+	
+	outdev_initialize("skiout", &skiout, &skiout_ops);
+	stdout = &skiout;
+	
+	sysinfo_set_item_val("fb", NULL, false);
+}
+
+/** Ask debug console if a key was pressed.
+ *
+ * Use SSC (Simulator System Call) to
+ * get character from debug console.
+ *
+ * This call is non-blocking.
+ *
+ * @return ASCII code of pressed key or 0 if no key pressed.
+ *
+ */
+static wchar_t ski_getchar(void)
+{
+	uint64_t ch;
+	
+	asm volatile (
+		"mov r15 = %1\n"
+		"break 0x80000;;\n"  /* modifies r8 */
+		"mov %0 = r8;;\n"
+		
+		: "=r" (ch)
+		: "i" (SKI_GETCHAR)
+		: "r15", "r8"
+	);
+	
+	return (wchar_t) ch;
+}
+
+/** Ask keyboard if a key was pressed. */
+static void poll_keyboard(ski_instance_t *instance)
+{
+	if (kbd_disabled)
+		return;
+	
+	wchar_t ch = ski_getchar();
+	
+	if (ch != 0)
+		indev_push_character(instance->srlnin, ch);
+}
+
+/** Kernel thread for polling keyboard. */
+static void kskipoll(void *arg)
+{
+	ski_instance_t *instance = (ski_instance_t *) arg;
+	
+	while (true) {
+		if (!silent)
+			poll_keyboard(instance);
+		
+		thread_usleep(POLL_INTERVAL);
+	}
+}
+
+ski_instance_t *skiin_init(void)
+{
+	ski_init();
+	
+	ski_instance_t *instance
+	    = malloc(sizeof(ski_instance_t), FRAME_ATOMIC);
+	
+	if (instance) {
+		instance->thread = thread_create(kskipoll, (void *) instance, TASK, 0, "kskipoll", true);
+		
+		if (!instance->thread) {
+			free(instance);
+			return NULL;
+		}
+		
+		instance->srlnin = NULL;
+	}
+	
+	return instance;
+}
+
+void skiin_wire(ski_instance_t *instance, indev_t *srlnin)
+{
+	ASSERT(instance);
+	ASSERT(srlnin);
+	
+	instance->srlnin = srlnin;
+	thread_ready(instance->thread);
+	
+	sysinfo_set_item_val("kbd", NULL, true);
+	sysinfo_set_item_val("kbd.type", NULL, KBD_SKI);
+}
+
+void ski_kbd_grab(void)
+{
+	kbd_disabled = true;
+}
+
+void ski_kbd_release(void)
+{
+	kbd_disabled = false;
+}
+
+/** @}
+ */
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ia64/src/ia64.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -34,5 +34,5 @@
 
 #include <arch.h>
-#include <arch/ski/ski.h>
+#include <arch/drivers/ski.h>
 #include <arch/drivers/it.h>
 #include <arch/interrupt.h>
@@ -149,9 +149,15 @@
 void arch_post_smp_init(void)
 {
-#ifdef SKI
-	indev_t *in;
-	in = skiin_init();
-	if (in)
-		srln_init(in);
+#ifdef MACHINE_ski
+	ski_instance_t *ski_instance = skiin_init();
+	if (ski_instance) {
+		srln_instance_t *srln_instance = srln_init();
+		if (srln_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *srln = srln_wire(srln_instance, sink);
+			skiin_wire(ski_instance, srln);
+		}
+	}
+	
 	skiout_init();
 #endif
@@ -162,8 +168,14 @@
 	
 #ifdef CONFIG_NS16550
-	indev_t *kbrdin_ns16550
+	ns16550_instance_t *ns16550_instance
 	    = ns16550_init((ns16550_t *) NS16550_BASE, NS16550_IRQ, NULL, NULL);
-	if (kbrdin_ns16550)
-		srln_init(kbrdin_ns16550);
+	if (ns16550_instance) {
+		srln_instance_t *srln_instance = srln_init();
+		if (srln_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *srln = srln_wire(srln_instance, sink);
+			ns16550_wire(ns16550_instance, srln);
+		}
+	}
 	
 	sysinfo_set_item_val("kbd", NULL, true);
@@ -177,7 +189,13 @@
 	
 #ifdef CONFIG_I8042
-	indev_t *kbrdin_i8042 = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
-	if (kbrdin_i8042)
-		kbrd_init(kbrdin_i8042);
+	i8042_instance_t *i8042_instance = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
+	if (i8042_instance) {
+		kbrd_instance_t *kbrd_instance = kbrd_init();
+		if (kbrd_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
+			i8042_wire(i8042_instance, kbrd);
+		}
+	}
 	
 	sysinfo_set_item_val("kbd", NULL, true);
@@ -239,5 +257,5 @@
 void arch_grab_console(void)
 {
-#ifdef SKI
+#ifdef MACHINE_ski
 	ski_kbd_grab();
 #endif
@@ -249,5 +267,5 @@
 void arch_release_console(void)
 {
-#ifdef SKI
+#ifdef MACHINE_ski
 	ski_kbd_release();
 #endif
Index: kernel/arch/ia64/src/ski/ski.c
===================================================================
--- kernel/arch/ia64/src/ski/ski.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ 	(revision )
@@ -1,210 +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.
- */
-
-/** @addtogroup ia64
- * @{
- */
-/** @file
- */
-
-#include <arch/ski/ski.h>
-#include <console/console.h>
-#include <console/chardev.h>
-#include <sysinfo/sysinfo.h>
-#include <arch/types.h>
-#include <proc/thread.h>
-#include <synch/spinlock.h>
-#include <arch/asm.h>
-#include <arch/drivers/kbd.h>
-#include <string.h>
-#include <arch.h>
-
-static indev_t skiin;		/**< Ski input device. */
-static outdev_t skiout;		/**< Ski output device. */
-
-static bool kbd_disabled;
-
-static void ski_do_putchar(const wchar_t ch)
-{
-	asm volatile (
-		"mov r15 = %[cmd]\n"
-		"mov r32 = %[ch]\n"   /* r32 is in0 */
-		"break 0x80000\n"  /* modifies r8 */
-		:
-		: [cmd] "i" (SKI_PUTCHAR), [ch] "r" (ch)
-		: "r15", "in0", "r8"
-	);
-}
-
-/** Display character on debug console
- *
- * Use SSC (Simulator System Call) to
- * display character on debug console.
- *
- * @param d Character device.
- * @param ch Character to be printed.
- */
-static void ski_putchar(outdev_t *d, const wchar_t ch, bool silent)
-{
-	if (!silent) {
-		if (ascii_check(ch)) {
-			if (ch == '\n')
-				ski_do_putchar('\r');
-			
-			ski_do_putchar(ch);
-		} else
-			ski_do_putchar(SPECIAL);
-	}
-}
-
-static indev_operations_t skiin_ops = {
-	.poll = NULL
-};
-
-static outdev_operations_t skiout_ops = {
-	.write = ski_putchar
-};
-
-/** Ask debug console if a key was pressed.
- *
- * Use SSC (Simulator System Call) to
- * get character from debug console.
- *
- * This call is non-blocking.
- *
- * @return ASCII code of pressed key or 0 if no key pressed.
- */
-static int32_t ski_getchar(void)
-{
-	uint64_t ch;
-	
-	asm volatile (
-		"mov r15 = %1\n"
-		"break 0x80000;;\n"	/* modifies r8 */
-		"mov %0 = r8;;\n"		
-
-		: "=r" (ch)
-		: "i" (SKI_GETCHAR)
-		: "r15", "r8"
-	);
-
-	return (int32_t) ch;
-}
-
-/** Ask keyboard if a key was pressed. */
-static void poll_keyboard(void)
-{
-	char ch;
-	
-	if (kbd_disabled)
-		return;
-	ch = ski_getchar();
-	if(ch == '\r')
-		ch = '\n'; 
-	if (ch) {
-		indev_push_character(&skiin, ch);
-		return;
-	}
-}
-
-#define POLL_INTERVAL           10000           /* 10 ms */
-
-/** Kernel thread for polling keyboard. */
-static void kkbdpoll(void *arg)
-{
-	while (1) {
-		if (!silent) {
-			poll_keyboard();
-		}
-		thread_usleep(POLL_INTERVAL);
-	}
-}
-
-/** Initialize debug console
- *
- * Issue SSC (Simulator System Call) to
- * to open debug console.
- */
-static void ski_init(void)
-{
-	static bool initialized;
-
-	if (initialized)
-		return;
-	
-	asm volatile (
-		"mov r15 = %0\n"
-		"break 0x80000\n"
-		:
-		: "i" (SKI_INIT_CONSOLE)
-		: "r15", "r8"
-	);
-	
-	initialized = true;
-}
-
-indev_t *skiin_init(void)
-{
-	ski_init();
-
-	indev_initialize("skiin", &skiin, &skiin_ops);
-	thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
-	if (t)
-		thread_ready(t);
-	else
-		return NULL;
-
-	sysinfo_set_item_val("kbd", NULL, true);
-	sysinfo_set_item_val("kbd.type", NULL, KBD_SKI);
-
-	return &skiin;
-}
-
-
-void skiout_init(void)
-{
-	ski_init();
-
-	outdev_initialize("skiout", &skiout, &skiout_ops);
-	stdout = &skiout;
-
-	sysinfo_set_item_val("fb", NULL, false);
-}
-
-void ski_kbd_grab(void)
-{
-	kbd_disabled = true;
-}
-
-void ski_kbd_release(void)
-{
-	kbd_disabled = false;
-}
-
-/** @}
- */
Index: kernel/arch/ia64/src/smp/smp.c
===================================================================
--- kernel/arch/ia64/src/smp/smp.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ia64/src/smp/smp.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -34,5 +34,5 @@
 
 #include <arch.h>
-#include <arch/ski/ski.h>
+#include <arch/drivers/ski.h>
 #include <arch/drivers/it.h>
 #include <arch/interrupt.h>
Index: kernel/arch/mips32/Makefile.inc
===================================================================
--- kernel/arch/mips32/Makefile.inc	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/mips32/Makefile.inc	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -61,5 +61,4 @@
 	arch/$(KARCH)/src/panic.S \
 	arch/$(KARCH)/src/mips32.c \
-	arch/$(KARCH)/src/console.c \
 	arch/$(KARCH)/src/asm.S \
 	arch/$(KARCH)/src/exception.c \
Index: kernel/arch/mips32/include/console.h
===================================================================
--- kernel/arch/mips32/include/console.h	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ 	(revision )
@@ -1,41 +1,0 @@
-/*
- * Copyright (c) 2005 Martin Decky
- * 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 mips32	
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_mips32_CONSOLE_H_
-#define KERN_mips32_CONSOLE_H_
-
-#endif
-
-/** @}
- */
Index: kernel/arch/mips32/src/console.c
===================================================================
--- kernel/arch/mips32/src/console.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ 	(revision )
@@ -1,56 +1,0 @@
-/*
- * 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.
- */
-
-/** @addtogroup mips32
- * @{
- */
-/** @file
- */
-
-#include <console/console.h>
-#include <genarch/fb/fb.h>
-
-/** Acquire console back for kernel
- *
- */
-void arch_grab_console(void)
-{
-#ifdef CONFIG_FB
-	fb_redraw();
-#endif
-}
-
-/** Return console to userspace
- *
- */
-void arch_release_console(void)
-{
-}
-
-/** @}
- */
Index: kernel/arch/mips32/src/mips32.c
===================================================================
--- kernel/arch/mips32/src/mips32.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/mips32/src/mips32.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -37,14 +37,12 @@
 #include <arch/exception.h>
 #include <mm/as.h>
-
 #include <userspace.h>
-#include <arch/console.h>
 #include <memstr.h>
 #include <proc/thread.h>
 #include <proc/uarg.h>
 #include <print.h>
+#include <console/console.h>
 #include <syscall/syscall.h>
 #include <sysinfo/sysinfo.h>
-
 #include <arch/interrupt.h>
 #include <console/chardev.h>
@@ -60,5 +58,4 @@
 #include <string.h>
 #include <arch/drivers/msim.h>
-
 #include <arch/asm/regname.h>
 
@@ -170,8 +167,14 @@
 	 * module and connect it to the msim/GXemul keyboard. Enable keyboard interrupts.
 	 */
-	indev_t *kbrdin = dsrlnin_init((dsrlnin_t *) MSIM_KBD_ADDRESS, MSIM_KBD_IRQ);
-	if (kbrdin) {
-		srln_init(kbrdin);
-		cp0_unmask_int(MSIM_KBD_IRQ);
+	dsrlnin_instance_t *dsrlnin_instance
+	    = dsrlnin_init((dsrlnin_t *) MSIM_KBD_ADDRESS, MSIM_KBD_IRQ);
+	if (dsrlnin_instance) {
+		srln_instance_t *srln_instance = srln_init();
+		if (srln_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *srln = srln_wire(srln_instance, sink);
+			dsrlnin_wire(dsrlnin_instance, srln);
+			cp0_unmask_int(MSIM_KBD_IRQ);
+		}
 	}
 	
@@ -249,4 +252,18 @@
 }
 
+void arch_grab_console(void)
+{
+#ifdef CONFIG_FB
+	fb_redraw();
+#endif
+}
+
+/** Return console to userspace
+ *
+ */
+void arch_release_console(void)
+{
+}
+
 /** @}
  */
Index: kernel/arch/ppc32/Makefile.inc
===================================================================
--- kernel/arch/ppc32/Makefile.inc	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ppc32/Makefile.inc	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -55,5 +55,4 @@
 	arch/$(KARCH)/src/proc/scheduler.c \
 	arch/$(KARCH)/src/ddi/ddi.c \
-	arch/$(KARCH)/src/drivers/cuda.c \
 	arch/$(KARCH)/src/mm/as.c \
 	arch/$(KARCH)/src/mm/frame.c \
Index: kernel/arch/ppc32/include/drivers/cuda.h
===================================================================
--- kernel/arch/ppc32/include/drivers/cuda.h	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * 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 ppc32	
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_ppc32_CUDA_H_
-#define KERN_ppc32_CUDA_H_
-
-#include <arch/types.h>
-#include <typedefs.h>
-
-extern void cuda_init(uintptr_t base, size_t size);
-extern int cuda_get_scancode(void);
-
-#endif
-
-/** @}
- */
Index: kernel/arch/ppc32/include/drivers/pic.h
===================================================================
--- kernel/arch/ppc32/include/drivers/pic.h	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ppc32/include/drivers/pic.h	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ppc32	
+/** @addtogroup ppc32
  * @{
  */
@@ -37,4 +37,5 @@
 
 #include <arch/types.h>
+#include <ddi/irq.h>
 
 #define PIC_PENDING_LOW    8
@@ -45,9 +46,9 @@
 #define PIC_ACK_HIGH       6
 
-void pic_init(uintptr_t base, size_t size);
-void pic_enable_interrupt(int intnum);
-void pic_disable_interrupt(int intnum);
-void pic_ack_interrupt(int intnum);
-int pic_get_pending(void);
+extern void pic_init(uintptr_t base, size_t size, cir_t *cir, void **cir_arg);
+extern void pic_enable_interrupt(inr_t intnum);
+extern void pic_disable_interrupt(inr_t intnum);
+extern void pic_ack_interrupt(void *arg, inr_t intnum);
+extern int pic_get_pending(void);
 
 #endif
Index: kernel/arch/ppc32/src/drivers/cuda.c
===================================================================
--- kernel/arch/ppc32/src/drivers/cuda.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ 	(revision )
@@ -1,260 +1,0 @@
-/*
- * Copyright (c) 2006 Martin Decky
- * 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 ppc32
- * @{
- */
-/** @file
- */
-
-#include <arch/drivers/cuda.h>
-#include <arch/asm.h>
-#include <console/console.h>
-#include <console/chardev.h>
-#include <arch/drivers/pic.h>
-#include <sysinfo/sysinfo.h>
-#include <interrupt.h>
-#include <stdarg.h>
-#include <ddi/device.h>
-#include <string.h>
-
-#define CUDA_IRQ 10
-
-#define PACKET_ADB   0x00
-#define PACKET_CUDA  0x01
-
-#define CUDA_POWERDOWN  0x0a
-#define CUDA_RESET      0x11
-
-#define RS   0x200
-#define B    (0 * RS)
-#define A    (1 * RS)
-#define SR   (10 * RS)
-#define ACR  (11 * RS)
-
-#define SR_OUT  0x10
-#define TACK    0x10
-#define TIP     0x20
-
-#define SCANCODES  128
-
-static volatile uint8_t *cuda = NULL;
-static irq_t cuda_irq;                 /**< Cuda's IRQ. */
-
-static wchar_t lchars[SCANCODES] = {
-	'a', 's', 'd', 'f', 'h', 'g', 'z', 'x', 'c', 'v',
-	U_SPECIAL,
-	'b', 'q', 'w', 'e', 'r', 'y', 't', '1', '2', '3', '4', '6', '5',
-	'=', '9', '7', '-', '8', '0', ']', 'o', 'u', '[', 'i', 'p',
-	'\n',           /* Enter */
-	'l', 'j', '\'', 'k', ';', '\\', ',', '/', 'n', 'm', '.',
-	'\t',           /* Tab */
-	' ', '`',
-	'\b',           /* Backspace */
-	U_SPECIAL,
-	U_ESCAPE,       /* Escape */
-	U_SPECIAL,      /* Ctrl */
-	U_SPECIAL,      /* Alt */
-	U_SPECIAL,      /* Shift */
-	U_SPECIAL,      /* CapsLock */
-	U_SPECIAL,      /* Right Alt */
-	U_LEFT_ARROW,   /* Left */
-	U_RIGHT_ARROW,  /* Right */
-	U_DOWN_ARROW,   /* Down */
-	U_UP_ARROW,     /* Up */
-	U_SPECIAL,
-	U_SPECIAL,
-	'.',            /* Keypad . */
-	U_SPECIAL,
-	'*',            /* Keypad * */
-	U_SPECIAL,
-	'+',            /* Keypad + */
-	U_SPECIAL,
-	U_SPECIAL,      /* NumLock */
-	U_SPECIAL,
-	U_SPECIAL,
-	U_SPECIAL,
-	'/',            /* Keypad / */
-	'\n',           /* Keypad Enter */
-	U_SPECIAL,
-	'-',            /* Keypad - */
-	U_SPECIAL,
-	U_SPECIAL,
-	U_SPECIAL,
-	'0',            /* Keypad 0 */
-	'1',            /* Keypad 1 */
-	'2',            /* Keypad 2 */
-	'3',            /* Keypad 3 */
-	'4',            /* Keypad 4 */
-	'5',            /* Keypad 5 */
-	'6',            /* Keypad 6 */
-	'7',            /* Keypad 7 */
-	U_SPECIAL,
-	'8',            /* Keypad 8 */
-	'9',            /* Keypad 9 */
-	U_SPECIAL,
-	U_SPECIAL,
-	U_SPECIAL,
-	U_SPECIAL,      /* F5 */
-	U_SPECIAL,      /* F6 */
-	U_SPECIAL,      /* F7 */
-	U_SPECIAL,      /* F3 */
-	U_SPECIAL,      /* F8 */
-	U_SPECIAL,      /* F9 */
-	U_SPECIAL,
-	U_SPECIAL,      /* F11 */
-	U_SPECIAL,
-	U_SPECIAL,      /* F13 */
-	U_SPECIAL,
-	U_SPECIAL,      /* ScrollLock */
-	U_SPECIAL,
-	U_SPECIAL,      /* F10 */
-	U_SPECIAL,
-	U_SPECIAL,      /* F12 */
-	U_SPECIAL,
-	U_SPECIAL,      /* Pause */
-	U_SPECIAL,      /* Insert */
-	U_HOME_ARROW,   /* Home */
-	U_PAGE_UP,      /* Page Up */
-	U_DELETE,       /* Delete */
-	U_SPECIAL,      /* F4 */
-	U_END_ARROW,    /* End */
-	U_SPECIAL,      /* F2 */
-	U_PAGE_DOWN,    /* Page Down */
-	U_SPECIAL       /* F1 */
-};
-
-static void receive_packet(uint8_t *kind, index_t count, uint8_t data[])
-{
-	cuda[B] = cuda[B] & ~TIP;
-	*kind = cuda[SR];
-	
-	index_t i;
-	for (i = 0; i < count; i++)
-		data[i] = cuda[SR];
-	
-	cuda[B] = cuda[B] | TIP;
-}
-
-static indev_t kbrd;
-static indev_operations_t ops = {
-	.poll = NULL
-};
-
-int cuda_get_scancode(void)
-{
-	if (cuda) {
-		uint8_t kind;
-		uint8_t data[4];
-		
-		receive_packet(&kind, 4, data);
-		
-		if ((kind == PACKET_ADB) && (data[0] == 0x40) && (data[1] == 0x2c))
-			return data[2];
-	}
-	
-	return -1;
-}
-
-static void cuda_irq_handler(irq_t *irq)
-{
-	int scan_code = cuda_get_scancode();
-	
-	if (scan_code != -1) {
-		uint8_t scancode = (uint8_t) scan_code;
-		if ((scancode & 0x80) != 0x80)
-			indev_push_character(&kbrd, lchars[scancode & 0x7f]);
-	}
-}
-
-static irq_ownership_t cuda_claim(irq_t *irq)
-{
-	return IRQ_ACCEPT;
-}
-
-void cuda_init(uintptr_t base, size_t size)
-{
-	cuda = (uint8_t *) hw_map(base, size);
-	
-	indev_initialize("cuda_kbd", &kbrd, &ops);
-	stdin = &kbrd;
-	
-	irq_initialize(&cuda_irq);
-	cuda_irq.devno = device_assign_devno();
-	cuda_irq.inr = CUDA_IRQ;
-	cuda_irq.claim = cuda_claim;
-	cuda_irq.handler = cuda_irq_handler;
-	irq_register(&cuda_irq);
-	
-	pic_enable_interrupt(CUDA_IRQ);
-	
-	sysinfo_set_item_val("kbd", NULL, true);
-	sysinfo_set_item_val("kbd.inr", NULL, CUDA_IRQ);
-	sysinfo_set_item_val("kbd.address.virtual", NULL, base);
-}
-
-static void send_packet(const uint8_t kind, count_t count, ...)
-{
-	index_t i;
-	va_list va;
-	
-	cuda[B] = cuda[B] | TIP;
-	cuda[ACR] = cuda[ACR] | SR_OUT;
-	cuda[SR] = kind;
-	cuda[B] = cuda[B] & ~TIP;
-	
-	va_start(va, count);
-	
-	for (i = 0; i < count; i++) {
-		cuda[ACR] = cuda[ACR] | SR_OUT;
-		cuda[SR] = va_arg(va, int);
-		cuda[B] = cuda[B] | TACK;
-	}
-	
-	va_end(va);
-	
-	cuda[B] = cuda[B] | TIP;
-}
-
-void cpu_halt(void) {
-	asm volatile (
-		"b 0\n"
-	);
-}
-
-void arch_reboot(void) {
-	if (cuda)
-		send_packet(PACKET_CUDA, 1, CUDA_RESET);
-	
-	asm volatile (
-		"b 0\n"
-	);
-}
-
-/** @}
- */
Index: kernel/arch/ppc32/src/drivers/pic.c
===================================================================
--- kernel/arch/ppc32/src/drivers/pic.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ppc32/src/drivers/pic.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup ppc32	
+/** @addtogroup ppc32
  * @{
  */
@@ -41,10 +41,12 @@
 static volatile uint32_t *pic = NULL;
 
-void pic_init(uintptr_t base, size_t size)
+void pic_init(uintptr_t base, size_t size, cir_t *cir, void **cir_arg)
 {
 	pic = (uint32_t *) hw_map(base, size);
+	*cir = pic_ack_interrupt;
+	*cir_arg = NULL;
 }
 
-void pic_enable_interrupt(int intnum)
+void pic_enable_interrupt(inr_t intnum)
 {
 	if (pic) {
@@ -57,5 +59,5 @@
 }
 
-void pic_disable_interrupt(int intnum)
+void pic_disable_interrupt(inr_t intnum)
 {
 	if (pic) {
@@ -67,5 +69,5 @@
 }
 
-void pic_ack_interrupt(int intnum)
+void pic_ack_interrupt(void *arg, inr_t intnum)
 {
 	if (pic) {
Index: kernel/arch/ppc32/src/dummy.s
===================================================================
--- kernel/arch/ppc32/src/dummy.s	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ppc32/src/dummy.s	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -31,4 +31,5 @@
 .global asm_delay_loop
 .global sys_tls_set
+.global cpu_halt
 
 sys_tls_set:
@@ -37,2 +38,5 @@
 asm_delay_loop:
 	blr
+
+cpu_halt:
+	b cpu_halt
Index: kernel/arch/ppc32/src/interrupt.c
===================================================================
--- kernel/arch/ppc32/src/interrupt.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ppc32/src/interrupt.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -61,5 +61,4 @@
 	
 	while ((inum = pic_get_pending()) != -1) {
-		bool ack = false;
 		irq_t *irq = irq_dispatch_and_lock(inum);
 		if (irq) {
@@ -70,9 +69,15 @@
 			if (irq->preack) {
 				/* Acknowledge the interrupt before processing */
-				pic_ack_interrupt(inum);
-				ack = true;
+				if (irq->cir)
+					irq->cir(irq->cir_arg, irq->inr);
 			}
 			
 			irq->handler(irq);
+			
+			if (!irq->preack) {
+				if (irq->cir)
+					irq->cir(irq->cir_arg, irq->inr);
+			}
+			
 			spinlock_unlock(&irq->lock);
 		} else {
@@ -84,7 +89,4 @@
 #endif
 		}
-		
-		if (!ack)
-			pic_ack_interrupt(inum);
 	}
 }
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/ppc32/src/ppc32.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -36,5 +36,5 @@
 #include <arch.h>
 #include <arch/boot/boot.h>
-#include <arch/drivers/cuda.h>
+#include <genarch/drivers/via-cuda/cuda.h>
 #include <arch/interrupt.h>
 #include <genarch/fb/fb.h>
@@ -45,8 +45,10 @@
 #include <ddi/irq.h>
 #include <arch/drivers/pic.h>
+#include <align.h>
 #include <macros.h>
 #include <string.h>
 
 #define IRQ_COUNT  64
+#define IRQ_CUDA   10
 
 bootinfo_t bootinfo;
@@ -118,8 +120,25 @@
 		if (bootinfo.macio.addr) {
 			/* Initialize PIC */
-			pic_init(bootinfo.macio.addr, PAGE_SIZE);
+			cir_t cir;
+			void *cir_arg;
+			pic_init(bootinfo.macio.addr, PAGE_SIZE, &cir, &cir_arg);
+			
+#ifdef CONFIG_VIA_CUDA
+			uintptr_t pa = bootinfo.macio.addr + 0x16000;
+			uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
+			size_t offset = pa - aligned_addr;
+			size_t size = 2 * PAGE_SIZE;
+			
+			cuda_t *cuda = (cuda_t *)
+			    (hw_map(aligned_addr, offset + size) + offset);
 			
 			/* Initialize I/O controller */
-			cuda_init(bootinfo.macio.addr + 0x16000, 2 * PAGE_SIZE);
+			cuda_instance_t *cuda_instance =
+			    cuda_init(cuda, IRQ_CUDA, cir, cir_arg);
+			if (cuda_instance) {
+				indev_t *sink = stdin_wire();
+				cuda_wire(cuda_instance, sink);
+			}
+#endif
 		}
 		
@@ -187,4 +206,10 @@
 }
 
+void arch_reboot(void)
+{
+	// TODO
+	while (1);
+}
+
 /** @}
  */
Index: kernel/arch/sparc64/include/drivers/kbd.h
===================================================================
--- kernel/arch/sparc64/include/drivers/kbd.h	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/sparc64/include/drivers/kbd.h	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup sparc64	
+/** @addtogroup sparc64
  * @{
  */
@@ -39,13 +39,4 @@
 #include <genarch/ofw/ofw_tree.h>
 
-typedef enum {
-	KBD_UNKNOWN,
-	KBD_Z8530,
-	KBD_NS16550,
-	KBD_SGCN
-} kbd_type_t;
-
-extern kbd_type_t kbd_type;
-
 extern void kbd_init(ofw_tree_node_t *node);
 
Index: kernel/arch/sparc64/src/console.c
===================================================================
--- kernel/arch/sparc64/src/console.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/sparc64/src/console.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup sparc64	
+/** @addtogroup sparc64
  * @{
  */
@@ -136,13 +136,7 @@
 #endif
 	
-	switch (kbd_type) {
 #ifdef CONFIG_SGCN_KBD
-	case KBD_SGCN:
-		sgcn_grab();
-		break;
+	sgcn_grab();
 #endif
-	default:
-		break;
-	}
 }
 
@@ -152,13 +146,7 @@
 void arch_release_console(void)
 {
-	switch (kbd_type) {
 #ifdef CONFIG_SGCN_KBD
-	case KBD_SGCN:
-		sgcn_release();
-		break;
+	sgcn_release();
 #endif
-	default:
-		break;
-	}
 }
 
Index: kernel/arch/sparc64/src/drivers/kbd.c
===================================================================
--- kernel/arch/sparc64/src/drivers/kbd.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/sparc64/src/drivers/kbd.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -55,98 +55,52 @@
 #include <sysinfo/sysinfo.h>
 
-kbd_type_t kbd_type = KBD_UNKNOWN;
-
 #ifdef CONFIG_SUN_KBD
 
-/** Initialize keyboard.
- *
- * Traverse OpenFirmware device tree in order to find necessary
- * info about the keyboard device.
- *
- * @param node Keyboard device node.
- */
-void kbd_init(ofw_tree_node_t *node)
+#ifdef CONFIG_Z8530
+
+static bool kbd_z8530_init(ofw_tree_node_t *node)
 {
-	size_t offset;
-	uintptr_t aligned_addr;
-	ofw_tree_property_t *prop;
-	const char *name;
+	const char *name = ofw_tree_node_name(node);
+	
+	if (str_cmp(name, "zs") != 0)
+		return false;
+	
+	/*
+	 * Read 'interrupts' property.
+	 */
+	ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
+	if ((!prop) || (!prop->value)) {
+		printf("z8530: Unable to find interrupts property\n");
+		return false;
+	}
+	
+	uint32_t interrupts = *((uint32_t *) prop->value);
+	
+	/*
+	 * Read 'reg' property.
+	 */
+	prop = ofw_tree_getprop(node, "reg");
+	if ((!prop) || (!prop->value)) {
+		printf("z8530: Unable to find reg property\n");
+		return false;
+	}
+	
+	size_t size = ((ofw_fhc_reg_t *) prop->value)->size;
+	
+	uintptr_t pa;
+	if (!ofw_fhc_apply_ranges(node->parent,
+	    ((ofw_fhc_reg_t *) prop->value), &pa)) {
+		printf("z8530: Failed to determine address\n");
+		return false;
+	}
+	
+	inr_t inr;
 	cir_t cir;
 	void *cir_arg;
-	
-#ifdef CONFIG_NS16550
-	ns16550_t *ns16550;
-#endif
-#ifdef CONFIG_Z8530
-	z8530_t *z8530;
-#endif
-	
-	name = ofw_tree_node_name(node);
-	
-	/*
-	 * Determine keyboard serial controller type.
-	 */
-	if (str_cmp(name, "zs") == 0)
-		kbd_type = KBD_Z8530;
-	else if (str_cmp(name, "su") == 0)
-		kbd_type = KBD_NS16550;
-	
-	if (kbd_type == KBD_UNKNOWN) {
-		printf("Unknown keyboard device.\n");
-		return;
-	}
-	
-	/*
-	 * Read 'interrupts' property.
-	 */
-	uint32_t interrupts;
-	prop = ofw_tree_getprop(node, "interrupts");
-	if ((!prop) || (!prop->value))
-		panic("Cannot find 'interrupt' property.");
-	interrupts = *((uint32_t *) prop->value);
-	
-	/*
-	 * Read 'reg' property.
-	 */
-	prop = ofw_tree_getprop(node, "reg");
-	if ((!prop) || (!prop->value))
-		panic("Cannot find 'reg' property.");
-	
-	uintptr_t pa;
-	size_t size;
-	inr_t inr;
-	
-	switch (kbd_type) {
-	case KBD_Z8530:
-		size = ((ofw_fhc_reg_t *) prop->value)->size;
-		if (!ofw_fhc_apply_ranges(node->parent,
-		    ((ofw_fhc_reg_t *) prop->value), &pa)) {
-			printf("Failed to determine keyboard address.\n");
-			return;
-		}
-		if (!ofw_fhc_map_interrupt(node->parent,
-		    ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
-		    &cir_arg)) {
-			printf("Failed to determine keyboard interrupt.\n");
-			return;
-		}
-		break;
-		
-	case KBD_NS16550:
-		size = ((ofw_ebus_reg_t *) prop->value)->size;
-		if (!ofw_ebus_apply_ranges(node->parent,
-		    ((ofw_ebus_reg_t *) prop->value), &pa)) {
-			printf("Failed to determine keyboard address.\n");
-			return;
-		}
-		if (!ofw_ebus_map_interrupt(node->parent,
-		    ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
-		    &cir_arg)) {
-			printf("Failed to determine keyboard interrupt.\n");
-			return;
-		};
-		break;
-	default:
-		panic("Unexpected keyboard type.");
+	if (!ofw_fhc_map_interrupt(node->parent,
+	    ((ofw_fhc_reg_t *) prop->value), interrupts, &inr, &cir,
+	    &cir_arg)) {
+		printf("z8530: Failed to determine interrupt\n");
+		return false;
 	}
 	
@@ -157,57 +111,142 @@
 	 * underlying controller.
 	 */
-	aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
-	offset = pa - aligned_addr;
-	
-	switch (kbd_type) {
+	uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
+	size_t offset = pa - aligned_addr;
+	
+	z8530_t *z8530 = (z8530_t *)
+	    (hw_map(aligned_addr, offset + size) + offset);
+	
+	z8530_instance_t *z8530_instance = z8530_init(z8530, inr, cir, cir_arg);
+	if (z8530_instance) {
+		kbrd_instance_t *kbrd_instance = kbrd_init();
+		if (kbrd_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
+			z8530_wire(z8530_instance, kbrd);
+		}
+	}
+	
+	/*
+	 * This is the necessary evil until the userspace drivers are
+	 * entirely self-sufficient.
+	 */
+	sysinfo_set_item_val("kbd", NULL, true);
+	sysinfo_set_item_val("kbd.inr", NULL, inr);
+	sysinfo_set_item_val("kbd.address.kernel", NULL,
+	    (uintptr_t) z8530);
+	sysinfo_set_item_val("kbd.address.physical", NULL, pa);
+	sysinfo_set_item_val("kbd.type.z8530", NULL, true);
+	
+	return true;
+}
+
+#endif /* CONFIG_Z8530 */
+
+#ifdef CONFIG_NS16550
+
+static bool kbd_ns16550_init(ofw_tree_node_t *node)
+{
+	const char *name = ofw_tree_node_name(node);
+	
+	if (str_cmp(name, "su") != 0)
+		return false;
+	
+	/*
+	 * Read 'interrupts' property.
+	 */
+	ofw_tree_property_t *prop = ofw_tree_getprop(node, "interrupts");
+	if ((!prop) || (!prop->value)) {
+		printf("ns16550: Unable to find interrupts property\n");
+		return false;
+	}
+	
+	uint32_t interrupts = *((uint32_t *) prop->value);
+	
+	/*
+	 * Read 'reg' property.
+	 */
+	prop = ofw_tree_getprop(node, "reg");
+	if ((!prop) || (!prop->value)) {
+		printf("ns16550: Unable to find reg property\n");
+		return false;
+	}
+	
+	size_t size = ((ofw_ebus_reg_t *) prop->value)->size;
+	
+	uintptr_t pa;
+	if (!ofw_ebus_apply_ranges(node->parent,
+	    ((ofw_ebus_reg_t *) prop->value), &pa)) {
+		printf("ns16550: Failed to determine address\n");
+		return false;
+	}
+	
+	inr_t inr;
+	cir_t cir;
+	void *cir_arg;
+	if (!ofw_ebus_map_interrupt(node->parent,
+	    ((ofw_ebus_reg_t *) prop->value), interrupts, &inr, &cir,
+	    &cir_arg)) {
+		printf("ns16550: Failed to determine interrupt\n");
+		return false;
+	}
+	
+	/*
+	 * We need to pass aligned address to hw_map().
+	 * However, the physical keyboard address can
+	 * be pretty much unaligned, depending on the
+	 * underlying controller.
+	 */
+	uintptr_t aligned_addr = ALIGN_DOWN(pa, PAGE_SIZE);
+	size_t offset = pa - aligned_addr;
+	
+	ns16550_t *ns16550 = (ns16550_t *)
+	   (hw_map(aligned_addr, offset + size) + offset);
+	
+	ns16550_instance_t *ns16550_instance = ns16550_init(ns16550, inr, cir, cir_arg);
+	if (ns16550_instance) {
+		kbrd_instance_t *kbrd_instance = kbrd_init();
+		if (kbrd_instance) {
+			indev_t *sink = stdin_wire();
+			indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
+			ns16550_wire(ns16550_instance, kbrd);
+		}
+	}
+	
+	/*
+	 * This is the necessary evil until the userspace drivers are
+	 * entirely self-sufficient.
+	 */
+	sysinfo_set_item_val("kbd", NULL, true);
+	sysinfo_set_item_val("kbd.inr", NULL, inr);
+	sysinfo_set_item_val("kbd.address.kernel", NULL,
+	    (uintptr_t) ns16550);
+	sysinfo_set_item_val("kbd.address.physical", NULL, pa);
+	sysinfo_set_item_val("kbd.type.ns16550", NULL, true);
+	
+	return true;
+}
+
+#endif /* CONFIG_NS16550 */
+
+/** Initialize keyboard.
+ *
+ * Traverse OpenFirmware device tree in order to find necessary
+ * info about the keyboard device.
+ *
+ * @param node Keyboard device node.
+ *
+ */
+void kbd_init(ofw_tree_node_t *node)
+{
 #ifdef CONFIG_Z8530
-	case KBD_Z8530:
-		z8530 = (z8530_t *)
-		    (hw_map(aligned_addr, offset + size) + offset);
-		
-		indev_t *kbrdin_z8530 = z8530_init(z8530, inr, cir, cir_arg);
-		if (kbrdin_z8530)
-			kbrd_init(kbrdin_z8530);
-		
-		/*
-		 * This is the necessary evil until the userspace drivers are
-		 * entirely self-sufficient.
-		 */
-		sysinfo_set_item_val("kbd", NULL, true);
-		sysinfo_set_item_val("kbd.type", NULL, KBD_Z8530);
-		sysinfo_set_item_val("kbd.inr", NULL, inr);
-		sysinfo_set_item_val("kbd.address.kernel", NULL,
-		    (uintptr_t) z8530);
-		sysinfo_set_item_val("kbd.address.physical", NULL, pa);
-		break;
-#endif
+	kbd_z8530_init(node);
+#endif
+	
 #ifdef CONFIG_NS16550
-	case KBD_NS16550:
-		ns16550 = (ns16550_t *)
-		   (hw_map(aligned_addr, offset + size) + offset);
-		
-		indev_t *kbrdin_ns16550 = ns16550_init(ns16550, inr, cir, cir_arg);
-		if (kbrdin_ns16550)
-			kbrd_init(kbrdin_ns16550);
-		
-		/*
-		 * This is the necessary evil until the userspace driver is
-		 * entirely self-sufficient.
-		 */
-		sysinfo_set_item_val("kbd", NULL, true);
-		sysinfo_set_item_val("kbd.type", NULL, KBD_NS16550);
-		sysinfo_set_item_val("kbd.inr", NULL, inr);
-		sysinfo_set_item_val("kbd.address.kernel", NULL,
-		    (uintptr_t) ns16550);
-		sysinfo_set_item_val("kbd.address.physical", NULL, pa);
-		break;
-#endif
-	default:
-		printf("Kernel is not compiled with the necessary keyboard "
-		    "driver this machine requires.\n");
-	}
+	kbd_ns16550_init(node);
+#endif
 }
 
-#endif
+#endif /* CONFIG_SUN_KBD */
 
 /** @}
Index: kernel/arch/sparc64/src/drivers/sgcn.c
===================================================================
--- kernel/arch/sparc64/src/drivers/sgcn.c	(revision f03afad718ff8655274836534b65e4a5b4f6d098)
+++ kernel/arch/sparc64/src/drivers/sgcn.c	(revision c2417bcc6cc9caba6dca867e322c9cc5723b35f4)
@@ -101,7 +101,4 @@
 /** Returns a pointer to the console buffer header. */
 #define SGCN_BUFFER_HEADER	(SGCN_BUFFER(sgcn_buffer_header_t, 0))
-
-/** defined in drivers/kbd.c */
-extern kbd_type_t kbd_type;
 
 /** starting address of SRAM, will be set by the init_sram_begin function */
@@ -354,8 +351,5 @@
 	sgcn_buffer_begin_init();
 
-	kbd_type = KBD_SGCN;
-
 	sysinfo_set_item_val("kbd", NULL, true);
-	sysinfo_set_item_val("kbd.type", NULL, KBD_SGCN);
 
 	thread_t *t = thread_create(kkbdpoll, NULL, TASK, 0, "kkbdpoll", true);
