aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/init_main.c59
-rw-r--r--sys/kern/kern_panic.c58
-rw-r--r--sys/kern/kern_syslog.c96
-rw-r--r--sys/kern/tty.c387
-rw-r--r--sys/kern/tty_subr.c59
5 files changed, 659 insertions, 0 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
new file mode 100644
index 0000000..2ae2a09
--- /dev/null
+++ b/sys/kern/init_main.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the VegaOS 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 VegaOS 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.
+ */
+
+/* $Id$ */
+
+#include <sys/cdefs.h>
+#include <sys/tty.h>
+#include <sys/syslog.h>
+#include <sys/machdep.h>
+#include <vm/vm_physseg.h>
+#include <logo.h>
+
+__KERNEL_META("$Vega$: init_main.c, Ian Marco Moffett, "
+ "Where the Vega kernel first starts up");
+
+static struct processor bsp = {
+ .gdtr = &g_early_gdtr,
+ .gdt = &g_dmmy_gdt[0]
+};
+
+void
+main(void)
+{
+ tty_init();
+ syslog_init();
+ PRINT_LOGO();
+
+ processor_init(&bsp);
+ vm_physseg_init();
+
+ /* We're done here, halt the processor */
+ __ASMV("cli; hlt");
+}
diff --git a/sys/kern/kern_panic.c b/sys/kern/kern_panic.c
new file mode 100644
index 0000000..69680f7
--- /dev/null
+++ b/sys/kern/kern_panic.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the VegaOS 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 VegaOS 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.
+ */
+
+/* $Id$ */
+
+#include <sys/panic.h>
+#include <sys/syslog.h>
+#include <sys/machdep.h>
+
+/*
+ * Tells the user something terribly
+ * wrong happened then halting the system
+ * as soon as possible.
+ *
+ * XXX: There is no need to cleanup stuff here (e.g `va_list ap`)
+ * as we won't be returning from here anyways and the source
+ * of the panic could be *anywhere* so it's best not to mess with
+ * things.
+ */
+void
+panic(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ kprintf("panic: ");
+ vkprintf(fmt, &ap);
+
+ processor_halt();
+ __builtin_unreachable();
+}
diff --git a/sys/kern/kern_syslog.c b/sys/kern/kern_syslog.c
new file mode 100644
index 0000000..cd7f8f0
--- /dev/null
+++ b/sys/kern/kern_syslog.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the VegaOS 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 VegaOS 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.
+ */
+
+/* $Id$ */
+
+#include <sys/syslog.h>
+#include <sys/tty.h>
+#include <string.h>
+
+static struct tty syslog_tty;
+
+static void
+syslog_handle_fmt(va_list *ap, char fmt_spec)
+{
+ char tmp_ch;
+ int64_t tmp_int;
+ const char *tmp_str;
+ char tmp_buf[256] = { 0 };
+
+ switch (fmt_spec) {
+ case 'c':
+ tmp_ch = va_arg(*ap, int);
+ tty_write(&syslog_tty, &tmp_ch, 1);
+ break;
+ case 's':
+ tmp_str = va_arg(*ap, const char *);
+ tty_write(&syslog_tty, tmp_str, strlen(tmp_str));
+ break;
+ case 'd':
+ tmp_int = va_arg(*ap, int64_t);
+ itoa(tmp_int, tmp_buf, 10);
+ tty_write(&syslog_tty, tmp_buf, strlen(tmp_buf));
+ break;
+ case 'x':
+ tmp_int = va_arg(*ap, uint64_t);
+ itoa(tmp_int, tmp_buf, 16);
+ tty_write(&syslog_tty, tmp_buf + 2, strlen(tmp_buf) - 2);
+ break;
+ }
+}
+
+void
+vkprintf(const char *fmt, va_list *ap)
+{
+ while (*fmt) {
+ if (*fmt == '%') {
+ ++fmt;
+ syslog_handle_fmt(ap, *fmt++);
+ } else {
+ tty_write(&syslog_tty, fmt++, 1);
+ }
+ }
+}
+
+void
+kprintf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vkprintf(fmt, &ap);
+ va_end(ap);
+}
+
+void
+syslog_init(void)
+{
+ tty_set_defaults(&syslog_tty);
+ tty_attach(&syslog_tty);
+}
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
new file mode 100644
index 0000000..f166302
--- /dev/null
+++ b/sys/kern/tty.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the VegaOS 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 VegaOS 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.
+ */
+
+/* $Id$ */
+
+#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("$Vega$: 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 */
+}
diff --git a/sys/kern/tty_subr.c b/sys/kern/tty_subr.c
new file mode 100644
index 0000000..4c8405e
--- /dev/null
+++ b/sys/kern/tty_subr.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2023 Ian Marco Moffett and the VegaOS 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 VegaOS 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.
+ */
+
+/* $Id$ */
+
+#include <sys/tty.h>
+
+/*
+ * Pushes a char to the TTY
+ * ring buffer.
+ *
+ * Call with TTY locked.
+ */
+void
+tty_push_char(struct tty *tty, int c)
+{
+ struct tty_ring *ring;
+
+ ring = &tty->ring;
+
+ /*
+ * If our ring is full, it should
+ * be flushed as soon as possible.
+ *
+ * XXX: ring->len will be reset by tty_flush()
+ * so there is no need to do it here.
+ */
+ if (ring->len >= LINE_RING_SIZE) {
+ tty_flush(tty);
+ }
+
+ ring->buf[ring->len++] = c;
+}