Serial output works!

This commit is contained in:
lordtet 2025-07-04 01:47:44 -04:00
parent d6465ade55
commit 62ab718e4d
3 changed files with 37 additions and 21 deletions

View file

@ -9,9 +9,9 @@
#include "io.h" #include "io.h"
#include <stdint.h> #include <stdint.h>
typedef struct SerialState_s { typedef struct serial_ctx_s {
uint16_t port; uint16_t port;
} SerialState_t; } serial_ctx_t;
extern char_writer_t* default_COM; extern char_writer_t* default_COM;
@ -20,7 +20,7 @@ extern char_writer_t* default_COM;
* @param port The serial port number to initialize * @param port The serial port number to initialize
* @return Status code indicating success or failure * @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 * @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 * @brief Receive a single byte from the serial port
* @return The received byte as an 8-bit unsigned integer * @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 * @brief Check if the serial port is ready to send data
* @return Non-zero if ready to send, 0 otherwise * @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 * @brief Send a single byte through the serial port
* @param data The 8-bit data byte to send * @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 #endif

View file

@ -25,7 +25,16 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
default_vga = &vga_writer; default_vga = &vga_writer;
vga_clear_ctx(&vga_ctx); 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); printf(&vga_writer, "Entry eax:%X\n", multiboot_magic);
if(multiboot_magic != 0x2BADB002) { if(multiboot_magic != 0x2BADB002) {
@ -34,7 +43,6 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
} else { } else {
println(&vga_writer, "Multiboot detected! Continuing..."); println(&vga_writer, "Multiboot detected! Continuing...");
} }
printf(&vga_writer, "MEM_LOWER:%X\n", multiboot_info->mem_lower); printf(&vga_writer, "MEM_LOWER:%X\n", multiboot_info->mem_lower);
printf(&vga_writer, "MEM_UPPER:%X\n", multiboot_info->mem_upper); printf(&vga_writer, "MEM_UPPER:%X\n", multiboot_info->mem_upper);
} }

View file

@ -3,11 +3,12 @@
char_writer_t* default_COM = 0; 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 //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. //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: //Sets the baud rate. Quick except on baud rate:
//internal clock for the serial controller is 115200 ticks/sec. Or 115200hz. //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) //(Source:https://wiki.osdev.org/Serial_Ports#Baud_Rate)
//Baud lo byte //Baud lo byte
outb(port, 0x03); outb(ctx->port, 0x03);
//Baud hi byte //Baud hi byte
outb(port+1, 0x00); outb(ctx->port+1, 0x00);
//Again from OSWiki we're going to use their defaults for now. //Again from OSWiki we're going to use their defaults for now.
//DLAB off //DLAB off
//Parity=0(no Parity) //Parity=0(no Parity)
//One stop bit (set to 0) //One stop bit (set to 0)
//Transmit in units of 8 bits //Transmit in units of 8 bits
outb(port+3, 0b00000011); outb(ctx->port+3, 0b00000011);
//FIFO Control register //FIFO Control register
//14 bit threshold for interrupt trigger //14 bit threshold for interrupt trigger
//flush and enable FIFOs. //flush and enable FIFOs.
outb(port+2, 0b11000111); outb(ctx->port+2, 0b11000111);
//Enable IRQs + DTR + RTS //Enable IRQs + DTR + RTS
//Nicely explained here: https://stackoverflow.com/questions/957337/what-is-the-difference-between-dtr-dsr-and-rts-cts-flow-control //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. //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. //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 //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 //Boo womp
return 1; return 1;
} }
//we're good! All set up. Lets put it back into normal operational mode and gtfo. //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; 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 //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;
} }