Files
Espresso/drivers/serio.c

89 lines
2.0 KiB
C
Raw Permalink Normal View History

2025-10-20 21:57:30 -05:00
/*
Driver for serial output.
Mostly useful for debug output because QEMU allows the redirection of serial output to either stdio or a file on the host computer.
*/
#include <types.h>
#include <port_io.h>
#include <string.h>
#include <drivers/serio.h>
#define COM1_IO_ADDR 0x3F8
#define COM2_IO_ADDR 0x2F8
#define COM1_IRQ 0x4
#define COM2_IRQ 0x3
#define COM1_LCR (COM1_IO_ADDR + 3)
#define COM2_LCR (COM2_IO_ADDR + 3)
#define BAUD 57600
#define DIVISOR 2
int serial_init(void)
{
/* The following is taken from https://wiki.osdev.org/Serial_Ports */
outb(COM1_IO_ADDR + 1, 0x00); // Disable all interrupts
outb(COM1_IO_ADDR + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(COM1_IO_ADDR + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
outb(COM1_IO_ADDR + 1, 0x00); // (hi byte)
outb(COM1_IO_ADDR + 3, 0x03); // 8 bits, no parity, one stop bit
outb(COM1_IO_ADDR + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
outb(COM1_IO_ADDR + 4, 0x0B); // IRQs enabled, RTS/DSR set
outb(COM1_IO_ADDR + 4, 0x1E); // Set in loopback mode, test the serial chip
outb(COM1_IO_ADDR + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if(inb(COM1_IO_ADDR + 0) != 0xAE)
{
return 1;
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
outb(COM1_IO_ADDR + 4, 0x0F);
return 0;
}
static int is_transmit_empty(void)
{
return inb(COM1_IO_ADDR + 5) & 0x20;
}
static int serial_received(void)
{
return inb(COM1_IO_ADDR + 5) & 1;
}
void serial_write(char a)
{
while (is_transmit_empty() == 0);
outb(COM1_IO_ADDR, a);
}
void serial_puts(const char* s)
{
for (int i = 0; i < (int) strlen(s); i++)
{
serial_write(s[i]);
}
}
char serial_read(void)
{
while (serial_received() == 0);
return inb(COM1_IO_ADDR);
}
bool use_serial(void)
{
return true;
}