From 714e732504021937171665407133851ad9f3e68b Mon Sep 17 00:00:00 2001 From: Minep Date: Sat, 25 Jun 2022 22:52:08 +0100 Subject: [PATCH] feat: a simple console that support scrolling. --- lunaix-os/includes/lunaix/lxconsole.h | 6 ++ lunaix-os/includes/lunaix/tty/console.h | 3 + lunaix-os/kernel/ds/semaphore.c | 2 +- lunaix-os/kernel/lxconsole.c | 74 +++++++++++++++---------- lunaix-os/kernel/lxinit.c | 13 +++-- 5 files changed, 64 insertions(+), 34 deletions(-) diff --git a/lunaix-os/includes/lunaix/lxconsole.h b/lunaix-os/includes/lunaix/lxconsole.h index a264766..06902d0 100644 --- a/lunaix-os/includes/lunaix/lxconsole.h +++ b/lunaix-os/includes/lunaix/lxconsole.h @@ -10,6 +10,12 @@ console_write_str(char* str); void console_write_char(char chr); +void +console_view_up(); + +void +console_view_down(); + void console_start_flushing(); #endif /* __LUNAIX_LXCONSOLE_H */ diff --git a/lunaix-os/includes/lunaix/tty/console.h b/lunaix-os/includes/lunaix/tty/console.h index 5e0ffcc..2c9e990 100644 --- a/lunaix-os/includes/lunaix/tty/console.h +++ b/lunaix-os/includes/lunaix/tty/console.h @@ -8,6 +8,9 @@ struct console { struct lx_timer* flush_timer; struct fifo_buffer buffer; + unsigned int erd_pos; + unsigned int lines; + unsigned int chars; }; #endif /* __LUNAIX_CONSOLE_H */ diff --git a/lunaix-os/kernel/ds/semaphore.c b/lunaix-os/kernel/ds/semaphore.c index ab494d2..84c0100 100644 --- a/lunaix-os/kernel/ds/semaphore.c +++ b/lunaix-os/kernel/ds/semaphore.c @@ -11,7 +11,7 @@ void sem_wait(struct sem_t* sem) { while (!atomic_load(&sem->counter)) { - schedule(); + // FIXME: better thing like wait queue } atomic_fetch_sub(&sem->counter, 1); } diff --git a/lunaix-os/kernel/lxconsole.c b/lunaix-os/kernel/lxconsole.c index 25c4faa..88fd1f4 100644 --- a/lunaix-os/kernel/lxconsole.c +++ b/lunaix-os/kernel/lxconsole.c @@ -39,35 +39,46 @@ console_schedule_flush() } void -console_view_up(struct fifo_buffer* buffer) +console_view_up() { - // mutex_lock(&buffer->lock); - size_t p = buffer->rd_pos - 2; - while (p < buffer->rd_pos && p != buffer->wr_pos && + struct fifo_buffer* buffer = &lx_console.buffer; + mutex_lock(&buffer->lock); + size_t p = lx_console.erd_pos - 2; + while (p < lx_console.erd_pos && p != buffer->wr_pos && ((char*)buffer->data)[p] != '\n') { p--; } p++; - if (p < buffer->rd_pos) { + if (p > lx_console.erd_pos) { p = 0; } - buffer->rd_pos = p; - // mutex_unlock(&buffer->lock); + buffer->flags |= FIFO_DIRTY; + lx_console.erd_pos = p; + mutex_unlock(&buffer->lock); } -void -console_view_down(struct fifo_buffer* buffer) +size_t +__find_next_line(size_t start) { - // mutex_lock(&buffer->lock); - size_t p = buffer->rd_pos; - while (p != buffer->wr_pos && ((char*)buffer->data)[p] != '\n') { - p = (p + 1) % buffer->size; + size_t p = start; + while (p != lx_console.buffer.wr_pos && + ((char*)lx_console.buffer.data)[p] != '\n') { + p = (p + 1) % lx_console.buffer.size; } + return p + 1; +} + +void +console_view_down() +{ + struct fifo_buffer* buffer = &lx_console.buffer; + mutex_lock(&buffer->lock); - buffer->rd_pos = p + 1; - // mutex_unlock(&buffer->lock); + lx_console.erd_pos = __find_next_line(lx_console.erd_pos); + buffer->flags |= FIFO_DIRTY; + mutex_unlock(&buffer->lock); } void @@ -80,18 +91,11 @@ __flush_cb(void* arg) return; } - size_t pos = tty_flush_buffer(lx_console.buffer.data, - lx_console.buffer.rd_pos, - lx_console.buffer.wr_pos, - lx_console.buffer.size); - lx_console.flush_timer = NULL; - if (pos < lx_console.buffer.wr_pos) { - console_view_down(&lx_console.buffer); - } else { - // clear the dirty bit only if we have flush all the data - // that means: read pointer == write pointer - lx_console.buffer.flags &= ~FIFO_DIRTY; - } + tty_flush_buffer(lx_console.buffer.data, + lx_console.erd_pos, + lx_console.buffer.wr_pos, + lx_console.buffer.size); + lx_console.buffer.flags &= ~FIFO_DIRTY; } void @@ -102,15 +106,29 @@ console_write(struct console* console, uint8_t* data, size_t size) uintptr_t ptr = console->buffer.wr_pos; uintptr_t rd_ptr = console->buffer.rd_pos; + char c; + int lines = 0; for (size_t i = 0; i < size; i++) { - buffer[(ptr + i) % console->buffer.size] = data[i]; + c = data[i]; + buffer[(ptr + i) % console->buffer.size] = c; + // chars += (31 < c && c < 127); + lines += (c == '\n'); } uintptr_t new_ptr = (ptr + size) % console->buffer.size; console->buffer.wr_pos = new_ptr; + + if (console->lines > TTY_HEIGHT && lines > 0) { + console->buffer.rd_pos = + __find_next_line((size + rd_ptr) % console->buffer.size); + } + if (new_ptr < ptr + size && new_ptr > rd_ptr) { console->buffer.rd_pos = new_ptr; } + + console->lines += lines; + console->erd_pos = console->buffer.rd_pos; console->buffer.flags |= FIFO_DIRTY; mutex_unlock(&console->buffer.lock); } diff --git a/lunaix-os/kernel/lxinit.c b/lunaix-os/kernel/lxinit.c index a767ec7..5119e4b 100644 --- a/lunaix-os/kernel/lxinit.c +++ b/lunaix-os/kernel/lxinit.c @@ -97,11 +97,14 @@ _lxinit_main() yield(); continue; } - if ((keyevent.state & KBD_KEY_FPRESSED) && - (keyevent.keycode & 0xff00) <= KEYPAD) { - console_write_char((char)(keyevent.keycode & 0x00ff)); - // FIXME: io to vga port is privileged and cause #GP in user mode - // tty_sync_cursor(); + if ((keyevent.state & KBD_KEY_FPRESSED)) { + if ((keyevent.keycode & 0xff00) <= KEYPAD) { + console_write_char((char)(keyevent.keycode & 0x00ff)); + } else if (keyevent.keycode == KEY_UP) { + console_view_up(); + } else if (keyevent.keycode == KEY_DOWN) { + console_view_down(); + } } } spin(); -- 2.27.0