mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
Add beginning basic serial driver
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "io.h"
|
#include "serial.h"
|
||||||
|
|
||||||
const char digits[] = "0123456789abcdef";
|
const char digits[] = "0123456789abcdef";
|
||||||
console g_console;
|
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() :
|
console::console() :
|
||||||
m_screen(nullptr)
|
m_screen(nullptr),
|
||||||
|
m_serial(nullptr)
|
||||||
{
|
{
|
||||||
const char *fgseq = "\x1b[2J";
|
}
|
||||||
while (*fgseq)
|
|
||||||
serial_write(*fgseq++);
|
console::console(serial_port *serial) :
|
||||||
|
m_screen(nullptr),
|
||||||
|
m_serial(serial)
|
||||||
|
{
|
||||||
|
if (m_serial) {
|
||||||
|
const char *fgseq = "\x1b[2J";
|
||||||
|
while (*fgseq)
|
||||||
|
m_serial->write(*fgseq++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console::echo()
|
||||||
|
{
|
||||||
|
putc(m_serial->read());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -239,32 +242,40 @@ console::set_color(uint8_t fg, uint8_t bg)
|
|||||||
if (m_screen)
|
if (m_screen)
|
||||||
m_screen->set_color(fg, bg);
|
m_screen->set_color(fg, bg);
|
||||||
|
|
||||||
const char *fgseq = "\x1b[38;5;";
|
if (m_serial) {
|
||||||
while (*fgseq)
|
const char *fgseq = "\x1b[38;5;";
|
||||||
serial_write(*fgseq++);
|
while (*fgseq)
|
||||||
if (fg >= 100) serial_write('0' + (fg/100));
|
m_serial->write(*fgseq++);
|
||||||
if (fg >= 10) serial_write('0' + (fg/10) % 10);
|
if (fg >= 100) m_serial->write('0' + (fg/100));
|
||||||
serial_write('0' + fg % 10);
|
if (fg >= 10) m_serial->write('0' + (fg/10) % 10);
|
||||||
serial_write('m');
|
m_serial->write('0' + fg % 10);
|
||||||
|
m_serial->write('m');
|
||||||
|
|
||||||
const char *bgseq = "\x1b[48;5;";
|
const char *bgseq = "\x1b[48;5;";
|
||||||
while (*bgseq)
|
while (*bgseq)
|
||||||
serial_write(*bgseq++);
|
m_serial->write(*bgseq++);
|
||||||
if (bg >= 100) serial_write('0' + (bg/100));
|
if (bg >= 100) m_serial->write('0' + (bg/100));
|
||||||
if (bg >= 10) serial_write('0' + (bg/10) % 10);
|
if (bg >= 10) m_serial->write('0' + (bg/10) % 10);
|
||||||
serial_write('0' + bg % 10);
|
m_serial->write('0' + bg % 10);
|
||||||
serial_write('m');
|
m_serial->write('m');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
console::puts(const char *message)
|
console::puts(const char *message)
|
||||||
{
|
{
|
||||||
while (message && *message) {
|
while (message && *message)
|
||||||
char c = *message++;
|
putc(*message++);
|
||||||
if (m_screen) m_screen->putc(c);
|
}
|
||||||
|
|
||||||
serial_write(c);
|
void
|
||||||
if (c == '\n') serial_write('\r');
|
console::putc(char c)
|
||||||
|
{
|
||||||
|
if (m_screen) m_screen->putc(c);
|
||||||
|
|
||||||
|
if (m_serial) {
|
||||||
|
m_serial->write(c);
|
||||||
|
if (c == '\r') m_serial->write('\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,17 @@
|
|||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
class console_out_screen;
|
class console_out_screen;
|
||||||
|
class serial_port;
|
||||||
|
|
||||||
class console
|
class console
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
console();
|
console();
|
||||||
|
console(serial_port *serial);
|
||||||
|
|
||||||
void set_color(uint8_t fg = 7, uint8_t bg = 0);
|
void set_color(uint8_t fg = 7, uint8_t bg = 0);
|
||||||
|
|
||||||
|
void putc(char c);
|
||||||
void puts(const char *message);
|
void puts(const char *message);
|
||||||
void vprintf(const char *fmt, va_list args);
|
void vprintf(const char *fmt, va_list args);
|
||||||
|
|
||||||
@@ -33,10 +36,13 @@ public:
|
|||||||
|
|
||||||
void set_screen(console_out_screen *out) { m_screen = out; }
|
void set_screen(console_out_screen *out) { m_screen = out; }
|
||||||
|
|
||||||
|
void echo();
|
||||||
|
|
||||||
static console * get();
|
static console * get();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
console_out_screen *m_screen;
|
console_out_screen *m_screen;
|
||||||
|
serial_port *m_serial;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern console g_console;
|
extern console g_console;
|
||||||
|
|||||||
@@ -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;
|
g_idt_table[i].reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
disable_legacy_pic()
|
disable_legacy_pic()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -154,6 +154,13 @@ disable_legacy_pic()
|
|||||||
outb(PIC2+1, 0x02); io_wait();
|
outb(PIC2+1, 0x02); io_wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enable_serial_interrupts()
|
||||||
|
{
|
||||||
|
uint8_t ier = inb(COM1+1);
|
||||||
|
outb(COM1+1, ier | 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
interrupts_init()
|
interrupts_init()
|
||||||
{
|
{
|
||||||
@@ -186,6 +193,7 @@ interrupts_init()
|
|||||||
|
|
||||||
idt_write();
|
idt_write();
|
||||||
disable_legacy_pic();
|
disable_legacy_pic();
|
||||||
|
enable_serial_interrupts();
|
||||||
|
|
||||||
log::info(logs::interrupt, "Interrupts enabled.");
|
log::info(logs::interrupt, "Interrupts enabled.");
|
||||||
}
|
}
|
||||||
@@ -288,6 +296,11 @@ irq_handler(registers regs)
|
|||||||
cons->set_color();
|
cons->set_color();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
// TODO: move this to a real serial driver
|
||||||
|
cons->echo();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cons->set_color(11);
|
cons->set_color(11);
|
||||||
cons->printf("\nReceived IRQ interrupt: %d (vec %d)\n",
|
cons->printf("\nReceived IRQ interrupt: %d (vec %d)\n",
|
||||||
|
|||||||
@@ -7,11 +7,13 @@
|
|||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "interrupts.h"
|
#include "interrupts.h"
|
||||||
|
#include "io.h"
|
||||||
#include "kernel_data.h"
|
#include "kernel_data.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "memory_pages.h"
|
#include "memory_pages.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void do_the_set_registers(popcorn_data *header);
|
void do_the_set_registers(popcorn_data *header);
|
||||||
@@ -41,7 +43,9 @@ load_console(const popcorn_data *header)
|
|||||||
void
|
void
|
||||||
kernel_main(popcorn_data *header)
|
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->set_color(0x21, 0x00);
|
||||||
cons->puts("Popcorn OS ");
|
cons->puts("Popcorn OS ");
|
||||||
cons->set_color(0x08, 0x00);
|
cons->set_color(0x08, 0x00);
|
||||||
|
|||||||
31
src/kernel/serial.cpp
Normal file
31
src/kernel/serial.cpp
Normal 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
25
src/kernel/serial.h
Normal 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;
|
||||||
Reference in New Issue
Block a user