diff options
author | dzwdz | 2021-08-09 22:20:32 +0200 |
---|---|---|
committer | dzwdz | 2021-08-09 22:20:32 +0200 |
commit | 4165209842edf74bd786f6525a58b7b0bb9790d5 (patch) | |
tree | b1e578f3fd55f2ea759cda5cfa95309ea10b4974 /src/kernel/arch | |
parent | ab1843f5de80752ba40fb1ea5075eb7e3dad8171 (diff) |
implement serial output
Diffstat (limited to 'src/kernel/arch')
-rw-r--r-- | src/kernel/arch/i386/tty/serial.c | 44 | ||||
-rw-r--r-- | src/kernel/arch/i386/tty/serial.h | 5 | ||||
-rw-r--r-- | src/kernel/arch/i386/tty/tty.c | 3 |
3 files changed, 52 insertions, 0 deletions
diff --git a/src/kernel/arch/i386/tty/serial.c b/src/kernel/arch/i386/tty/serial.c new file mode 100644 index 0000000..bf55c41 --- /dev/null +++ b/src/kernel/arch/i386/tty/serial.c @@ -0,0 +1,44 @@ +#include <kernel/arch/i386/tty/serial.h> +#include <stdint.h> + +const int COM1 = 0x3f8; + +// TODO move to some header file +inline void port_outb(uint16_t port, uint8_t val) { + asm volatile("outb %0, %1" : : "a" (val), "Nd" (port)); +} + +inline uint8_t port_inb(uint16_t port) { + uint8_t val; + asm volatile("inb %1, %0" : "=a" (val) : "Nd" (port)); + return val; +} + +void serial_init() { + // see https://www.sci.muni.cz/docs/pc/serport.txt + + port_outb(COM1 + 1, 0x00); // disable interrupts, we won't be using them + + // set baud rate divisor + port_outb(COM1 + 3, 0b10000000); // enable DLAB + port_outb(COM1 + 0, 0x01); // divisor = 1 (low byte) + port_outb(COM1 + 1, 0x00); // (high byte) + + port_outb(COM1 + 3, 0b00000011); // 8 bits, no parity, one stop bit + port_outb(COM1 + 2, 0b11000111); // enable FIFO with 14-bit trigger level (???) + port_outb(COM1 + 4, 0b00001111); // enable everything in the MCR + + /* the example on the OSDEV wiki does a selftest of the serial connection + * i don't really see the point as long as i'm not using it for input? + * if i start using serial for input, TODO selftest */ +} + +void serial_putchar(char c) { + while ((port_inb(COM1 + 5) & 0x20) == 0); // wait for THRE + port_outb(COM1, c); +} + +void serial_write(const char *buf, size_t len) { + for (size_t i = 0; i < len; i++) + serial_putchar(buf[i]); +} diff --git a/src/kernel/arch/i386/tty/serial.h b/src/kernel/arch/i386/tty/serial.h new file mode 100644 index 0000000..ac7131b --- /dev/null +++ b/src/kernel/arch/i386/tty/serial.h @@ -0,0 +1,5 @@ +#pragma once +#include <stddef.h> + +void serial_write(const char *buf, size_t len); +void serial_init(); diff --git a/src/kernel/arch/i386/tty/tty.c b/src/kernel/arch/i386/tty/tty.c index 670dd5b..300bbcc 100644 --- a/src/kernel/arch/i386/tty/tty.c +++ b/src/kernel/arch/i386/tty/tty.c @@ -1,10 +1,13 @@ +#include <kernel/arch/i386/tty/serial.h> #include <kernel/arch/i386/tty/vga.h> #include <kernel/arch/log.h> void tty_init() { vga_clear(); + serial_init(); } void tty_write(const char *buf, size_t len) { vga_write(buf, len); + serial_write(buf, len); } |