aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-05-18 01:00:19 -0400
committerIan Moffett <ian@osmora.org>2024-05-18 01:01:07 -0400
commit68bc6fb38fe2f308746d74de1973c7aa84fed440 (patch)
tree61928ffcc55703133c90c5ede4d17b96898c9333
parenta38eb07f6cee8618d2ad59396a46e6bfee05b1b3 (diff)
kernel: tty: Handle ICANON
Add basic handling for canonical mode Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--sys/arch/amd64/isa/i8042.c1
-rw-r--r--sys/kern/kern_tty.c46
2 files changed, 41 insertions, 6 deletions
diff --git a/sys/arch/amd64/isa/i8042.c b/sys/arch/amd64/isa/i8042.c
index dd1990f..0f160d3 100644
--- a/sys/arch/amd64/isa/i8042.c
+++ b/sys/arch/amd64/isa/i8042.c
@@ -237,7 +237,6 @@ kb_isr(void *sf)
tty_putc(&g_root_tty, c);
}
}
- tty_flush(&g_root_tty);
spinlock_release(&data_lock);
lapic_send_eoi();
}
diff --git a/sys/kern/kern_tty.c b/sys/kern/kern_tty.c
index 641e7ba..7be7042 100644
--- a/sys/kern/kern_tty.c
+++ b/sys/kern/kern_tty.c
@@ -31,6 +31,7 @@
#include <sys/cdefs.h>
#include <sys/errno.h>
#include <sys/syslog.h>
+#include <sys/ascii.h>
#include <fs/devfs.h>
#include <string.h>
@@ -62,18 +63,27 @@ static ssize_t
__tty_flush(struct tty *tty)
{
struct tty_ring *ring = &tty->ring;
+ const struct termios *termios;
size_t count = 0;
char tmp;
+ termios = &tty->termios;
+
/* Do we have any data left? */
if (ring->deq_index >= ring->enq_index)
return -EAGAIN;
- /* Flush the ring */
- while (ring->deq_index < ring->enq_index) {
- tmp = ring->data[ring->deq_index++];
- vcons_putch(tty->scr, tmp);
- ++count;
+ /*
+ * Flush the ring to the console if we are in
+ * canonical mode. Otherwise, just throw away
+ * the bytes.
+ */
+ if (__TEST(termios->c_lflag, ICANON)) {
+ while (ring->deq_index < ring->enq_index) {
+ tmp = ring->data[ring->deq_index++];
+ vcons_putch(tty->scr, tmp);
+ ++count;
+ }
}
ring->enq_index = 0;
@@ -132,11 +142,37 @@ int
tty_putc(struct tty *tty, int c)
{
struct tty_ring *ring;
+ const struct termios *termios;
+ bool canon;
ring = &tty->ring;
+ termios = &tty->termios;
+ canon = __TEST(termios->c_lflag, ICANON);
+
spinlock_acquire(&tty->rlock);
ring->data[ring->enq_index++] = c;
+ /*
+ * If we aren't in canonical mode, just write directly to
+ * the console.
+ *
+ * XXX: Won't need to worry about extra bytes being printed
+ * as __tty_flush() won't flush them to the console
+ * when we aren't in canonical mode.
+ */
+ if (!canon) {
+ vcons_putch(tty->scr, c);
+ }
+
+ /*
+ * If we are in canonical mode and we have a linefeed ('\n')
+ * character, we should flush the ring.
+ */
+ if (canon && c == ASCII_LF) {
+ __tty_flush(tty);
+ }
+
+ /* Flush if the buffer is full */
if (ring->enq_index >= TTY_RING_SIZE) {
__tty_flush(tty);
}