summaryrefslogtreecommitdiff
path: root/kernel/src/tty
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/tty')
-rw-r--r--kernel/src/tty/color.c67
-rw-r--r--kernel/src/tty/color.h62
-rw-r--r--kernel/src/tty/cursor.c30
-rw-r--r--kernel/src/tty/cursor.h9
-rw-r--r--kernel/src/tty/term.c131
-rw-r--r--kernel/src/tty/term.h27
6 files changed, 326 insertions, 0 deletions
diff --git a/kernel/src/tty/color.c b/kernel/src/tty/color.c
new file mode 100644
index 0000000..c7258d9
--- /dev/null
+++ b/kernel/src/tty/color.c
@@ -0,0 +1,67 @@
+#include "color.h"
+#include "panic.h"
+
+bool itoac(int i, enum AnsiiColor *color) {
+ if (i < 0 || i > 15) return false;
+ *color = i;
+ return true;
+}
+
+bool itovc(int i, enum VGAColor *color) {
+ if (
+ (i >= 30 && i <= 37) ||
+ (i >= 40 && i <= 47) ||
+ (i >= 90 && i <= 97) ||
+ (i >= 100 && i <= 107)
+ ) {
+ *color = i;
+ return true;
+ }
+ return false;
+}
+
+enum VGAColor atovc(enum AnsiiColor color) {
+ switch(color) {
+ case ANSII_FRONT_BLACK:
+ case ANSII_FRONT_BLACK_EMPH:
+ case ANSII_BACK_BLACK:
+ case ANSII_BACK_BLACK_EMPH:
+ return VGA_BLACK;
+ case ANSII_FRONT_RED:
+ case ANSII_FRONT_RED_EMPH:
+ case ANSII_BACK_RED:
+ case ANSII_BACK_RED_EMPH:
+ return VGA_LIGHT_RED;
+ case ANSII_FRONT_GREEN:
+ case ANSII_FRONT_GREEN_EMPH:
+ case ANSII_BACK_GREEN:
+ case ANSII_BACK_GREEN_EMPH:
+ return VGA_LIGHT_GREEN;
+ case ANSII_FRONT_YELLOW:
+ case ANSII_FRONT_YELLOW_EMPH:
+ case ANSII_BACK_YELLOW:
+ case ANSII_BACK_YELLOW_EMPH:
+ return VGA_LIGHT_BROWN;
+ case ANSII_FRONT_BLUE:
+ case ANSII_FRONT_BLUE_EMPH:
+ case ANSII_BACK_BLUE:
+ case ANSII_BACK_BLUE_EMPH:
+ return VGA_LIGHT_BLUE;
+ case ANSII_FRONT_PURPLE:
+ case ANSII_FRONT_PURPLE_EMPH:
+ case ANSII_BACK_PURPLE:
+ case ANSII_BACK_PURPLE_EMPH:
+ return VGA_LIGHT_MAGENTA;
+ case ANSII_FRONT_CYAN:
+ case ANSII_FRONT_CYAN_EMPH:
+ case ANSII_BACK_CYAN:
+ case ANSII_BACK_CYAN_EMPH:
+ return VGA_LIGHT_CYAN;
+ case ANSII_FRONT_WHITE:
+ case ANSII_FRONT_WHITE_EMPH:
+ case ANSII_BACK_WHITE:
+ case ANSII_BACK_WHITE_EMPH:
+ return VGA_WHITE;
+ }
+ panic("this should not be reached (make gcc quiet)");
+}
diff --git a/kernel/src/tty/color.h b/kernel/src/tty/color.h
new file mode 100644
index 0000000..0751353
--- /dev/null
+++ b/kernel/src/tty/color.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+enum VGAColor {
+ VGA_BLACK = 0,
+ VGA_BLUE = 1,
+ VGA_GREEN = 2,
+ VGA_CYAN = 3,
+ VGA_RED = 4,
+ VGA_MAGENTA = 5,
+ VGA_BROWN = 6,
+ VGA_LIGHT_GREY = 7,
+ VGA_DARK_GREY = 8,
+ VGA_LIGHT_BLUE = 9,
+ VGA_LIGHT_GREEN = 10,
+ VGA_LIGHT_CYAN = 11,
+ VGA_LIGHT_RED = 12,
+ VGA_LIGHT_MAGENTA = 13,
+ VGA_LIGHT_BROWN = 14,
+ VGA_WHITE = 15,
+};
+
+enum AnsiiColor {
+ ANSII_FRONT_BLACK = 30,
+ ANSII_FRONT_RED = 31,
+ ANSII_FRONT_GREEN = 32,
+ ANSII_FRONT_YELLOW = 33,
+ ANSII_FRONT_BLUE = 34,
+ ANSII_FRONT_PURPLE = 35,
+ ANSII_FRONT_CYAN = 36,
+ ANSII_FRONT_WHITE = 37,
+ ANSII_FRONT_BLACK_EMPH = 90,
+ ANSII_FRONT_RED_EMPH = 91,
+ ANSII_FRONT_GREEN_EMPH = 92,
+ ANSII_FRONT_YELLOW_EMPH = 93,
+ ANSII_FRONT_BLUE_EMPH = 94,
+ ANSII_FRONT_PURPLE_EMPH = 95,
+ ANSII_FRONT_CYAN_EMPH = 96,
+ ANSII_FRONT_WHITE_EMPH = 97,
+ ANSII_BACK_BLACK = 40,
+ ANSII_BACK_RED = 41,
+ ANSII_BACK_GREEN = 42,
+ ANSII_BACK_YELLOW = 43,
+ ANSII_BACK_BLUE = 44,
+ ANSII_BACK_PURPLE = 45,
+ ANSII_BACK_CYAN = 46,
+ ANSII_BACK_WHITE = 47,
+ ANSII_BACK_BLACK_EMPH = 100,
+ ANSII_BACK_RED_EMPH = 101,
+ ANSII_BACK_GREEN_EMPH = 102,
+ ANSII_BACK_YELLOW_EMPH = 103,
+ ANSII_BACK_BLUE_EMPH = 104,
+ ANSII_BACK_PURPLE_EMPH = 105,
+ ANSII_BACK_CYAN_EMPH = 106,
+ ANSII_BACK_WHITE_EMPH = 107,
+};
+
+bool itoac(int i, enum AnsiiColor *color);
+bool itovc(int i, enum VGAColor *color);
+enum VGAColor atovc(enum AnsiiColor color);
diff --git a/kernel/src/tty/cursor.c b/kernel/src/tty/cursor.c
new file mode 100644
index 0000000..3a3888b
--- /dev/null
+++ b/kernel/src/tty/cursor.c
@@ -0,0 +1,30 @@
+#include <sys.h>
+
+#include "cursor.h"
+#include "term.h"
+
+void cursor_enable(void) {
+ cursor_setsize(13, 16);
+}
+
+void cursor_disable(void) {
+ outb(0x3D4, 0x0A);
+ outb(0x3D5, 0x20);
+}
+
+void cursor_setsize(uint8_t start, uint8_t end) {
+ outb(0x3D4, 0x0A);
+ outb(0x3D5, (inb(0x3D5) & 0xC0) | start);
+
+ outb(0x3D4, 0x0B);
+ outb(0x3D5, (inb(0x3D5) & 0xE0) | end);
+}
+
+void cursor_setpos(uint8_t x, uint8_t y) {
+; uint16_t pos = y * TERM_W + x;
+
+ outb(0x3D4, 0x0F);
+ outb(0x3D5, (uint8_t) (pos & 0xFF));
+ outb(0x3D4, 0x0E);
+ outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
+}
diff --git a/kernel/src/tty/cursor.h b/kernel/src/tty/cursor.h
new file mode 100644
index 0000000..602d9cd
--- /dev/null
+++ b/kernel/src/tty/cursor.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <stdint.h>
+
+void cursor_enable(void);
+void cursor_disable(void);
+void cursor_setsize(uint8_t start, uint8_t end);
+void cursor_setpos(uint8_t x, uint8_t y);
+
diff --git a/kernel/src/tty/term.c b/kernel/src/tty/term.c
new file mode 100644
index 0000000..4f75788
--- /dev/null
+++ b/kernel/src/tty/term.c
@@ -0,0 +1,131 @@
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys.h>
+#include <print.h>
+
+#include "term.h"
+#include "color.h"
+#include "cursor.h"
+
+uint16_t *buffer;
+uint8_t x, y;
+uint8_t color;
+
+const uint16_t blank = (uint16_t) 0 | VGA_BLACK << 12 | VGA_WHITE << 8;
+
+static void term_clear_line(int y) {
+ if (y < 0 || y >= TERM_H)
+ return;
+ for (uint8_t x = 0; x < TERM_W; x++) {
+ const size_t index = y * TERM_W + x;
+ buffer[index] = blank;
+ }
+}
+
+void term_init (void) {
+ x = 0;
+ y = 0;
+ buffer = (uint16_t*) 0xb8000;
+ term_setfg(VGA_WHITE);
+ term_setbg(VGA_BLACK);
+ term_clear();
+}
+
+void term_setpos(uint8_t xp, uint8_t yp) {
+ x = xp;
+ y = yp;
+ cursor_setpos(x, y);
+}
+
+void term_scroll (int lines) {
+ int_disable();
+ y -= lines;
+ if (!lines) return;
+ if(lines >= TERM_H || lines <= -TERM_H) {
+ term_clear();
+ } else if(lines > 0) {
+ memmove(buffer, buffer + lines * TERM_W, 2 * (TERM_H - lines) * TERM_W);
+ term_clear_line(TERM_H - lines);
+ } else {
+ memmove(buffer + lines * TERM_W, buffer + lines, (TERM_H + lines) * TERM_W);
+ }
+ int_enable();
+}
+
+void term_setfg(enum VGAColor c) {
+ color = (color & 0xF0) | c;
+}
+
+void term_setbg(enum VGAColor c) {
+ color = (color & 0x0F) | c << 4;
+}
+
+void term_clear (void) {
+ for (uint8_t y = 0; y < TERM_H; y++)
+ term_clear_line(y);
+}
+
+uint32_t term_save(void) {
+ uint32_t state = 0;
+ state |= (uint32_t) x << 16;
+ state |= (uint32_t) y << 8;
+ state |= (uint32_t) color << 0;
+ return state;
+}
+
+void term_load(uint32_t state) {
+ x = (uint8_t) (state >> 16);
+ y = (uint8_t) (state >> 8);
+ color = (uint8_t) (state >> 0);
+ cursor_setpos(x, y);
+}
+
+uint16_t term_save_col(void) {
+ return color;
+}
+
+void term_load_col(uint16_t c) {
+ color = c;
+}
+
+void putchar(int c) {
+ switch (c) {
+ case '\n':
+ x = 0;
+ y++;
+ break;
+ case '\t':
+ x += 4;
+ break;
+ case '\v':
+ case '\f':
+ y++;
+ break;
+ case '\r':
+ x = 0;
+ break;
+ default: {
+ const size_t index = y * TERM_W + x;
+ buffer[index] = c | (uint16_t) color << 8;
+ x++;
+ }
+ }
+
+ if (x >= TERM_W) {
+ x = 0;
+ y++;
+ }
+
+ if (y >= TERM_H) {
+ term_scroll(y - (TERM_H - 1));
+ y = TERM_H - 1;
+ }
+
+ cursor_setpos(x, y);
+}
+
+bool term_newline(void) {
+ return x == 0;
+}
diff --git a/kernel/src/tty/term.h b/kernel/src/tty/term.h
new file mode 100644
index 0000000..f6eb555
--- /dev/null
+++ b/kernel/src/tty/term.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "color.h"
+
+#define TERM_W 80
+#define TERM_H 25
+
+void term_init(void);
+
+void term_reset(void);
+void term_setfg(enum VGAColor color);
+void term_setbg(enum VGAColor color);
+
+void term_clear(void);
+void term_scroll(int lines);
+void term_setpos(uint8_t x, uint8_t y);
+
+uint32_t term_save(void);
+void term_load(uint32_t state);
+
+uint16_t term_save_col(void);
+void term_load_col(uint16_t color);
+
+bool term_newline(void);