#include #include #include #include #include #include #include /// Port for printing to serial #define PORT_COM1 0x03F8 /// \ref debugprintf buffer size #define BUFFER_SIZE 1024 /// Lock, which ensures that prints to the serial port are atomic 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); } /** * @brief Formatted printing to serial. \ref serial_lock ensures that * all prints are atomic. */ void debugprintf (const char* fmt, ...) { 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); while (*p) { amd64_debug_serial_write (*p); p++; } spin_unlock (&serial_lock); } /// 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; }