summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2017-05-28 16:32:01 +0200
committerRichard Braun <rbraun@sceen.net>2017-05-28 17:11:32 +0200
commita72801f115413cd3eab46857545ab527f31abb2b (patch)
tree5d475ef0717a2e77fbf1a9d60e2586068d9a9ee7
parent7fba7f7b2fe1106e442cf4150c1e6f7ffa4492a3 (diff)
kern/console: implement console selection
-rw-r--r--arch/x86/machine/cga.c2
-rw-r--r--arch/x86/machine/uart.c14
-rw-r--r--kern/console.c61
-rw-r--r--kern/console.h19
4 files changed, 73 insertions, 23 deletions
diff --git a/arch/x86/machine/cga.c b/arch/x86/machine/cga.c
index 86a661cb..3b217ca1 100644
--- a/arch/x86/machine/cga.c
+++ b/arch/x86/machine/cga.c
@@ -191,6 +191,6 @@ cga_setup(void)
cga_cursor = cga_get_cursor_position();
- console_init(&cga_console, cga_console_putc);
+ console_init(&cga_console, "cga", cga_console_putc);
console_register(&cga_console);
}
diff --git a/arch/x86/machine/uart.c b/arch/x86/machine/uart.c
index 86ef1e3a..f17bc66e 100644
--- a/arch/x86/machine/uart.c
+++ b/arch/x86/machine/uart.c
@@ -67,6 +67,16 @@ static struct uart uart_devs[UART_MAX_DEVS];
static uint16_t uart_intrs[UART_MAX_DEVS] = { 4, 3, 4, 3 };
+static size_t
+uart_get_id(const struct uart *uart)
+{
+ size_t id;
+
+ id = uart - uart_devs;
+ assert(id < ARRAY_SIZE(uart_devs));
+ return id;
+}
+
static uint16_t
uart_get_addr(const struct uart *uart, uint16_t reg)
{
@@ -163,6 +173,7 @@ uart_console_putc(struct console *console, char c)
static void __init
uart_init(struct uart *uart, uint16_t port, uint16_t intr)
{
+ char name[CONSOLE_NAME_SIZE];
uint8_t byte;
uart->port = port;
@@ -179,7 +190,8 @@ uart_init(struct uart *uart, uint16_t port, uint16_t intr)
byte = UART_LCR_8BITS | UART_LCR_NP | UART_LCR_1S | UART_LCR_BEN;
uart_write(uart, UART_REG_LCR, byte);
- console_init(&uart->console, uart_console_putc);
+ snprintf(name, sizeof(name), "uart%zu", uart_get_id(uart));
+ console_init(&uart->console, name, uart_console_putc);
console_register(&uart->console);
}
diff --git a/kern/console.c b/kern/console.c
index 138a4248..eb1306f8 100644
--- a/kern/console.c
+++ b/kern/console.c
@@ -15,16 +15,48 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdbool.h>
#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <kern/arg.h>
#include <kern/assert.h>
#include <kern/init.h>
#include <kern/console.h>
#include <kern/list.h>
#include <kern/spinlock.h>
+/*
+ * Registered consoles.
+ */
static struct list console_devs;
-static struct spinlock console_lock;
+
+/*
+ * Active console device.
+ */
+static struct console *console_dev;
+
+static const char *console_name __initdata;
+
+static bool __init
+console_name_match(const char *name)
+{
+ if (console_name == NULL) {
+ return true;
+ }
+
+ return (strcmp(console_name, name) == 0);
+}
+
+void __init
+console_init(struct console *console, const char *name,
+ console_putc_fn putc)
+{
+ spinlock_init(&console->lock);
+ console->putc = putc;
+ strlcpy(console->name, name, sizeof(console->name));
+}
static void
console_putc(struct console *console, char c)
@@ -40,30 +72,31 @@ void __init
console_setup(void)
{
list_init(&console_devs);
- spinlock_init(&console_lock);
+ console_name = arg_value("console");
}
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);
+
+ if ((console_dev == NULL) && console_name_match(console->name)) {
+ console_dev = console;
+ }
+
+ printf("console: %s registered\n", console->name);
+
+ if (console == console_dev) {
+ printf("console: %s selected as active console\n", console->name);
+ }
}
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);
+ if (console_dev == NULL) {
+ return;
}
- spinlock_unlock_intr_restore(&console_lock, flags);
+ console_putc(console_dev, c);
}
diff --git a/kern/console.h b/kern/console.h
index 8fdef160..3087b711 100644
--- a/kern/console.h
+++ b/kern/console.h
@@ -31,25 +31,27 @@ struct console;
*/
typedef void (*console_putc_fn)(struct console *console, char c);
+#define CONSOLE_NAME_SIZE 16
+
/*
* 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.
+ * for each device. Interrupts are disabled when calling operations.
*/
struct console {
struct spinlock lock;
struct list node;
console_putc_fn putc;
+ char name[CONSOLE_NAME_SIZE];
};
-static inline void
-console_init(struct console *console, console_putc_fn putc)
-{
- spinlock_init(&console->lock);
- console->putc = putc;
-}
+/*
+ * Console initialization.
+ */
+void console_init(struct console *console, const char *name,
+ console_putc_fn putc);
/*
* Initialize the console module.
@@ -60,6 +62,9 @@ void console_setup(void);
* Register a console device.
*
* The given console must be initialized before calling this function.
+ *
+ * This function isn't thread-safe and can only be called during system
+ * initialization.
*/
void console_register(struct console *console);