summaryrefslogtreecommitdiff
path: root/sys/kern/tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r--sys/kern/tty.c382
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 */
-}