Add beginning basic serial driver

This commit is contained in:
Justin C. Miller
2018-05-03 00:08:22 -07:00
parent 59700b07db
commit d9fe457b44
6 changed files with 128 additions and 38 deletions

View File

@@ -1,5 +1,5 @@
#include "console.h"
#include "io.h"
#include "serial.h"
const char digits[] = "0123456789abcdef";
console g_console;
@@ -212,25 +212,28 @@ console_get_screen_out(const font &f, const screen &s, void *scratch, size_t len
}
static bool
serial_ready()
{
return (inb(COM1 + 5) & 0x20) != 0;
}
static void
serial_write(char c) {
while (!serial_ready());
outb(COM1, c);
}
console::console() :
m_screen(nullptr)
m_screen(nullptr),
m_serial(nullptr)
{
}
console::console(serial_port *serial) :
m_screen(nullptr),
m_serial(serial)
{
if (m_serial) {
const char *fgseq = "\x1b[2J";
while (*fgseq)
serial_write(*fgseq++);
m_serial->write(*fgseq++);
}
}
void
console::echo()
{
putc(m_serial->read());
}
void
@@ -239,32 +242,40 @@ console::set_color(uint8_t fg, uint8_t bg)
if (m_screen)
m_screen->set_color(fg, bg);
if (m_serial) {
const char *fgseq = "\x1b[38;5;";
while (*fgseq)
serial_write(*fgseq++);
if (fg >= 100) serial_write('0' + (fg/100));
if (fg >= 10) serial_write('0' + (fg/10) % 10);
serial_write('0' + fg % 10);
serial_write('m');
m_serial->write(*fgseq++);
if (fg >= 100) m_serial->write('0' + (fg/100));
if (fg >= 10) m_serial->write('0' + (fg/10) % 10);
m_serial->write('0' + fg % 10);
m_serial->write('m');
const char *bgseq = "\x1b[48;5;";
while (*bgseq)
serial_write(*bgseq++);
if (bg >= 100) serial_write('0' + (bg/100));
if (bg >= 10) serial_write('0' + (bg/10) % 10);
serial_write('0' + bg % 10);
serial_write('m');
m_serial->write(*bgseq++);
if (bg >= 100) m_serial->write('0' + (bg/100));
if (bg >= 10) m_serial->write('0' + (bg/10) % 10);
m_serial->write('0' + bg % 10);
m_serial->write('m');
}
}
void
console::puts(const char *message)
{
while (message && *message) {
char c = *message++;
while (message && *message)
putc(*message++);
}
void
console::putc(char c)
{
if (m_screen) m_screen->putc(c);
serial_write(c);
if (c == '\n') serial_write('\r');
if (m_serial) {
m_serial->write(c);
if (c == '\r') m_serial->write('\n');
}
}

View File

@@ -6,14 +6,17 @@
#include "screen.h"
class console_out_screen;
class serial_port;
class console
{
public:
console();
console(serial_port *serial);
void set_color(uint8_t fg = 7, uint8_t bg = 0);
void putc(char c);
void puts(const char *message);
void vprintf(const char *fmt, va_list args);
@@ -33,10 +36,13 @@ public:
void set_screen(console_out_screen *out) { m_screen = out; }
void echo();
static console * get();
private:
console_out_screen *m_screen;
serial_port *m_serial;
};
extern console g_console;

View File

@@ -130,7 +130,7 @@ set_idt_entry(uint8_t i, uint64_t addr, uint16_t selector, uint8_t flags)
g_idt_table[i].reserved = 0;
}
void
static void
disable_legacy_pic()
{
@@ -154,6 +154,13 @@ disable_legacy_pic()
outb(PIC2+1, 0x02); io_wait();
}
static void
enable_serial_interrupts()
{
uint8_t ier = inb(COM1+1);
outb(COM1+1, ier | 0x1);
}
void
interrupts_init()
{
@@ -186,6 +193,7 @@ interrupts_init()
idt_write();
disable_legacy_pic();
enable_serial_interrupts();
log::info(logs::interrupt, "Interrupts enabled.");
}
@@ -288,6 +296,11 @@ irq_handler(registers regs)
cons->set_color();
break;
case 4:
// TODO: move this to a real serial driver
cons->echo();
break;
default:
cons->set_color(11);
cons->printf("\nReceived IRQ interrupt: %d (vec %d)\n",

View File

@@ -7,11 +7,13 @@
#include "device_manager.h"
#include "font.h"
#include "interrupts.h"
#include "io.h"
#include "kernel_data.h"
#include "log.h"
#include "memory.h"
#include "memory_pages.h"
#include "screen.h"
#include "serial.h"
extern "C" {
void do_the_set_registers(popcorn_data *header);
@@ -41,7 +43,9 @@ load_console(const popcorn_data *header)
void
kernel_main(popcorn_data *header)
{
console *cons = new (&g_console) console();
serial_port *com1 = new (&g_com1) serial_port(COM1);
console *cons = new (&g_console) console(com1);
cons->set_color(0x21, 0x00);
cons->puts("Popcorn OS ");
cons->set_color(0x08, 0x00);

31
src/kernel/serial.cpp Normal file
View File

@@ -0,0 +1,31 @@
#include "io.h"
#include "serial.h"
serial_port g_com1;
serial_port::serial_port() :
m_port(0)
{
}
serial_port::serial_port(uint16_t port) :
m_port(port)
{
}
bool serial_port::read_ready() { return (inb(m_port + 5) & 0x01) != 0; }
bool serial_port::write_ready() { return (inb(m_port + 5) & 0x20) != 0; }
char
serial_port::read() {
while (!read_ready());
return inb(m_port);
}
void
serial_port::write(char c) {
while (!write_ready());
outb(m_port, c);
}

25
src/kernel/serial.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
/// \file serial.h
/// Declarations related to serial ports.
#include <stdint.h>
class serial_port
{
public:
/// Constructor.
/// \arg port The IO address of the serial port
serial_port(uint16_t port);
serial_port();
void write(char c);
char read();
private:
uint16_t m_port;
bool read_ready();
bool write_ready();
};
extern serial_port g_com1;