aboutsummaryrefslogtreecommitdiff
path: root/kernel/l0/dbglog.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/l0/dbglog.c')
-rw-r--r--kernel/l0/dbglog.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/kernel/l0/dbglog.c b/kernel/l0/dbglog.c
new file mode 100644
index 0000000..0285002
--- /dev/null
+++ b/kernel/l0/dbglog.c
@@ -0,0 +1,151 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <printf.h>
+#include <dbglog.h>
+#include <config.h>
+#include <sys.h>
+
+// ==================================================================
+
+#ifdef DBGLOG_TO_SCREEN
+
+static const size_t VGA_WIDTH = 80;
+static const size_t VGA_HEIGHT = 25;
+
+static uint8_t vga_color = 7;
+static uint16_t* vga_buffer = 0;
+static uint16_t vga_row = 0, vga_column = 0;
+
+static uint16_t make_vgaentry(char c, uint8_t color) {
+ uint16_t c16 = c;
+ uint16_t color16 = color;
+ return c16 | color16 << 8;
+}
+
+static void vga_putentryat(char c, uint8_t color, size_t x, size_t y) {
+ const size_t index = y * VGA_WIDTH + x;
+ vga_buffer[index] = make_vgaentry(c, color);
+}
+
+static void vga_update_cursor() {
+ uint16_t cursor_location = vga_row * 80 + vga_column;
+ outb(0x3D4, 14); //Sending high cursor byte
+ outb(0x3D5, cursor_location >> 8);
+ outb(0x3D4, 15); //Sending high cursor byte
+ outb(0x3D5, cursor_location);
+}
+
+static void vga_init() {
+ vga_row = 0;
+ vga_column = 0;
+ vga_buffer = (uint16_t*) (&k_highhalf_addr + 0xB8000);
+
+ for (size_t y = 0; y < VGA_HEIGHT; y++) {
+ for (size_t x = 0; x < VGA_WIDTH; x++) {
+ vga_putentryat(' ', vga_color, x, y);
+ }
+ }
+
+ vga_update_cursor();
+}
+
+static void vga_scroll() {
+ for (size_t i = 0; i < VGA_WIDTH * (VGA_HEIGHT - 1); i++) {
+ vga_buffer[i] = vga_buffer[i + VGA_WIDTH];
+ }
+ for (size_t x = 0; x < VGA_WIDTH; x++) {
+ vga_putentryat(' ', vga_color, x, VGA_HEIGHT - 1);
+ }
+ vga_row--;
+}
+
+static void vga_newline() {
+ vga_column = 0;
+ if (++vga_row == VGA_HEIGHT) {
+ vga_scroll();
+ }
+}
+
+static void vga_putc(char c) {
+ if (c == '\n') {
+ vga_newline();
+ } else if (c == '\t') {
+ vga_putc(' ');
+ while (vga_column % 4 != 0) vga_putc(' ');
+ } else {
+ vga_putentryat(c, vga_color, vga_column, vga_row);
+ if (++vga_column == VGA_WIDTH) {
+ vga_newline();
+ }
+ }
+}
+
+static void vga_puts(const char* data) {
+ size_t datalen = strlen(data);
+ for (size_t i = 0; i < datalen; i++)
+ vga_putc(data[i]);
+
+ vga_update_cursor();
+}
+
+#endif // DBGLOG_TO_SCREEN
+
+// ==================================================================
+
+#ifdef DBGLOG_TO_SERIAL
+
+#define SER_PORT 0x3F8 // COM1
+
+static void serial_init() {
+ outb(SER_PORT + 1, 0x00); // disable interrupts
+ outb(SER_PORT + 3, 0x80); // set baud rate
+ outb(SER_PORT + 0, 0x03); // set divisor to 3 (38400 baud)
+ outb(SER_PORT + 1, 0x00);
+ outb(SER_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(SER_PORT + 2, 0xC7); // enable FIFO, clear them, with 14-byte threshold
+}
+
+static void serial_putc(const char c) {
+ while (!(inb(SER_PORT + 5) & 0x20));
+ outb(SER_PORT, c);
+}
+
+static void serial_puts(const char *c) {
+ while (*c) {
+ serial_putc(*c);
+ c++;
+ }
+}
+
+#endif // DBGLOG_TO_SERIAL
+
+// ==================================================================
+
+void dbglog_setup() {
+#ifdef DBGLOG_TO_SCREEN
+ vga_init();
+#endif
+#ifdef DBGLOG_TO_SERIAL
+ serial_init();
+#endif
+}
+
+void dbg_print(const char* str) {
+#ifdef DBGLOG_TO_SCREEN
+ vga_puts(str);
+#endif
+#ifdef DBGLOG_TO_SERIAL
+ serial_puts(str);
+#endif
+}
+
+void dbg_printf(const char* fmt, ...) {
+ va_list ap;
+ char buffer[256];
+
+ va_start(ap, fmt);
+ vsnprintf(buffer, 256, fmt, ap);
+ va_end(ap);
+
+ dbg_print(buffer);
+}