aboutsummaryrefslogtreecommitdiff
path: root/devices/vga.c
diff options
context:
space:
mode:
Diffstat (limited to 'devices/vga.c')
-rw-r--r--devices/vga.c112
1 files changed, 104 insertions, 8 deletions
diff --git a/devices/vga.c b/devices/vga.c
index 983e630..908bd5e 100644
--- a/devices/vga.c
+++ b/devices/vga.c
@@ -1,35 +1,131 @@
#include "vga.h"
-#include <stddef.h>
#include <stdint.h>
+#include <sys/io.h>
struct __attribute__((packed)) VGAEntry {
unsigned char text;
uint8_t foreground : 4;
uint8_t background : 4;
};
+_Static_assert(sizeof(struct VGAEntry) == 2, "sizeof VGAEntry");
-_Static_assert(sizeof(struct VGAEntry) == 2);
-
-const size_t width = 80;
-const size_t height = 25;
+const int width = 80;
+const int height = 25;
struct VGAEntry *buffer;
+int col = 0;
+int row = 0;
void
vga_init()
{
buffer = (struct VGAEntry *)0xc03ff000;
+ // vga_enable_cursor(0, 15);
vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
}
void
vga_clear(enum vga_color foreground, enum vga_color background)
{
- for (size_t y = 0; y < height; ++y)
- for (size_t x = 0; x < width; ++x) {
- const size_t index = y * width + x;
+ 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;
+ // vga_update_cursor();
+}
+
+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;
+ }
+}
+
+void
+vga_puts(const char *string, int len)
+{
+
+ if (len == -1)
+ while (*string != '\0') {
+ vga_putc(*string);
+ ++string;
+ }
+
+ else
+ for (int i = 0; i < len; ++i) { vga_putc(string[i]); }
+}
+
+// Cursor
+const uint16_t cga_idx_port = 0x3d4;
+const uint16_t cga_dat_port = 0x3d5;
+
+const uint8_t cursor_start = 0xa;
+const uint8_t cursor_end = 0xb;
+const uint8_t cursor_addr_h = 0xe;
+const uint8_t cursor_addr_l = 0xf;
+const uint8_t cursor_hide = 0x20;
+
+void
+vga_enable_cursor(unsigned char start, unsigned char end)
+{
+ outb(cga_idx_port, cursor_start);
+ outb(cga_dat_port, (inb(cga_dat_port) & 0xc0) | start);
+
+ outb(cga_idx_port, cursor_end);
+ outb(cga_dat_port, (inb(cga_dat_port) & 0xe0) | end);
+}
+
+void
+vga_disable_cursor()
+{
+ outb(cga_idx_port, cursor_start);
+ outb(cga_dat_port, cursor_hide);
+}
+
+void
+vga_update_cursor()
+{
+ const uint16_t pos = row * width + col;
+
+ outb(cga_idx_port, cursor_addr_l);
+ outb(cga_dat_port, pos & 0xff);
+
+ outb(cga_idx_port, cursor_addr_h);
+ outb(cga_dat_port, (pos >> 8) & 0xff);
}