diff options
author | Richard Braun <rbraun@sceen.net> | 2017-05-28 16:32:01 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2017-05-28 17:11:32 +0200 |
commit | a72801f115413cd3eab46857545ab527f31abb2b (patch) | |
tree | 5d475ef0717a2e77fbf1a9d60e2586068d9a9ee7 | |
parent | 7fba7f7b2fe1106e442cf4150c1e6f7ffa4492a3 (diff) |
kern/console: implement console selection
-rw-r--r-- | arch/x86/machine/cga.c | 2 | ||||
-rw-r--r-- | arch/x86/machine/uart.c | 14 | ||||
-rw-r--r-- | kern/console.c | 61 | ||||
-rw-r--r-- | kern/console.h | 19 |
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); |