From 9b2a78fa52249ab481493550490aa5f37872dcf6 Mon Sep 17 00:00:00 2001 From: aqua Date: Sat, 10 Dec 2022 20:56:57 +0200 Subject: Rewrite drivers/uart and drivers/vga in cpp --- devices/vga.cpp | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 devices/vga.cpp (limited to 'devices/vga.cpp') diff --git a/devices/vga.cpp b/devices/vga.cpp new file mode 100644 index 0000000..3f83a5f --- /dev/null +++ b/devices/vga.cpp @@ -0,0 +1,138 @@ +#include "vga.hpp" +#include +#include + +// FIXME user a Port +#define cga_idx_port 0x3d4 +#define cga_dat_port 0x3d5 + +// FIXME make constexpr +#define cursor_start 0x0a +#define cursor_end 0x0b +#define cursor_addr_h 0x0e +#define cursor_addr_l 0x0f +#define cursor_hide 0x20 + +static_assert(sizeof(struct VGA::VGAEntry) == 2, "sizeof VGAEntry"); + +// FIXME make constexpr +const int width = 80; +const int height = 25; + +// *** Cursor *** +// FIXME make VGA members +void +vga_enable_cursor(unsigned char start, unsigned char end) +{ + outb(cursor_start, cga_idx_port); + outb((inb(cga_dat_port) & 0xc0) | start, cga_dat_port); + + outb(cursor_end, cga_idx_port); + outb((inb(cga_dat_port) & 0xe0) | end, cga_dat_port); +} + +void +vga_disable_cursor() +{ + outb(cursor_start, cga_idx_port); + outb(cursor_hide, cga_dat_port); +} + +void +VGA::update_cursor() +{ + const uint16_t pos = row * width + col; + + outb(cursor_addr_l, cga_idx_port); + outb(pos & 0xff, cga_dat_port); + + outb(cursor_addr_h, cga_idx_port); + outb((pos >> 8) & 0xff, cga_dat_port); +} + +// *** Text Mode Output *** +void +VGA::putc(char a) +{ + switch (a) { + case '\n': + col = 0; + ++row; + break; + case '\r': + col = 0; + break; + case '\b': + --col; + if (col < 0) col = 0; + break; + default: + buffer[row * width + col].text = a; + ++col; + } + + if (col == width) { + col = 0; + ++row; + } + + if (row == height) { + // scroll up + for (int y = 1; y < height; ++y) + for (int x = 0; x < width; ++x) { + const int prev = (y - 1) * width + x; + const int curr = y * width + x; + buffer[prev] = buffer[curr]; + } + // blank out last row + for (int i = (height - 1) * width; i < height * width; ++i) buffer[i].text = ' '; + --row; + } +} + +int +VGA::puts(const char *string, int len) +{ + int written = 0; + if (len == -1) + while (*string != '\0') { + putc(*string); + ++string; + ++written; + } + + else + for (int i = 0; i < len; ++i) { + putc(string[i]); + ++written; + } + return written; +} + +// *** Text Mode *** +VGA::VGA(void *addr) +{ + buffer = (struct VGAEntry *)addr; + vga_enable_cursor(14, 15); + clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY); +} +FILE * +vga_init(void *buffer) +{ + static VGA device(buffer); + return &device; +} + +void +VGA::clear(enum vga_color foreground, enum vga_color background) +{ + for (int y = 0; y < height; ++y) + for (int x = 0; x < width; ++x) { + const int index = y * width + x; + buffer[index].text = ' '; + buffer[index].foreground = foreground; + buffer[index].background = background; + } + col = row = 0; + update_cursor(); +} -- cgit v1.2.1