diff options
Diffstat (limited to 'kernel/src/tty')
-rw-r--r-- | kernel/src/tty/color.c | 67 | ||||
-rw-r--r-- | kernel/src/tty/color.h | 62 | ||||
-rw-r--r-- | kernel/src/tty/cursor.c | 30 | ||||
-rw-r--r-- | kernel/src/tty/cursor.h | 9 | ||||
-rw-r--r-- | kernel/src/tty/term.c | 131 | ||||
-rw-r--r-- | kernel/src/tty/term.h | 27 |
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); |