#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 /* * Lock, which ensures that prints to the serial port are atomic (ie. one debugprintf is atomic in * itself). */ static spin_lock_t serial_lock = SPIN_LOCK_INIT; static bool debug_init = false; /* Block until TX buffer is empty */ static bool amd64_debug_serial_tx_empty (void) { return (bool)(amd64_io_inb (PORT_COM1 + 5) & 0x20); } /* Write a single character to serial */ static void amd64_debug_serial_write (char x) { while (!amd64_debug_serial_tx_empty ()) ; amd64_io_outb (PORT_COM1, (uint8_t)x); } /* * Formatted printing to serial. serial_lock ensures that all prints are atomic. */ void debugprintf (const char* fmt, ...) { spin_lock_ctx_t ctxdbgp; if (!debug_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 (&serial_lock, &ctxdbgp); while (*p) { amd64_debug_serial_write (*p); p++; } spin_unlock (&serial_lock, &ctxdbgp); } /* Initialize serial */ void amd64_debug_init (void) { amd64_io_outb (PORT_COM1 + 1, 0x00); amd64_io_outb (PORT_COM1 + 3, 0x80); amd64_io_outb (PORT_COM1 + 0, 0x03); amd64_io_outb (PORT_COM1 + 1, 0x00); amd64_io_outb (PORT_COM1 + 3, 0x03); amd64_io_outb (PORT_COM1 + 2, 0xC7); amd64_io_outb (PORT_COM1 + 4, 0x0B); debug_init = true; }