Index: kernel/genarch/src/drivers/dsrln/dsrlnout.c
===================================================================
--- kernel/genarch/src/drivers/dsrln/dsrlnout.c	(revision b9c742533861d30ff1a3f7a0986e6b524800644d)
+++ kernel/genarch/src/drivers/dsrln/dsrlnout.c	(revision 21d8020c2d212caa3f64025e5c2bb519e3ee2e4b)
@@ -35,40 +35,63 @@
  */
 
-
 #include <genarch/drivers/dsrln/dsrlnout.h>
 #include <console/chardev.h>
 #include <arch/asm.h>
+#include <mm/slab.h>
 #include <console/console.h>
 #include <sysinfo/sysinfo.h>
 #include <string.h>
 
-static ioport8_t *dsrlnout_base;
+typedef struct {
+	ioport8_t *base;
+} dsrlnout_instance_t;
 
-static void dsrlnout_putchar(outdev_t *dev __attribute__((unused)), const wchar_t ch, bool silent)
+static void dsrlnout_putchar(outdev_t *dev, const wchar_t ch, bool silent)
 {
+	dsrlnout_instance_t *instance = (dsrlnout_instance_t *) dev->data;
+	
 	if (!silent) {
 		if (ascii_check(ch))
-			pio_write_8(dsrlnout_base, ch);
+			pio_write_8(instance->base, ch);
 		else
-			pio_write_8(dsrlnout_base, U_SPECIAL);
+			pio_write_8(instance->base, U_SPECIAL);
 	}
 }
 
-static outdev_t dsrlnout_console;
-static outdev_operations_t dsrlnout_ops = {
-	.write = dsrlnout_putchar
+static outdev_operations_t dsrlndev_ops = {
+	.write = dsrlnout_putchar,
+	.redraw = NULL
 };
 
-void dsrlnout_init(ioport8_t *base)
+outdev_t *dsrlnout_init(ioport8_t *base)
 {
-	/* Initialize the software structure. */
-	dsrlnout_base = base;
+	outdev_t *dsrlndev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
+	if (!dsrlndev)
+		return NULL;
 	
-	outdev_initialize("dsrlnout", &dsrlnout_console, &dsrlnout_ops);
-	stdout_wire(&dsrlnout_console);
+	dsrlnout_instance_t *instance = malloc(sizeof(dsrlnout_instance_t), FRAME_ATOMIC);
+	if (!instance) {
+		free(dsrlndev);
+		return NULL;
+	}
 	
-	sysinfo_set_item_val("fb", NULL, true);
-	sysinfo_set_item_val("fb.kind", NULL, 3);
-	sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(base));
+	outdev_initialize("dsrlndev", dsrlndev, &dsrlndev_ops);
+	dsrlndev->data = instance;
+	
+	instance->base = base;
+	
+	if (!fb_exported) {
+		/*
+		 * This is the necessary evil until the userspace driver is entirely
+		 * self-sufficient.
+		 */
+		sysinfo_set_item_val("fb", NULL, true);
+		sysinfo_set_item_val("fb.kind", NULL, 3);
+		sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(base));
+		
+		fb_exported = true;
+	}
+	
+	return dsrlndev;
 }
 
Index: kernel/genarch/src/drivers/ega/ega.c
===================================================================
--- kernel/genarch/src/drivers/ega/ega.c	(revision b9c742533861d30ff1a3f7a0986e6b524800644d)
+++ kernel/genarch/src/drivers/ega/ega.c	(revision 21d8020c2d212caa3f64025e5c2bb519e3ee2e4b)
@@ -56,10 +56,4 @@
  */
 
-SPINLOCK_INITIALIZE(egalock);
-static uint32_t ega_cursor;
-static uint8_t *videoram;
-static uint8_t *backbuf;
-static ioport8_t *ega_base;
-
 #define SPACE  0x20
 #define STYLE  0x1e
@@ -68,4 +62,21 @@
 #define EMPTY_CHAR  ((STYLE << 8) | SPACE)
 
+typedef struct {
+	SPINLOCK_DECLARE(lock);
+	
+	uint32_t cursor;
+	uint8_t *addr;
+	uint8_t *backbuf;
+	ioport8_t *base;
+} ega_instance_t;
+
+static void ega_putchar(outdev_t *dev, wchar_t ch, bool silent);
+static void ega_redraw(outdev_t *dev);
+
+static outdev_operations_t egadev_ops = {
+	.write = ega_putchar,
+	.redraw = ega_redraw
+};
+
 static uint16_t ega_oem_glyph(const wchar_t ch)
 {
@@ -427,71 +438,80 @@
  * This function takes care of scrolling.
  */
-static void ega_check_cursor(bool silent)
-{
-	if (ega_cursor < EGA_SCREEN)
+static void ega_check_cursor(ega_instance_t *instance, bool silent)
+{
+	if (instance->cursor < EGA_SCREEN)
 		return;
 	
-	memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
+	memmove((void *) instance->backbuf,
+	    (void *) (instance->backbuf + EGA_COLS * 2),
 	    (EGA_SCREEN - EGA_COLS) * 2);
-	memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
+	memsetw(instance->backbuf + (EGA_SCREEN - EGA_COLS) * 2,
+	    EGA_COLS, EMPTY_CHAR);
 	
 	if (!silent) {
-		memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
+		memmove((void *) instance->addr,
+		    (void *) (instance->addr + EGA_COLS * 2),
 		    (EGA_SCREEN - EGA_COLS) * 2);
-		memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
-	}
-	
-	ega_cursor = ega_cursor - EGA_COLS;
-}
-
-static void ega_show_cursor(bool silent)
+		memsetw(instance->addr + (EGA_SCREEN - EGA_COLS) * 2,
+		    EGA_COLS, EMPTY_CHAR);
+	}
+	
+	instance->cursor = instance->cursor - EGA_COLS;
+}
+
+static void ega_show_cursor(ega_instance_t *instance, bool silent)
 {
 	if (!silent) {
-		pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
-		uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
-		pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
-		pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
-	}
-}
-
-static void ega_move_cursor(bool silent)
+		pio_write_8(instance->base + EGA_INDEX_REG, 0x0a);
+		uint8_t stat = pio_read_8(instance->base + EGA_DATA_REG);
+		pio_write_8(instance->base + EGA_INDEX_REG, 0x0a);
+		pio_write_8(instance->base + EGA_DATA_REG, stat & (~(1 << 5)));
+	}
+}
+
+static void ega_move_cursor(ega_instance_t *instance, bool silent)
 {
 	if (!silent) {
-		pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
-		pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
-		pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
-		pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
-	}
-}
-
-static void ega_sync_cursor(bool silent)
+		pio_write_8(instance->base + EGA_INDEX_REG, 0x0e);
+		pio_write_8(instance->base + EGA_DATA_REG,
+		    (uint8_t) ((instance->cursor >> 8) & 0xff));
+		pio_write_8(instance->base + EGA_INDEX_REG, 0x0f);
+		pio_write_8(instance->base + EGA_DATA_REG,
+		    (uint8_t) (instance->cursor & 0xff));
+	}
+}
+
+static void ega_sync_cursor(ega_instance_t *instance, bool silent)
 {
 	if (!silent) {
-		pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
-		uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
-		pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
-		uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
+		pio_write_8(instance->base + EGA_INDEX_REG, 0x0e);
+		uint8_t hi = pio_read_8(instance->base + EGA_DATA_REG);
+		pio_write_8(instance->base + EGA_INDEX_REG, 0x0f);
+		uint8_t lo = pio_read_8(instance->base + EGA_DATA_REG);
 		
-		ega_cursor = (hi << 8) | lo;
+		instance->cursor = (hi << 8) | lo;
 	} else
-		ega_cursor = 0;
-	
-	if (ega_cursor >= EGA_SCREEN)
-		ega_cursor = 0;
-	
-	if ((ega_cursor % EGA_COLS) != 0)
-		ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
-	
-	memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
+		instance->cursor = 0;
+	
+	if (instance->cursor >= EGA_SCREEN)
+		instance->cursor = 0;
+	
+	if ((instance->cursor % EGA_COLS) != 0)
+		instance->cursor =
+		    (instance->cursor + EGA_COLS) - instance->cursor % EGA_COLS;
+	
+	memsetw(instance->backbuf + instance->cursor * 2,
+	    EGA_SCREEN - instance->cursor, EMPTY_CHAR);
 	
 	if (!silent)
-		memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
-	
-	ega_check_cursor(silent);
-	ega_move_cursor(silent);
-	ega_show_cursor(silent);
-}
-
-static void ega_display_char(wchar_t ch, bool silent)
+		memsetw(instance->addr + instance->cursor * 2,
+		    EGA_SCREEN - instance->cursor, EMPTY_CHAR);
+	
+	ega_check_cursor(instance, silent);
+	ega_move_cursor(instance, silent);
+	ega_show_cursor(instance, silent);
+}
+
+static void ega_display_char(ega_instance_t *instance, wchar_t ch, bool silent)
 {
 	uint16_t index = ega_oem_glyph(ch);
@@ -507,79 +527,114 @@
 	}
 	
-	backbuf[ega_cursor * 2] = glyph;
-	backbuf[ega_cursor * 2 + 1] = style;
+	instance->backbuf[instance->cursor * 2] = glyph;
+	instance->backbuf[instance->cursor * 2 + 1] = style;
 	
 	if (!silent) {
-		videoram[ega_cursor * 2] = glyph;
-		videoram[ega_cursor * 2 + 1] = style;
-	}
-}
-
-static void ega_putchar(outdev_t *dev __attribute__((unused)), wchar_t ch, bool silent)
-{
-	ipl_t ipl;
-	
-	ipl = interrupts_disable();
-	spinlock_lock(&egalock);
+		instance->addr[instance->cursor * 2] = glyph;
+		instance->addr[instance->cursor * 2 + 1] = style;
+	}
+}
+
+static void ega_putchar(outdev_t *dev, wchar_t ch, bool silent)
+{
+	ega_instance_t *instance = (ega_instance_t *) dev->data;
+	
+	ipl_t ipl = interrupts_disable();
+	spinlock_lock(&instance->lock);
 	
 	switch (ch) {
 	case '\n':
-		ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
+		instance->cursor = (instance->cursor + EGA_COLS)
+		    - instance->cursor % EGA_COLS;
 		break;
 	case '\t':
-		ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
+		instance->cursor = (instance->cursor + 8)
+		    - instance->cursor % 8;
 		break;
 	case '\b':
-		if (ega_cursor % EGA_COLS)
-			ega_cursor--;
+		if (instance->cursor % EGA_COLS)
+			instance->cursor--;
 		break;
 	default:
-		ega_display_char(ch, silent);
-		ega_cursor++;
+		ega_display_char(instance, ch, silent);
+		instance->cursor++;
 		break;
 	}
-	ega_check_cursor(silent);
-	ega_move_cursor(silent);
-	
-	spinlock_unlock(&egalock);
+	ega_check_cursor(instance, silent);
+	ega_move_cursor(instance, silent);
+	
+	spinlock_unlock(&instance->lock);
 	interrupts_restore(ipl);
 }
 
-static outdev_t ega_console;
-static outdev_operations_t ega_ops = {
-	.write = ega_putchar
-};
-
-void ega_init(ioport8_t *base, uintptr_t videoram_phys)
-{
-	/* Initialize the software structure. */
-	ega_base = base;
-	
-	backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
-	if (!backbuf)
-		panic("Unable to allocate backbuffer.");
-	
-	videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
+static void ega_redraw(outdev_t *dev)
+{
+	ega_instance_t *instance = (ega_instance_t *) dev->data;
+	
+	ipl_t ipl = interrupts_disable();
+	spinlock_lock(&instance->lock);
+	
+	memcpy(instance->addr, instance->backbuf, EGA_VRAM_SIZE);
+	ega_move_cursor(instance, silent);
+	ega_show_cursor(instance, silent);
+	
+	spinlock_unlock(&instance->lock);
+	interrupts_restore(ipl);
+}
+
+outdev_t *ega_init(ioport8_t *base, uintptr_t addr)
+{
+	outdev_t *egadev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
+	if (!egadev)
+		return NULL;
+	
+	ega_instance_t *instance = malloc(sizeof(ega_instance_t), FRAME_ATOMIC);
+	if (!instance) {
+		free(egadev);
+		return NULL;
+	}
+	
+	outdev_initialize("egadev", egadev, &egadev_ops);
+	egadev->data = instance;
+	
+	spinlock_initialize(&instance->lock, "*ega_lock");
+	
+	instance->base = base;
+	instance->addr = (uint8_t *) hw_map(addr, EGA_VRAM_SIZE);
+	if (!instance->addr) {
+		LOG("Unable to EGA video memory.");
+		free(instance);
+		free(egadev);
+		return NULL;
+	}
+	
+	instance->backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
+	if (!instance->backbuf) {
+		LOG("Unable to allocate backbuffer.");
+		free(instance);
+		free(egadev);
+		return NULL;
+	}
 	
 	/* Synchronize the back buffer and cursor position. */
-	memcpy(backbuf, videoram, EGA_VRAM_SIZE);
-	ega_sync_cursor(silent);
-	
-	outdev_initialize("ega", &ega_console, &ega_ops);
-	stdout_wire(&ega_console);
-	
-	sysinfo_set_item_val("fb", NULL, true);
-	sysinfo_set_item_val("fb.kind", NULL, 2);
-	sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
-	sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
-	sysinfo_set_item_val("fb.blinking", NULL, true);
-	sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
-}
-
-void ega_redraw(void)
-{
-	memcpy(videoram, backbuf, EGA_VRAM_SIZE);
-	ega_move_cursor(silent);
-	ega_show_cursor(silent);
+	memcpy(instance->backbuf, instance->addr, EGA_VRAM_SIZE);
+	ega_sync_cursor(instance, silent);
+	
+	if (!fb_exported) {
+		/*
+		 * This is the necessary evil until the userspace driver is entirely
+		 * self-sufficient.
+		 */
+		sysinfo_set_item_val("fb", NULL, true);
+		sysinfo_set_item_val("fb.kind", NULL, 2);
+		sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
+		sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
+		sysinfo_set_item_val("fb.blinking", NULL, true);
+		sysinfo_set_item_val("fb.address.physical", NULL, addr);
+		
+		fb_exported = true;
+	}
+	
+	return egadev;
 }
 
