summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefrag.am2
-rw-r--r--arch/x86/machine/boot.c2
-rw-r--r--arch/x86/machine/cga.c83
-rw-r--r--arch/x86/machine/cga.h7
-rw-r--r--kern/console.c69
-rw-r--r--kern/console.h71
-rw-r--r--kern/printf.c8
7 files changed, 193 insertions, 49 deletions
diff --git a/Makefrag.am b/Makefrag.am
index 55bf93b5..8a7b8e98 100644
--- a/Makefrag.am
+++ b/Makefrag.am
@@ -18,6 +18,8 @@ x15_SOURCES += \
kern/condition.c \
kern/condition.h \
kern/condition_types.h \
+ kern/console.c \
+ kern/console.h \
kern/config.h \
kern/cpumap.c \
kern/cpumap.h \
diff --git a/arch/x86/machine/boot.c b/arch/x86/machine/boot.c
index 09ed36eb..28ed46e7 100644
--- a/arch/x86/machine/boot.c
+++ b/arch/x86/machine/boot.c
@@ -49,6 +49,7 @@
#include <string.h>
#include <kern/arg.h>
+#include <kern/console.h>
#include <kern/init.h>
#include <kern/kmem.h>
#include <kern/kernel.h>
@@ -464,6 +465,7 @@ boot_main(void)
pit_setup_free_running();
cpu_setup();
thread_bootstrap();
+ console_setup();
cga_setup();
printf_setup();
boot_show_version();
diff --git a/arch/x86/machine/cga.c b/arch/x86/machine/cga.c
index c926ec3d..86a661cb 100644
--- a/arch/x86/machine/cga.c
+++ b/arch/x86/machine/cga.c
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <string.h>
+#include <kern/console.h>
#include <kern/init.h>
#include <kern/macros.h>
#include <kern/param.h>
@@ -69,6 +70,8 @@
static uint8_t *cga_memory __read_mostly;
static uint16_t cga_cursor;
+static struct console cga_console;
+
static uint16_t
cga_get_cursor_position(void)
{
@@ -101,33 +104,6 @@ cga_get_cursor_column(void)
return cga_cursor % CGA_COLUMNS;
}
-void __init
-cga_setup(void)
-{
- uint8_t misc_output_register;
-
- cga_memory = (void *)vm_page_direct_va(CGA_MEMORY);
-
- /*
- * Check if the Input/Output Address Select bit is set.
- */
- misc_output_register = io_read_byte(CGA_MISC_OUTPUT_REGISTER_READ);
-
- if (!(misc_output_register & 0x1)) {
- /*
- * Set the I/O AS bit.
- */
- misc_output_register |= 0x1;
-
- /*
- * Update the misc output register.
- */
- io_write_byte(CGA_MISC_OUTPUT_REGISTER_WRITE, misc_output_register);
- }
-
- cga_cursor = cga_get_cursor_position();
-}
-
static void
cga_scroll_lines(void)
{
@@ -143,12 +119,12 @@ cga_scroll_lines(void)
}
}
-void
-cga_write_byte(uint8_t byte)
+static void
+cga_write_char(char c)
{
- if (byte == '\r') {
+ if (c == '\r') {
return;
- } else if (byte == '\n') {
+ } else if (c == '\n') {
cga_cursor += CGA_COLUMNS - cga_get_cursor_column();
if (cga_cursor >= (CGA_LINES * CGA_COLUMNS)) {
@@ -157,17 +133,17 @@ cga_write_byte(uint8_t byte)
}
cga_set_cursor_position(cga_cursor);
- } else if (byte == '\b') {
+ } else if (c == '\b') {
if (cga_cursor > 0) {
cga_cursor--;
((uint16_t *)cga_memory)[cga_cursor] = CGA_BLANK;
cga_set_cursor_position(cga_cursor);
}
- } else if (byte == '\t') {
+ } else if (c == '\t') {
int i;
for(i = 0; i < CGA_TABULATION_SPACES; i++) {
- cga_write_byte(' ');
+ cga_write_char(' ');
}
} else {
if ((cga_cursor + 1) >= CGA_COLUMNS * CGA_LINES) {
@@ -176,10 +152,45 @@ cga_write_byte(uint8_t byte)
}
((uint16_t *)cga_memory)[cga_cursor] = ((CGA_FOREGROUND_COLOR << 8)
- | byte);
+ | c);
cga_cursor++;
cga_set_cursor_position(cga_cursor);
}
}
-void console_write_byte(char c) __alias("cga_write_byte");
+static void
+cga_console_putc(struct console *console, char c)
+{
+ (void)console;
+ cga_write_char(c);
+}
+
+void __init
+cga_setup(void)
+{
+ uint8_t misc_output_register;
+
+ cga_memory = (void *)vm_page_direct_va(CGA_MEMORY);
+
+ /*
+ * Check if the Input/Output Address Select bit is set.
+ */
+ misc_output_register = io_read_byte(CGA_MISC_OUTPUT_REGISTER_READ);
+
+ if (!(misc_output_register & 0x1)) {
+ /*
+ * Set the I/O AS bit.
+ */
+ misc_output_register |= 0x1;
+
+ /*
+ * Update the misc output register.
+ */
+ io_write_byte(CGA_MISC_OUTPUT_REGISTER_WRITE, misc_output_register);
+ }
+
+ cga_cursor = cga_get_cursor_position();
+
+ console_init(&cga_console, cga_console_putc);
+ console_register(&cga_console);
+}
diff --git a/arch/x86/machine/cga.h b/arch/x86/machine/cga.h
index 2dc12cf4..a6771621 100644
--- a/arch/x86/machine/cga.h
+++ b/arch/x86/machine/cga.h
@@ -21,16 +21,9 @@
#ifndef _X86_CGA_H
#define _X86_CGA_H
-#include <stdint.h>
-
/*
* Initialize the cga module.
*/
void cga_setup(void);
-/*
- * Write a byte on the screen at current cursor position.
- */
-void cga_write_byte(uint8_t byte);
-
#endif /* _X86_CGA_H */
diff --git a/kern/console.c b/kern/console.c
new file mode 100644
index 00000000..138a4248
--- /dev/null
+++ b/kern/console.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Richard Braun.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stddef.h>
+
+#include <kern/assert.h>
+#include <kern/init.h>
+#include <kern/console.h>
+#include <kern/list.h>
+#include <kern/spinlock.h>
+
+static struct list console_devs;
+static struct spinlock console_lock;
+
+static void
+console_putc(struct console *console, char c)
+{
+ unsigned long flags;
+
+ spinlock_lock_intr_save(&console->lock, &flags);
+ console->putc(console, c);
+ spinlock_unlock_intr_restore(&console->lock, flags);
+}
+
+void __init
+console_setup(void)
+{
+ list_init(&console_devs);
+ spinlock_init(&console_lock);
+}
+
+void __init
+console_register(struct console *console)
+{
+ assert(console->putc != NULL);
+
+ spinlock_lock(&console_lock);
+ list_insert_tail(&console_devs, &console->node);
+ spinlock_unlock(&console_lock);
+}
+
+void
+console_write_char(char c)
+{
+ struct console *console;
+ unsigned long flags;
+
+ spinlock_lock_intr_save(&console_lock, &flags);
+
+ list_for_each_entry(&console_devs, console, node) {
+ console_putc(console, c);
+ }
+
+ spinlock_unlock_intr_restore(&console_lock, flags);
+}
diff --git a/kern/console.h b/kern/console.h
new file mode 100644
index 00000000..8fdef160
--- /dev/null
+++ b/kern/console.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017 Richard Braun.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Device-independent console interface.
+ */
+
+#ifndef _KERN_CONSOLE_H
+#define _KERN_CONSOLE_H
+
+#include <kern/list.h>
+#include <kern/spinlock.h>
+
+struct console;
+
+/*
+ * Type for character writing functions.
+ */
+typedef void (*console_putc_fn)(struct console *console, char c);
+
+/*
+ * Console device.
+ *
+ * This structure should be embedded in the hardware-specific console
+ * objects. Calls to console operations are all serialized by this module
+ * for each device.
+ */
+struct console {
+ struct spinlock lock;
+ struct list node;
+ console_putc_fn putc;
+};
+
+static inline void
+console_init(struct console *console, console_putc_fn putc)
+{
+ spinlock_init(&console->lock);
+ console->putc = putc;
+}
+
+/*
+ * Initialize the console module.
+ */
+void console_setup(void);
+
+/*
+ * Register a console device.
+ *
+ * The given console must be initialized before calling this function.
+ */
+void console_register(struct console *console);
+
+/*
+ * Write a single character to all registered console devices.
+ */
+void console_write_char(char c);
+
+#endif /* _KERN_CONSOLE_H */
diff --git a/kern/printf.c b/kern/printf.c
index 68ae1037..d7a1d100 100644
--- a/kern/printf.c
+++ b/kern/printf.c
@@ -17,6 +17,7 @@
#include <stdio.h>
+#include <kern/console.h>
#include <kern/spinlock.h>
#include <machine/cpu.h>
@@ -25,11 +26,6 @@
*/
#define PRINTF_BUFSIZE 1024
-/*
- * XXX Must be provided by a console driver.
- */
-extern void console_write_byte(char c);
-
static char printf_buffer[PRINTF_BUFSIZE];
static struct spinlock printf_lock;
@@ -58,7 +54,7 @@ vprintf(const char *format, va_list ap)
length = vsnprintf(printf_buffer, sizeof(printf_buffer), format, ap);
for (ptr = printf_buffer; *ptr != '\0'; ptr++) {
- console_write_byte(*ptr);
+ console_write_char(*ptr);
}
spinlock_unlock_intr_restore(&printf_lock, flags);