From 62ab718e4dd6094cd100c5a231b25c114e757a9c Mon Sep 17 00:00:00 2001 From: lordtet Date: Fri, 4 Jul 2025 01:47:44 -0400 Subject: [PATCH] Serial output works! --- include/serial.h | 12 ++++++------ src/main.c | 10 +++++++++- src/serial.c | 36 ++++++++++++++++++++++-------------- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/include/serial.h b/include/serial.h index 6b044ad..f85526e 100644 --- a/include/serial.h +++ b/include/serial.h @@ -9,9 +9,9 @@ #include "io.h" #include -typedef struct SerialState_s { +typedef struct serial_ctx_s { uint16_t port; -} SerialState_t; +} serial_ctx_t; extern char_writer_t* default_COM; @@ -20,7 +20,7 @@ extern char_writer_t* default_COM; * @param port The serial port number to initialize * @return Status code indicating success or failure */ -int serial_init(uint16_t port); +int serial_init(serial_ctx_t* ctx); /** * @brief Check if there is pending data to receive on the serial port @@ -32,19 +32,19 @@ int serial_recv_pending(); * @brief Receive a single byte from the serial port * @return The received byte as an 8-bit unsigned integer */ -uint8_t serial_recv8(uint16_t port); +uint8_t serial_recv8(serial_ctx_t* ctx); /** * @brief Check if the serial port is ready to send data * @return Non-zero if ready to send, 0 otherwise */ -int serial_send_pending(uint16_t port); +int serial_send_pending(serial_ctx_t* ctx); /** * @brief Send a single byte through the serial port * @param data The 8-bit data byte to send */ -int serial_send8(uint16_t port, char data); +int serial_send8(void* ctx, char data); #endif diff --git a/src/main.c b/src/main.c index 7ca8b88..3cbfbf2 100644 --- a/src/main.c +++ b/src/main.c @@ -25,7 +25,16 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info) default_vga = &vga_writer; vga_clear_ctx(&vga_ctx); + //Serial prep + serial_ctx_t serial_ctx; + serial_ctx.port = COM1; + char_writer_t serial_writer; + serial_writer.ctx = &serial_ctx; + serial_writer.putChar = serial_send8; + default_COM = &serial_writer; + serial_init(&serial_ctx); + printf(&vga_writer, "Entry eax:%X\n", multiboot_magic); if(multiboot_magic != 0x2BADB002) { @@ -34,7 +43,6 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info) } else { println(&vga_writer, "Multiboot detected! Continuing..."); } - printf(&vga_writer, "MEM_LOWER:%X\n", multiboot_info->mem_lower); printf(&vga_writer, "MEM_UPPER:%X\n", multiboot_info->mem_upper); } diff --git a/src/serial.c b/src/serial.c index 3d21ee1..37ac718 100644 --- a/src/serial.c +++ b/src/serial.c @@ -3,11 +3,12 @@ char_writer_t* default_COM = 0; -int serial_init(uint16_t port) { +int serial_init(serial_ctx_t* ctx) { + //disable interrupts when messing with it - outb(port + 1, 0x00); + outb(ctx->port + 1, 0x00); //set the dlab latch in order to make the baud rate accessible. In binary for clarity. - outb(port + 3, 0b10000000); + outb(ctx->port + 3, 0b10000000); //Sets the baud rate. Quick except on baud rate: //internal clock for the serial controller is 115200 ticks/sec. Or 115200hz. @@ -18,44 +19,51 @@ int serial_init(uint16_t port) { //(Source:https://wiki.osdev.org/Serial_Ports#Baud_Rate) //Baud lo byte - outb(port, 0x03); + outb(ctx->port, 0x03); //Baud hi byte - outb(port+1, 0x00); + outb(ctx->port+1, 0x00); //Again from OSWiki we're going to use their defaults for now. //DLAB off //Parity=0(no Parity) //One stop bit (set to 0) //Transmit in units of 8 bits - outb(port+3, 0b00000011); + outb(ctx->port+3, 0b00000011); //FIFO Control register //14 bit threshold for interrupt trigger //flush and enable FIFOs. - outb(port+2, 0b11000111); + outb(ctx->port+2, 0b11000111); //Enable IRQs + DTR + RTS //Nicely explained here: https://stackoverflow.com/questions/957337/what-is-the-difference-between-dtr-dsr-and-rts-cts-flow-control //In the future, this will be referred to 0x0B. - outb(port+4, 0b00001011); + outb(ctx->port+4, 0b00001011); //done! Let's test our chip. put it in loopback mode. - outb(port+4, 0x1E); + outb(ctx->port+4, 0x1E); //Lets try sending C4 (boom!) to test it - outb(port, 0xC4); + outb(ctx->port, 0xC4); - if(inb(port) != 0xC4) { + if(inb(ctx->port) != 0xC4) { //Boo womp return 1; } //we're good! All set up. Lets put it back into normal operational mode and gtfo. - outb(port+4, 0x0B); + outb(ctx->port+4, 0x0B); return 0; } -int serial_send_pending(uint16_t port) { +int serial_send_pending(serial_ctx_t* ctx) { //Bit 5 of the line status register has our output queue, essentially - return !(inb(port + 5) & 0x20); + return !(inb(ctx->port + 5) & 0x20); +} + +int serial_send8(void* ctx, char out) { + serial_ctx_t* serial_ctx = (serial_ctx_t*) ctx; + while(serial_send_pending(serial_ctx)); + outb(serial_ctx->port, out); + return 0; }