From 184f1fc5d716729b210af0127f2e5b4b00f094a8 Mon Sep 17 00:00:00 2001 From: ChUrl Date: Sat, 16 Jul 2022 00:57:17 +0200 Subject: [PATCH] add simple serial output --- c_os/user/devices/SerialOut.cc | 51 ++++++++++++++++++++++++++++++++++ c_os/user/devices/SerialOut.h | 28 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 c_os/user/devices/SerialOut.cc create mode 100644 c_os/user/devices/SerialOut.h diff --git a/c_os/user/devices/SerialOut.cc b/c_os/user/devices/SerialOut.cc new file mode 100644 index 0000000..13e20da --- /dev/null +++ b/c_os/user/devices/SerialOut.cc @@ -0,0 +1,51 @@ +#include "user/devices/SerialOut.h" +#include "kernel/Globals.h" + +int SerialOut::init() const { + // NOTE: I could add different ports for every register but this was easier as it's that way on OSDev + com1.outb(1, 0x00); // Disable all interrupts + com1.outb(3, 0x80); // Enable DLAB (set baud rate divisor) + com1.outb(0x03); // Set divisor to 3 (lo byte) 38400 baud + com1.outb(1, 0x00); // (hi byte) + com1.outb(3, 0x03); // 8 bits, no parity, one stop bit + com1.outb(2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + com1.outb(4, 0x0B); // IRQs enabled, RTS/DSR set + com1.outb(4, 0x1E); // Set in loopback mode, test the serial chip + com1.outb(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 (com1.inb() != 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) + com1.outb(4, 0x0F); + return 0; +} + +int SerialOut::serial_received() { + return com1.inb(5) & 1; +} + +int SerialOut::is_transmit_empty() { + return com1.inb(5) & 0x20; +} + +char SerialOut::read() { + while (serial_received() == 0) {} + return com1.inb(); +} + +void SerialOut::write(char a) { + while (is_transmit_empty() == 0) {} + com1.outb(a); +} + +void SerialOut::write(char* a) { + char* current = a; + do { + this->write(*current); + current = current + 1; + } while (*current != '\0'); +} diff --git a/c_os/user/devices/SerialOut.h b/c_os/user/devices/SerialOut.h new file mode 100644 index 0000000..92939b6 --- /dev/null +++ b/c_os/user/devices/SerialOut.h @@ -0,0 +1,28 @@ +#ifndef __SerialOut_Include_H_ +#define __SerialOut_Include_H_ + +#include "kernel/interrupts/ISR.h" +#include "kernel/IOport.h" + +// NOTE: I took this code from https://wiki.osdev.org/Serial_Ports + +class SerialOut { +private: + const IOport com1; + + SerialOut(const SerialOut& copy) = delete; + + int serial_received(); + int is_transmit_empty(); + +public: + SerialOut() : com1(0x3f8) {} + + int init() const; + + char read(); + void write(char a); + void write(char* a); +}; + +#endif