From a9e95db39bb090571535edae47d2051ad3fc5691 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 6 May 2023 21:33:36 +0100 Subject: [PATCH] x86_64: write printk messages to COM1 serial port --- arch/x86_64/include/arch/serial.h | 2 + arch/x86_64/init.c | 2 + arch/x86_64/serial.c | 88 ++++++++++++++++++++++++++----- arch/x86_64/vgacon.c | 2 +- 4 files changed, 80 insertions(+), 14 deletions(-) diff --git a/arch/x86_64/include/arch/serial.h b/arch/x86_64/include/arch/serial.h index ac58933..cb7e828 100644 --- a/arch/x86_64/include/arch/serial.h +++ b/arch/x86_64/include/arch/serial.h @@ -18,6 +18,8 @@ extern char serial_recv_byte(int device); extern int serial_rcvd(int device); +extern void serialcon_init(void); + #ifdef __cplusplus } #endif diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index 5091116..fa56e88 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #define PTR32(x) ((void *)((uintptr_t)(x))) @@ -47,6 +48,7 @@ int ml_init(uintptr_t arg) bootstrap_cpu_init(); vgacon_init(); + serialcon_init(); clock_calibrate(500); print_kernel_banner(); diff --git a/arch/x86_64/serial.c b/arch/x86_64/serial.c index 0c2d666..840de79 100644 --- a/arch/x86_64/serial.c +++ b/arch/x86_64/serial.c @@ -1,30 +1,92 @@ +#include +#include +#include #include #include +#define COM1 0x3F8 +#define COM2 0x2F8 +#define COM3 0x3E8 +#define COM4 0x2E8 + static int transmit_empty(int device) { - return inportb(device + 5) & 0x20; + return inportb(device + 5) & 0x20; +} + +static int serial_received(int device) +{ + return inportb(device + 5) & 0x1; } void serial_send_byte(int device, char out) { - unsigned int _count = 0; - while (!transmit_empty(device)) { - _count++; - } + volatile unsigned int _count = 0; + while (!transmit_empty(device)) { + _count++; + } - outportb(device, out); + outportb(device, out); - while (!transmit_empty(device)) { - _count++; - } + while (!transmit_empty(device)) { + _count++; + } } void serial_putchar(int port, char ch) { - if (ch == '\n') { - serial_send_byte(port, '\r'); - } + if (ch == '\n') { + serial_send_byte(port, '\r'); + } - serial_send_byte(port, ch); + serial_send_byte(port, ch); +} + +void serialcon_write(struct console *con, const char *s, unsigned int len) +{ + for (unsigned int i = 0; i < len; i++) { + serial_putchar(COM1, s[i]); + } +} + +static void init_serial_port(int port) +{ + outportb(port + 1, 0x00); // Disable all interrupts + outportb(port + 3, 0x80); // Enable DLAB (set baud rate divisor) + outportb(port + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud + outportb(port + 1, 0x00); // (hi byte) + outportb(port + 3, 0x03); // 8 bits, no parity, one stop bit + outportb(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + outportb(port + 4, 0x0B); // IRQs enabled, RTS/DSR set + outportb(port + 4, 0x1E); // Set in loopback mode, test the serial chip + outportb(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte) + + volatile unsigned int q = 0; + while (!serial_received(port)) { + q++; + } + + // Check if serial is faulty (i.e: not same byte as sent) + if(inportb(port + 0) != 0xAE) { + panic("serial: port %x init failed", port); + return; + } + + // If serial is not faulty set it in normal operation mode + // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) + outportb(port + 4, 0x0F); + printk("serial: port %x initialised", port); +} + +static struct console serialcon = { + .c_name = "serialcon", + .c_flags = CON_BOOT, + .c_write = serialcon_write, + .c_lock = SPIN_LOCK_INIT, +}; + +void serialcon_init(void) +{ + init_serial_port(COM1); + console_register(&serialcon); } diff --git a/arch/x86_64/vgacon.c b/arch/x86_64/vgacon.c index 5c2a43b..2168817 100644 --- a/arch/x86_64/vgacon.c +++ b/arch/x86_64/vgacon.c @@ -76,7 +76,7 @@ static void handle_ctrl(int c) static void vgacon_putchar(int c) { - serial_putchar(SERIAL_PORT_A, c); + //serial_putchar(SERIAL_PORT_A, c); if (iscntrl(c)) { handle_ctrl(c);