diff options
author | Joursoir <chat@joursoir.net> | 2021-08-05 14:44:54 +0000 |
---|---|---|
committer | Joursoir <chat@joursoir.net> | 2021-08-05 14:44:54 +0000 |
commit | fd5a3001e12a341fd23cedcf63a37b399b52e0d1 (patch) | |
tree | 5e842784af1bdf7bdf80b5fadb3b23b7cfb1911c | |
parent | 9d6cbd98bf5397041454d2871a352e14c53d9ba0 (diff) | |
download | mfsos-fd5a3001e12a341fd23cedcf63a37b399b52e0d1.tar.gz mfsos-fd5a3001e12a341fd23cedcf63a37b399b52e0d1.tar.bz2 mfsos-fd5a3001e12a341fd23cedcf63a37b399b52e0d1.zip |
video-vga: add routines for vga
-rw-r--r-- | kernel/video-vga.c | 98 | ||||
-rw-r--r-- | kernel/video-vga.h | 36 |
2 files changed, 134 insertions, 0 deletions
diff --git a/kernel/video-vga.c b/kernel/video-vga.c new file mode 100644 index 0000000..4a7a14c --- /dev/null +++ b/kernel/video-vga.c @@ -0,0 +1,98 @@ +#include "video-vga.h" +#include "string.h" +#include "i386.h" + +#define VGA_BASE 0xB8000 +#define CRTC_PORT 0x3D4 + +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 + +static size_t vga_row, vga_column; +static uint8_t vga_color; +static uint16_t *vga_buffer; + +uint8_t vga_entry_color(enum vga_colors fg, enum vga_colors bg) +{ + return fg | bg << 4; +} + +uint16_t vga_entry(uint8_t uc, uint8_t color) +{ + return (uint16_t) uc | (uint16_t) color << 8; +} + +void vga_init(void) +{ + size_t x, y; + size_t vga_char; + vga_row = 0, vga_column = 0; + vga_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); + vga_char = vga_entry(' ', vga_color); + vga_buffer = (uint16_t *) VGA_BASE; + for(y = 0; y < VGA_HEIGHT; y++) { + for(x = 0; x < VGA_WIDTH; x++) { + const size_t index = y * VGA_WIDTH + x; + vga_buffer[index] = vga_char; + } + } +} + +void vga_setcolor(uint8_t color) +{ + vga_color = color; +} + +void vga_scroll(size_t lines) +{ + size_t count = (VGA_HEIGHT - lines) * VGA_WIDTH; + size_t vga_char = vga_entry(' ', vga_color); + + memmove(vga_buffer, vga_buffer + VGA_WIDTH * lines, count * 2); + for(; count < (vga_row + 1) * VGA_WIDTH; count++) + vga_buffer[count] = vga_char; +} + +void vga_putchar(char c) +{ + uint16_t pos; + if(c == '\n') { + vga_column = 0; + if(++vga_row >= VGA_HEIGHT) { + vga_scroll(1); + vga_row--; + } + } + else { + const size_t index = vga_row * VGA_WIDTH + vga_column; + vga_buffer[index] = vga_entry(c, vga_color); + + if(++vga_column >= VGA_WIDTH) { + vga_column = 0; + if(++vga_row >= VGA_HEIGHT) { + vga_scroll(1); + vga_row--; + } + } + } + + /* Update cursor position */ + pos = vga_row * VGA_WIDTH + vga_column; + outb(CRTC_PORT, 0x0E); + outb(CRTC_PORT+1, (uint8_t) ((pos >> 8) & 0xFF)); + outb(CRTC_PORT, 0x0F); + outb(CRTC_PORT+1, (uint8_t) (pos & 0xFF)); +} + + +void vga_write(const char *str, size_t size) +{ + size_t i; + for(i = 0; i < size; i++) + vga_putchar(str[i]); +} + +void vga_print(const char *str) +{ + vga_write(str, strlen(str)); +} diff --git a/kernel/video-vga.h b/kernel/video-vga.h new file mode 100644 index 0000000..ddcfc31 --- /dev/null +++ b/kernel/video-vga.h @@ -0,0 +1,36 @@ +#ifndef KERNEL_VIDEO_VGA +#define KERNEL_VIDEO_VGA + +#include <stddef.h> +#include <stdint.h> + +/* Hardware text mode color constants. */ +enum vga_colors { + VGA_COLOR_BLACK = 0, + VGA_COLOR_BLUE = 1, + VGA_COLOR_GREEN = 2, + VGA_COLOR_CYAN = 3, + VGA_COLOR_RED = 4, + VGA_COLOR_MAGENTA = 5, + VGA_COLOR_BROWN = 6, + VGA_COLOR_LIGHT_GREY = 7, + VGA_COLOR_DARK_GREY = 8, + VGA_COLOR_LIGHT_BLUE = 9, + VGA_COLOR_LIGHT_GREEN = 10, + VGA_COLOR_LIGHT_CYAN = 11, + VGA_COLOR_LIGHT_RED = 12, + VGA_COLOR_LIGHT_MAGENTA = 13, + VGA_COLOR_LIGHT_BROWN = 14, + VGA_COLOR_WHITE = 15 +}; + +uint8_t vga_entry_color(enum vga_colors fg, enum vga_colors bg); +uint16_t vga_entry(uint8_t uc, uint8_t color); +void vga_init(void); +void vga_setcolor(uint8_t color); +void vga_scroll(size_t lines); +void vga_putchar(char c); +void vga_write(const char *str, size_t size); +void vga_print(const char *str); + +#endif /* KERNEL_VIDEO_VGA */ |