#include #include #include #include #include #include #include /* Port for printing to serial */ /* TODO: Make this configurable */ #define PORT_COM1 0x03F8 /* debugprintf buffer size */ #define BUFFER_SIZE 1024 static spin_lock_t debug_lock = SPIN_LOCK_INIT; static bool debug_is_init = false; /* Block until TX buffer is empty */ static bool debug_serial_tx_empty(void) { return (bool)(inb(PORT_COM1 + 5) & 0x20); } /* Write a single character to serial */ static void debug_serial_write(char x) { while (!debug_serial_tx_empty()) ; outb(PORT_COM1, (uint8_t)x); } /* * Formatted printing to serial. serial_lock ensures that all prints are atomic. */ void debugprintf(const char* fmt, ...) { if (!debug_is_init) return; char buffer[BUFFER_SIZE]; memset(buffer, 0, sizeof(buffer)); va_list ap; va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); buffer[sizeof(buffer) - 1] = '\0'; const char* p = buffer; spin_lock(&debug_lock); while (*p) { debug_serial_write(*p); p++; } spin_unlock(&debug_lock); } void debugprintf_nolock(const char* fmt, ...) { if (!debug_is_init) return; char buffer[BUFFER_SIZE]; memset(buffer, 0, sizeof(buffer)); va_list ap; va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); buffer[sizeof(buffer) - 1] = '\0'; const char* p = buffer; while (*p) { debug_serial_write(*p); p++; } } /* Initialize serial */ void debug_init(void) { outb(PORT_COM1 + 1, 0x00); outb(PORT_COM1 + 3, 0x80); outb(PORT_COM1 + 0, 0x03); outb(PORT_COM1 + 1, 0x00); outb(PORT_COM1 + 3, 0x03); outb(PORT_COM1 + 2, 0xC7); outb(PORT_COM1 + 4, 0x0B); debug_is_init = true; }