diff options
author | Ian Moffett <ian@osmora.org> | 2024-02-25 22:28:09 -0500 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-02-25 22:30:15 -0500 |
commit | d4372855f00cb47ccfa60db79c5ee35c17f96707 (patch) | |
tree | 6efffc5617fc4c66a38d2e41a7990ddd7534c922 /sys/kern/tty.c | |
parent | 752ae0d0c23d1edf9b2ce563c4e82283dffd273a (diff) |
kernel: Move video console code
This commit introduces a video console driver to Hyra and replaces
that weird tty.c file used only for video console logic
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r-- | sys/kern/tty.c | 382 |
1 files changed, 0 insertions, 382 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c deleted file mode 100644 index 3a959a9..0000000 --- a/sys/kern/tty.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Hyra nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/tty.h> -#include <sys/cdefs.h> -#include <sys/errno.h> -#include <sys/ascii.h> -#include <string.h> -#include <tty_font.h> - -/* - * Default cursor color. - * - * TODO: The cursor color should - * be the invert of the color - * of whatever it is on top of. - */ -#define DEFAULT_CURSOR_BG 0x808080 - -#define CURSOR_WIDTH FONT_WIDTH -#define CURSOR_HEIGHT FONT_HEIGHT - -__KERNEL_META("$Hyra$: tty.c, Ian Marco Moffett, " - "Core TTY implementation"); - -/* List of attached TTYs */ -static TAILQ_HEAD(, tty) tty_list; - -/* - * Renders a char onto the TTY specified by `tty`. - */ -static void -tty_draw_char(struct tty *tty, char c, uint32_t fg, uint32_t bg) -{ - uint32_t *fb_ptr; - uint32_t x, y; - size_t idx; - const uint8_t *glyph; - - /* Get a pointer to framebuffer memory */ - fb_ptr = tty->fbdev.mem; - - /* Get the specific glyph of `c` */ - glyph = &DEFAULT_FONT_DATA[(int)c*16]; - - x = tty->chpos_x; - y = tty->chpos_y; - - for (uint32_t cy = 0; cy < FONT_HEIGHT; ++cy) { - for (uint32_t cx = 0; cx < FONT_WIDTH; ++cx) { - idx = fbdev_get_index(&tty->fbdev, x+FONT_WIDTH-cx, y+cy); - fb_ptr[idx] = __TEST(glyph[cy], __BIT(cx)) ? fg : bg; - } - } -} - -/* - * Draws a cursor onto the screen. - * - * Call with TTY locked. - */ -static void -tty_draw_cursor(struct tty *tty, bool hide) -{ - uint32_t x, y, idx; - uint32_t *fb_ptr; - uint32_t color; - - fb_ptr = tty->fbdev.mem; - color = hide ? tty->bg : DEFAULT_CURSOR_BG; - - for (size_t cy = 0; cy < CURSOR_HEIGHT; ++cy) { - for (size_t cx = 0; cx < CURSOR_WIDTH; ++cx) { - x = tty->curspos_x + cx; - y = tty->curspos_y + cy; - idx = fbdev_get_index(&tty->fbdev, x, y); - fb_ptr[idx] = color; - } - } -} - -static void -tty_scroll_single(struct tty *tty) -{ - uint32_t *fb_ptr; - size_t line_size, dest_idx, src_idx; - - fb_ptr = tty->fbdev.mem; - line_size = tty->fbdev.pitch/4; - - /* Copy each line up */ - for (size_t y = FONT_HEIGHT; y < tty->t_ws_ypixel; y += FONT_HEIGHT) { - dest_idx = fbdev_get_index(&tty->fbdev, 0, y - FONT_HEIGHT); - src_idx = fbdev_get_index(&tty->fbdev, 0, y); - memcpy32(&fb_ptr[dest_idx], &fb_ptr[src_idx], FONT_HEIGHT*line_size); - } - - /* - * Ensure we start at X position 0 - * after we scrolled down. - */ - tty->chpos_x = 0; - tty->curspos_x = 0; -} - -/* - * Handles a newline. - * - * Call with TTY locked. - */ -static inline void -tty_newline(struct tty *tty) -{ - uint32_t ypos; - const uint32_t MAX_YPOS = tty->t_ws_ypixel - (CURSOR_HEIGHT*2); - - /* Hide the cursor */ - tty_draw_cursor(tty, true); - - /* Reset X positions */ - tty->chpos_x = 0; - tty->curspos_x = 0; - - /* - * Get the value closest to end - * of the screen. - */ - ypos = __MAX(tty->chpos_y, tty->curspos_y); - - /* - * Check if we need to scroll - * instead of incrementing - * Y positions. - */ - if (ypos < MAX_YPOS) { - tty->chpos_y += FONT_HEIGHT; - tty->curspos_y += FONT_HEIGHT; - } else { - tty_scroll_single(tty); - } - - /* Redraw the cursor */ - tty_draw_cursor(tty, false); -} - -/* - * Appends a character to the TTY specified - * by `tty` as well as incrementing tty->chpos_x - * and making newlines as needed. - * - * Call with TTY locked. - */ -static inline void -tty_append_char(struct tty *tty, int c) -{ - const uint32_t MAX_XPOS = tty->t_ws_xpixel - FONT_WIDTH; - - /* Hide the cursor */ - tty_draw_cursor(tty, true); - - tty_draw_char(tty, c, tty->fg, tty->bg); - tty->chpos_x += FONT_WIDTH; - tty->curspos_x += FONT_WIDTH; - - if (tty->chpos_x >= MAX_XPOS) { - tty_newline(tty); - } - - /* Redraw the cursor */ - tty_draw_cursor(tty, false); -} - -/* - * Writes out a tab as `tty->tab_width` - * spaces. - * - * Call with TTY locked. - */ -static void -tty_expand_tab(struct tty *tty) -{ - for (size_t i = 0; i < tty->tab_width; ++i) { - tty_append_char(tty, ' '); - } -} - -/* - * Writes a char to the TTY. - * - * Returns 0 on success; non-zero value - * is a character to be resent. - * - * Call with TTY locked. - */ -static int -tty_putch(struct tty *tty, int c) -{ - if (!__TEST(tty->t_oflag, OPOST)) { - /* - * Just write out the char with - * no processing. - */ - tty_append_char(tty, c); - return 0; - } - - switch (c) { - case ASCII_HT: - /* Tab */ - tty_expand_tab(tty); - break; - case ASCII_LF: - /* Line feed ('\n') */ - tty_newline(tty); - break; - default: - tty_append_char(tty, c); - break; - } - - return 0; -} - -/* - * Flushes a TTY specified by `tty`. - * - * Call with TTY locked. - */ -void -tty_flush(struct tty *tty) -{ - struct tty_ring *ring; - - ring = &tty->ring; - - /* - * Write each byte from the buffer - * to the screen with output processing - * if possible. - * - * XXX: Perhaps there could be a faster - * way of doing this instead of - * byte by byte? - */ - for (size_t i = 0; i < ring->len; ++i) { - tty_putch(tty, ring->buf[i]); - } - - ring->len = 0; -} - -/* - * Writes to a TTY specified by `tty`. - * - * @buf: Buffer to write. - * @len: Length of buffer. - * - * Returns number of bytes written, and - * EXIT_FAILURE on error. - */ -ssize_t -tty_write(struct tty *tty, const char *buf, size_t len) -{ - if (len == 0) { - /* Bad value, don't even try */ - return EXIT_FAILURE; - } - - TTY_LOCK(tty); - for (size_t i = 0; i < len; ++i) { - tty_push_char(tty, buf[i]); - /* - * If we have a newline and we are - * buffering bytes, flush the ring. - */ - if (buf[i] == '\n' && __TEST(tty->t_oflag, ORBUF)) { - tty_flush(tty); - } - } - - /* - * If we aren't buffering bytes, don't - * keep the bytes within the ring and - * flush it right away per `tty_write()` - * call. - */ - if (!__TEST(tty->t_oflag, ORBUF)) { - tty_flush(tty); - } - - TTY_UNLOCK(tty); - return len; -} - -/* - * Sets TTY fields to their defaults. - */ -void -tty_set_defaults(struct tty *tty) -{ - /* Ensure everything is initially zero */ - memset(tty, 0, sizeof(*tty)); - - /* - * Now, initialize everything to their defaults. - * - * Some notes about the default framebuffer device: - * ------------------------------------------------ - * The default framebuffer device should be the - * front buffer. Later on during boot, all attached - * TTYs shall have their fbdev swapped out with a - * backbuffer to improve performace as reading directly - * from video memory is going to be slow. - * - * XXX: At some point we should be allocating a backbuffer - * instead when it's time for *all* TTYs to have them. - * - * A good idea would be to only allocate a backbuffer - * *if* we switched to some TTY and deallocate - * that backbuffer when switching away from that TTY. - * - * The first thing that comes to mind when thinking - * about this idea is loosing our text when we switch - * back out. To rectify this, we could buffer chars - * which would take less memory than keeping the whole - * backbuffer (holds pixels i.e uint32_t). - * - * This can perhaps be done by some internal flag which - * indicates that kmalloc() is usable and chars can - * be buffered. Once we switch back, just allocate - * a new backbuffer and copy the chars back. - */ - tty->fbdev = fbdev_get_front(); - tty->t_oflag = (OPOST | ORBUF); - tty->tab_width = DEFAULT_TAB_WIDTH; - tty->fg = 0x808080; - tty->bg = 0x000000; - tty->t_ws_xpixel = tty->fbdev.width; - tty->t_ws_ypixel = tty->fbdev.height; - tty->t_ws_row = tty->fbdev.height / FONT_HEIGHT; - tty->t_ws_col = tty->fbdev.width / FONT_WIDTH; - -} - -void -tty_attach(struct tty *tty) -{ - TAILQ_INSERT_TAIL(&tty_list, tty, link); - tty_draw_cursor(tty, false); -} - -void -tty_init(void) -{ - TAILQ_INIT(&tty_list); /* Ensure the TTY list is usable */ -} |