[uart] Add first pass UART driver and logger
First attempt at a UART driver. I'm not sure it's the most stable. Now that userspace is handling displaying logs, also removed serial and log output support from the kernel.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
#include "clock.h"
|
||||
#include "interrupts.h"
|
||||
#include "io.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
|
||||
uint64_t lapic::s_ticks_per_us = 0;
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#include <util/no_construct.h>
|
||||
|
||||
#include "console.h"
|
||||
#include "printf/printf.h"
|
||||
#include "serial.h"
|
||||
|
||||
|
||||
const char digits[] = "0123456789abcdef";
|
||||
|
||||
static util::no_construct<console> __g_console_storage;
|
||||
console &g_console = __g_console_storage.value;
|
||||
|
||||
|
||||
console::console() :
|
||||
m_serial(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
console::console(serial_port *serial) :
|
||||
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
|
||||
console::set_color(uint8_t fg, uint8_t bg)
|
||||
{
|
||||
if (m_serial) {
|
||||
const char *fgseq = "\x1b[38;5;";
|
||||
while (*fgseq)
|
||||
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)
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
console::puts(const char *message)
|
||||
{
|
||||
size_t n = 0;
|
||||
while (message && *message) {
|
||||
n++;
|
||||
putc(*message++);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
console::putc(char c)
|
||||
{
|
||||
if (m_serial) {
|
||||
if (c == '\n') m_serial->write('\r');
|
||||
m_serial->write(c);
|
||||
}
|
||||
}
|
||||
|
||||
void console::vprintf(const char *fmt, va_list args)
|
||||
{
|
||||
static const unsigned buf_size = 256;
|
||||
char buffer[buf_size];
|
||||
vsnprintf(buffer, buf_size, fmt, args);
|
||||
puts(buffer);
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct kernel_data;
|
||||
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);
|
||||
size_t puts(const char *message);
|
||||
void vprintf(const char *fmt, va_list args);
|
||||
|
||||
inline void printf(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void put_hex(T x, int width = 0, char pad = ' ');
|
||||
|
||||
template <typename T>
|
||||
void put_dec(T x, int width = 0, char pad = ' ');
|
||||
|
||||
void echo();
|
||||
|
||||
static console * get();
|
||||
|
||||
private:
|
||||
serial_port *m_serial;
|
||||
};
|
||||
|
||||
extern console &g_console;
|
||||
inline console * console::get() { return &g_console; }
|
||||
|
||||
|
||||
extern const char digits[];
|
||||
|
||||
template <typename T>
|
||||
void console::put_hex(T x, int width, char pad)
|
||||
{
|
||||
static const int chars = sizeof(x) * 2;
|
||||
char message[chars + 1];
|
||||
|
||||
int len = 1;
|
||||
for (int i = chars - 1; i >= 0; --i) {
|
||||
uint8_t nibble = (x >> (i*4)) & 0xf;
|
||||
if (nibble) len = len > i + 1 ? len : i + 1;
|
||||
message[chars - i - 1] = digits[nibble];
|
||||
}
|
||||
message[chars] = 0;
|
||||
|
||||
if (width > len) for(int i=0; i<(width-len); ++i) putc(pad);
|
||||
puts(message + (chars - len));
|
||||
if (-width > len) for(int i=0; i<(-width-len); ++i) putc(' ');
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void console::put_dec(T x, int width, char pad)
|
||||
{
|
||||
static const int chars = sizeof(x) * 3;
|
||||
char message[chars + 1];
|
||||
char *p = message + chars;
|
||||
int length = 0;
|
||||
*p-- = 0;
|
||||
do {
|
||||
*p-- = digits[x % 10];
|
||||
x /= 10;
|
||||
length += 1;
|
||||
} while (x != 0);
|
||||
|
||||
if (width > length) for(int i=0; i<(width-length); ++i) putc(pad);
|
||||
puts(++p);
|
||||
if (-width > length) for(int i=0; i<(-width-length); ++i) putc(' ');
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "device_manager.h"
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "msr.h"
|
||||
#include "objects/thread.h"
|
||||
#include "objects/vm_area.h"
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "debug.h"
|
||||
#include "gdt.h"
|
||||
#include "objects/process.h"
|
||||
#include "objects/thread.h"
|
||||
|
||||
size_t __counter_syscall_enter = 0;
|
||||
size_t __counter_syscall_sysret = 0;
|
||||
|
||||
void
|
||||
print_regs(const cpu_state ®s)
|
||||
{
|
||||
console *cons = console::get();
|
||||
cpu_data &cpu = current_cpu();
|
||||
|
||||
uint64_t cr2 = 0;
|
||||
__asm__ __volatile__ ("mov %%cr2, %0" : "=r"(cr2));
|
||||
|
||||
uintptr_t cr3 = 0;
|
||||
__asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (cr3) );
|
||||
|
||||
cons->printf(" process: %llx", cpu.process->koid());
|
||||
cons->printf(" thread: %llx\n", cpu.thread->koid());
|
||||
|
||||
print_regL("rax", regs.rax);
|
||||
print_regM("rbx", regs.rbx);
|
||||
print_regR("rcx", regs.rcx);
|
||||
print_regL("rdx", regs.rdx);
|
||||
print_regM("rdi", regs.rdi);
|
||||
print_regR("rsi", regs.rsi);
|
||||
|
||||
cons->puts("\n");
|
||||
print_regL(" r8", regs.r8);
|
||||
print_regM(" r9", regs.r9);
|
||||
print_regR("r10", regs.r10);
|
||||
print_regL("r11", regs.r11);
|
||||
print_regM("r12", regs.r12);
|
||||
print_regR("r13", regs.r13);
|
||||
print_regL("r14", regs.r14);
|
||||
print_regM("r15", regs.r15);
|
||||
|
||||
cons->puts("\n\n");
|
||||
print_regL("rbp", regs.rbp);
|
||||
print_regM("rsp", regs.rsp);
|
||||
print_regR("sp0", cpu.rsp0);
|
||||
|
||||
print_regL("rip", regs.rip);
|
||||
print_regM("cr3", cr3);
|
||||
print_regR("cr2", cr2);
|
||||
|
||||
cons->puts("\n");
|
||||
}
|
||||
|
||||
struct frame
|
||||
{
|
||||
frame *prev;
|
||||
uintptr_t return_addr;
|
||||
};
|
||||
|
||||
void
|
||||
print_stack(const cpu_state ®s)
|
||||
{
|
||||
console *cons = console::get();
|
||||
|
||||
cons->puts("\nStack:\n");
|
||||
uint64_t sp = regs.rsp;
|
||||
while (sp <= regs.rbp) {
|
||||
cons->printf("%016x: %016x\n", sp, *reinterpret_cast<uint64_t *>(sp));
|
||||
sp += sizeof(uint64_t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,3 @@ extern "C" {
|
||||
|
||||
extern size_t __counter_syscall_enter;
|
||||
extern size_t __counter_syscall_sysret;
|
||||
|
||||
void print_regs(const cpu_state ®s);
|
||||
void print_stack(const cpu_state ®s);
|
||||
|
||||
#define print_regL(name, value) cons->printf(" %s: %016lx", name, (value));
|
||||
#define print_regM(name, value) cons->printf(" %s: %016lx", name, (value));
|
||||
#define print_regR(name, value) cons->printf(" %s: %016lx\n", name, (value));
|
||||
|
||||
|
||||
@@ -7,13 +7,11 @@
|
||||
#include "acpi_tables.h"
|
||||
#include "apic.h"
|
||||
#include "clock.h"
|
||||
#include "console.h"
|
||||
#include "device_manager.h"
|
||||
#include "interrupts.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "objects/endpoint.h"
|
||||
#include "serial.h"
|
||||
|
||||
|
||||
static endpoint * const ignore_endpoint = reinterpret_cast<endpoint*>(-1ull);
|
||||
@@ -378,11 +376,6 @@ device_manager::init_drivers()
|
||||
bool
|
||||
device_manager::dispatch_irq(unsigned irq)
|
||||
{
|
||||
if (irq == 4) {
|
||||
g_com1.handle_interrupt();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (irq >= m_irqs.count())
|
||||
return false;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "assert.h"
|
||||
#include "frame_allocator.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
|
||||
using mem::frame_size;
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
#include <util/no_construct.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "gdt.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "tss.h"
|
||||
|
||||
extern "C" void gdt_write(const void *gdt_ptr, uint16_t cs, uint16_t ds, uint16_t tr);
|
||||
@@ -114,6 +113,7 @@ GDT::set_tss(TSS *tss)
|
||||
memcpy(&m_entries[tss_index], &tssd, sizeof(tss_descriptor));
|
||||
}
|
||||
|
||||
/*
|
||||
void
|
||||
GDT::dump(unsigned index) const
|
||||
{
|
||||
@@ -167,3 +167,4 @@ GDT::dump(unsigned index) const
|
||||
(gdt[i].size & 0x60) == 0x40 ? "32" : "16");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "device_manager.h"
|
||||
#include "hpet.h"
|
||||
#include "io.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace {
|
||||
inline uint64_t volatile *capabilities(uint64_t volatile *base) { return base; }
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "cpu.h"
|
||||
#include "idt.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
|
||||
extern "C" {
|
||||
void idt_write(const void *idt_ptr);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "idt.h"
|
||||
#include "interrupts.h"
|
||||
#include "io.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "objects/process.h"
|
||||
#include "printf/printf.h"
|
||||
|
||||
@@ -14,10 +14,8 @@ kernel = module("kernel",
|
||||
"assert.cpp",
|
||||
"boot.s",
|
||||
"clock.cpp",
|
||||
"console.cpp",
|
||||
"cpprt.cpp",
|
||||
"cpu.cpp",
|
||||
"debug.cpp",
|
||||
"debug.s",
|
||||
"device_manager.cpp",
|
||||
"frame_allocator.cpp",
|
||||
@@ -29,7 +27,6 @@ kernel = module("kernel",
|
||||
"interrupts.cpp",
|
||||
"interrupts.s",
|
||||
"io.cpp",
|
||||
"log.cpp",
|
||||
"logger.cpp",
|
||||
"main.cpp",
|
||||
"memory.cpp",
|
||||
@@ -48,7 +45,6 @@ kernel = module("kernel",
|
||||
"pci.cpp",
|
||||
"printf/printf.c",
|
||||
"scheduler.cpp",
|
||||
"serial.cpp",
|
||||
"syscall.cpp.cog",
|
||||
"syscall.h.cog",
|
||||
"syscall.s",
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
#include <j6/signals.h>
|
||||
#include <util/no_construct.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "console.h"
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "objects/system.h"
|
||||
#include "objects/thread.h"
|
||||
|
||||
static uint8_t log_buffer[128 * 1024];
|
||||
|
||||
// The logger is initialized _before_ global constructors are called,
|
||||
// so that we can start log output immediately. Keep its constructor
|
||||
// from being called here so as to not overwrite the previous initialization.
|
||||
static util::no_construct<log::logger> __g_logger_storage;
|
||||
log::logger &g_logger = __g_logger_storage.value;
|
||||
|
||||
static const uint8_t level_colors[] = {0x07, 0x07, 0x0f, 0x0b, 0x09};
|
||||
|
||||
static void
|
||||
output_log(logs area, log::level severity, const char *message)
|
||||
{
|
||||
auto *cons = console::get();
|
||||
cons->set_color(level_colors[static_cast<int>(severity)]);
|
||||
cons->printf("%7s %5s: %s\n",
|
||||
g_logger.area_name(area),
|
||||
g_logger.level_name(severity),
|
||||
message);
|
||||
cons->set_color();
|
||||
}
|
||||
|
||||
// For printf.c
|
||||
extern "C" void putchar_(char c) {}
|
||||
|
||||
void
|
||||
logger_task()
|
||||
{
|
||||
auto *cons = console::get();
|
||||
|
||||
log::info(logs::task, "Starting kernel logger task");
|
||||
g_logger.set_immediate(nullptr);
|
||||
|
||||
thread &self = thread::current();
|
||||
system &sys = system::get();
|
||||
|
||||
size_t buffer_size = 1;
|
||||
uint8_t *buffer = nullptr;
|
||||
|
||||
while (true) {
|
||||
size_t size = g_logger.get_entry(buffer, buffer_size);
|
||||
if (size > buffer_size) {
|
||||
while (size > buffer_size) buffer_size *= 2;
|
||||
kfree(buffer);
|
||||
buffer = reinterpret_cast<uint8_t*>(kalloc(buffer_size));
|
||||
kassert(buffer, "Could not allocate logger task buffer");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(size) {
|
||||
auto *ent = reinterpret_cast<log::logger::entry *>(buffer);
|
||||
buffer[ent->bytes] = 0;
|
||||
|
||||
cons->set_color(level_colors[static_cast<int>(ent->severity)]);
|
||||
cons->printf("%7s %5s: %s\n",
|
||||
g_logger.area_name(ent->area),
|
||||
g_logger.level_name(ent->severity),
|
||||
ent->message);
|
||||
cons->set_color();
|
||||
}
|
||||
|
||||
if (!g_logger.has_log()) {
|
||||
sys.deassert_signal(j6_signal_system_has_log);
|
||||
sys.add_blocked_thread(&self);
|
||||
self.wait_on_signals(j6_signal_system_has_log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void logger_init()
|
||||
{
|
||||
new (&g_logger) log::logger(log_buffer, sizeof(log_buffer), output_log);
|
||||
}
|
||||
|
||||
void logger_clear_immediate()
|
||||
{
|
||||
g_logger.set_immediate(nullptr);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
void logger_init();
|
||||
void logger_clear_immediate();
|
||||
void logger_task();
|
||||
@@ -1,12 +1,25 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <util/constexpr_hash.h>
|
||||
#include <util/no_construct.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "objects/system.h"
|
||||
#include "printf/printf.h"
|
||||
|
||||
static uint8_t log_buffer[128 * 1024];
|
||||
|
||||
// The logger is initialized _before_ global constructors are called,
|
||||
// so that we can start log output immediately. Keep its constructor
|
||||
// from being called here so as to not overwrite the previous initialization.
|
||||
static util::no_construct<log::logger> __g_logger_storage;
|
||||
log::logger &g_logger = __g_logger_storage.value;
|
||||
|
||||
// For printf.c
|
||||
extern "C" void putchar_(char c) {}
|
||||
|
||||
|
||||
namespace log {
|
||||
|
||||
logger *logger::s_log = nullptr;
|
||||
@@ -131,3 +144,9 @@ void fatal(logs area, const char *fmt, ...)
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
|
||||
|
||||
void logger_init()
|
||||
{
|
||||
new (&g_logger) log::logger(log_buffer, sizeof(log_buffer), nullptr);
|
||||
}
|
||||
|
||||
@@ -129,3 +129,5 @@ void fatal(logs area, const char *fmt, ...);
|
||||
extern log::logger &g_logger;
|
||||
|
||||
} // namespace log
|
||||
|
||||
void logger_init();
|
||||
|
||||
@@ -10,22 +10,19 @@
|
||||
#include "assert.h"
|
||||
#include "block_device.h"
|
||||
#include "clock.h"
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "device_manager.h"
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
#include "interrupts.h"
|
||||
#include "io.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "msr.h"
|
||||
#include "objects/channel.h"
|
||||
#include "objects/event.h"
|
||||
#include "objects/thread.h"
|
||||
#include "objects/vm_area.h"
|
||||
#include "scheduler.h"
|
||||
#include "serial.h"
|
||||
#include "syscall.h"
|
||||
#include "sysconf.h"
|
||||
#include "tss.h"
|
||||
@@ -56,18 +53,6 @@ void load_init_server(bootproto::program &program, uintptr_t modules_address);
|
||||
|
||||
unsigned start_aps(lapic &apic, const util::vector<uint8_t> &ids, void *kpml4);
|
||||
|
||||
void
|
||||
init_console()
|
||||
{
|
||||
serial_port *com1 = new (&g_com1) serial_port(COM1);
|
||||
console *cons = new (&g_console) console(com1);
|
||||
|
||||
cons->set_color(0x21, 0x00);
|
||||
cons->puts("jsix OS ");
|
||||
cons->set_color(0x08, 0x00);
|
||||
cons->puts(GIT_VERSION " booting...\n");
|
||||
}
|
||||
|
||||
void
|
||||
run_constructors()
|
||||
{
|
||||
@@ -86,9 +71,7 @@ kernel_main(bootproto::args *args)
|
||||
panic::symbol_table = util::offset_pointer(args->symbol_table, mem::linear_offset);
|
||||
}
|
||||
|
||||
init_console();
|
||||
logger_init();
|
||||
|
||||
cpu_validate();
|
||||
|
||||
extern IDT &g_bsp_idt;
|
||||
@@ -154,31 +137,7 @@ kernel_main(bootproto::args *args)
|
||||
|
||||
sysconf_create();
|
||||
interrupts_enable();
|
||||
g_com1.handle_interrupt();
|
||||
|
||||
/*
|
||||
block_device *disk = devices->get_block_device(0);
|
||||
if (disk) {
|
||||
for (int i=0; i<1; ++i) {
|
||||
uint8_t buf[512];
|
||||
memset(buf, 0, 512);
|
||||
|
||||
kassert(disk->read(0x200, sizeof(buf), buf),
|
||||
"Disk read returned 0");
|
||||
|
||||
console *cons = console::get();
|
||||
uint8_t *p = &buf[0];
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
for (int j = 0; j < 16; ++j) {
|
||||
cons->printf(" %02x", *p++);
|
||||
}
|
||||
cons->putc('\n');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::warn(logs::boot, "No block devices present.");
|
||||
}
|
||||
*/
|
||||
//g_com1.handle_interrupt();
|
||||
|
||||
scheduler *sched = new scheduler {g_num_cpus};
|
||||
scheduler_ready = true;
|
||||
@@ -186,7 +145,6 @@ kernel_main(bootproto::args *args)
|
||||
// Load the init server
|
||||
load_init_server(*args->init, args->modules);
|
||||
|
||||
sched->create_kernel_task(logger_task, scheduler::max_priority/4, true);
|
||||
sched->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "gdt.h"
|
||||
#include "heap_allocator.h"
|
||||
#include "io.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "msr.h"
|
||||
#include "objects/process.h"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <util/pointers.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "objects/thread.h"
|
||||
#include "objects/process.h"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <util/pointers.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "console.h"
|
||||
#include "memory.h"
|
||||
#include "frame_allocator.h"
|
||||
#include "page_table.h"
|
||||
@@ -259,6 +258,7 @@ page_table::free(page_table::level l)
|
||||
void
|
||||
page_table::dump(page_table::level lvl, bool recurse)
|
||||
{
|
||||
/*
|
||||
console *cons = console::get();
|
||||
|
||||
cons->printf("\nLevel %d page table @ %lx:\n", lvl, this);
|
||||
@@ -289,4 +289,5 @@ page_table::dump(page_table::level lvl, bool recurse)
|
||||
next->dump(deeper(lvl), true);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "assert.h"
|
||||
#include "console.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "interrupts.h"
|
||||
#include "pci.h"
|
||||
|
||||
@@ -36,6 +35,7 @@ struct pci_cap_msi64
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*
|
||||
void dump_msi(pci_cap_msi *cap)
|
||||
{
|
||||
auto cons = console::get();
|
||||
@@ -62,6 +62,7 @@ void dump_msi(pci_cap_msi *cap)
|
||||
}
|
||||
cons->putc('\n');
|
||||
};
|
||||
*/
|
||||
|
||||
pci_device::pci_device() :
|
||||
m_base(nullptr),
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
#include "apic.h"
|
||||
#include "assert.h"
|
||||
#include "clock.h"
|
||||
#include "console.h"
|
||||
#include "cpu.h"
|
||||
#include "debug.h"
|
||||
#include "device_manager.h"
|
||||
#include "gdt.h"
|
||||
#include "interrupts.h"
|
||||
#include "io.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "msr.h"
|
||||
#include "objects/channel.h"
|
||||
#include "objects/process.h"
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <util/no_construct.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "interrupts.h"
|
||||
#include "io.h"
|
||||
#include "serial.h"
|
||||
|
||||
// This object is initialized _before_ global constructors are called,
|
||||
// so we don't want it to have global constructors at all, lest it
|
||||
// overwrite the previous initialization.
|
||||
static util::no_construct<serial_port> __g_com1_storage;
|
||||
serial_port &g_com1 = __g_com1_storage.value;
|
||||
|
||||
constexpr size_t fifo_size = 64;
|
||||
|
||||
// register offsets
|
||||
constexpr uint16_t THR = 0; // Write
|
||||
constexpr uint16_t RBR = 0; // Read
|
||||
constexpr uint16_t IER = 1;
|
||||
constexpr uint16_t FCR = 2; // Write
|
||||
constexpr uint16_t IIR = 2; // Read
|
||||
constexpr uint16_t LCR = 3;
|
||||
constexpr uint16_t MCR = 4;
|
||||
constexpr uint16_t LSR = 5;
|
||||
constexpr uint16_t MSR = 6;
|
||||
|
||||
constexpr uint16_t DLL = 0; // DLAB == 1
|
||||
constexpr uint16_t DLH = 1; // DLAB == 1
|
||||
|
||||
uint8_t com1_out_buffer[4096*4];
|
||||
uint8_t com1_in_buffer[512];
|
||||
|
||||
serial_port::serial_port() :
|
||||
m_writing(false),
|
||||
m_port(0)
|
||||
{
|
||||
}
|
||||
|
||||
serial_port::serial_port(uint16_t port) :
|
||||
m_writing(false),
|
||||
m_port(port),
|
||||
m_out_buffer(com1_out_buffer, sizeof(com1_out_buffer)),
|
||||
m_in_buffer(com1_in_buffer, sizeof(com1_in_buffer))
|
||||
{
|
||||
outb(port + IER, 0x00); // Disable all interrupts
|
||||
outb(port + LCR, 0x80); // Enable the Divisor Latch Access Bit
|
||||
outb(port + DLL, 0x01); // Divisor low byte: 1 (115200 baud)
|
||||
outb(port + DLH, 0x00); // Divisor high byte
|
||||
outb(port + LCR, 0x03); // 8-N-1, diable DLAB
|
||||
outb(port + FCR, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger
|
||||
outb(port + MCR, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable)
|
||||
outb(port + IER, 0x03); // Enable interrupts
|
||||
|
||||
// Clear out pending interrupts
|
||||
handle_interrupt();
|
||||
}
|
||||
|
||||
inline bool read_ready(uint16_t port) { return (inb(port + LSR) & 0x01) != 0; }
|
||||
inline bool write_ready(uint16_t port) { return (inb(port + LSR) & 0x20) != 0; }
|
||||
|
||||
void
|
||||
serial_port::handle_interrupt()
|
||||
{
|
||||
interrupts_disable();
|
||||
uint8_t iir = inb(m_port + IIR);
|
||||
|
||||
while ((iir & 1) == 0) {
|
||||
uint8_t reg = 0;
|
||||
switch ((iir>>1) & 0x3) {
|
||||
case 0: // Modem status change
|
||||
reg = inb(m_port + MSR);
|
||||
handle_error(MSR, reg);
|
||||
break;
|
||||
|
||||
case 1: // Transmit buffer empty
|
||||
do_write();
|
||||
break;
|
||||
|
||||
case 2: // Received data available
|
||||
do_read();
|
||||
break;
|
||||
|
||||
case 3: // Line status change
|
||||
reg = inb(m_port + LSR);
|
||||
handle_error(LSR, reg);
|
||||
break;
|
||||
}
|
||||
|
||||
iir = inb(m_port + IIR);
|
||||
}
|
||||
interrupts_enable();
|
||||
}
|
||||
|
||||
void
|
||||
serial_port::do_read()
|
||||
{
|
||||
size_t used = 0;
|
||||
uint8_t *data = nullptr;
|
||||
size_t avail = m_in_buffer.reserve(fifo_size, reinterpret_cast<void**>(&data));
|
||||
|
||||
while (used < avail && read_ready(m_port)) {
|
||||
*data++ = inb(m_port);
|
||||
used++;
|
||||
}
|
||||
|
||||
m_in_buffer.commit(used);
|
||||
}
|
||||
|
||||
void
|
||||
serial_port::do_write()
|
||||
{
|
||||
uint8_t *data = nullptr;
|
||||
uint8_t tmp[fifo_size];
|
||||
|
||||
size_t n = m_out_buffer.get_block(reinterpret_cast<void**>(&data));
|
||||
|
||||
m_writing = (n > 0);
|
||||
if (!m_writing)
|
||||
return;
|
||||
|
||||
if (n > fifo_size)
|
||||
n = fifo_size;
|
||||
|
||||
memcpy(tmp, data, n);
|
||||
m_out_buffer.consume(n);
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
outb(m_port, data[i]);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
serial_port::handle_error(uint16_t reg, uint8_t value)
|
||||
{
|
||||
kassert(false, "serial line error");
|
||||
}
|
||||
|
||||
char
|
||||
serial_port::read()
|
||||
{
|
||||
uint8_t *data = nullptr;
|
||||
size_t n = m_in_buffer.get_block(reinterpret_cast<void**>(&data));
|
||||
if (!n) return 0;
|
||||
char c = *data;
|
||||
m_in_buffer.consume(1);
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
serial_port::write(char c)
|
||||
{
|
||||
uint8_t *data = nullptr;
|
||||
size_t avail = m_out_buffer.reserve(1, reinterpret_cast<void**>(&data));
|
||||
if (!avail)
|
||||
return;
|
||||
*data = c;
|
||||
m_out_buffer.commit(1);
|
||||
|
||||
if (!m_writing)
|
||||
do_write();
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
/// \file serial.h
|
||||
/// Declarations related to serial ports.
|
||||
#include <stdint.h>
|
||||
|
||||
#include <util/bip_buffer.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();
|
||||
|
||||
void handle_interrupt();
|
||||
|
||||
private:
|
||||
bool m_writing;
|
||||
uint16_t m_port;
|
||||
util::bip_buffer m_out_buffer;
|
||||
util::bip_buffer m_in_buffer;
|
||||
|
||||
void do_read();
|
||||
void do_write();
|
||||
void handle_error(uint16_t reg, uint8_t value);
|
||||
};
|
||||
|
||||
extern serial_port &g_com1;
|
||||
@@ -3,15 +3,17 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "syscall.h"
|
||||
|
||||
extern "C" {
|
||||
void syscall_invalid(uint64_t call);
|
||||
}
|
||||
|
||||
size_t __counter_syscall_enter = 0;
|
||||
size_t __counter_syscall_sysret = 0;
|
||||
|
||||
/*[[[cog code generation
|
||||
from definitions.context import Context
|
||||
|
||||
@@ -27,12 +29,7 @@ uintptr_t syscall_registry[num_syscalls] __attribute__((section(".syscall_regist
|
||||
void
|
||||
syscall_invalid(uint64_t call)
|
||||
{
|
||||
console *cons = console::get();
|
||||
cons->set_color(9);
|
||||
cons->printf("\nReceived unknown syscall: %02x\n", call);
|
||||
|
||||
cons->set_color();
|
||||
_halt();
|
||||
log::warn(logs::syscall, "Received unknown syscall: %02x\n", call);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <j6/errors.h>
|
||||
#include <j6/types.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "objects/endpoint.h"
|
||||
#include "syscalls/helpers.h"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <util/vector.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "objects/thread.h"
|
||||
#include "syscalls/helpers.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <j6/errors.h>
|
||||
#include <j6/types.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "objects/process.h"
|
||||
#include "syscalls/helpers.h"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "cpu.h"
|
||||
#include "device_manager.h"
|
||||
#include "frame_allocator.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "objects/endpoint.h"
|
||||
#include "objects/thread.h"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <j6/errors.h>
|
||||
#include <j6/types.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "objects/process.h"
|
||||
#include "objects/thread.h"
|
||||
#include "syscalls/helpers.h"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <j6/signals.h>
|
||||
#include <j6/types.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "objects/process.h"
|
||||
#include "objects/vm_area.h"
|
||||
#include "syscalls/helpers.h"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "assert.h"
|
||||
#include "cpu.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "objects/vm_area.h"
|
||||
#include "tss.h"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "assert.h"
|
||||
#include "frame_allocator.h"
|
||||
#include "log.h"
|
||||
#include "logger.h"
|
||||
#include "memory.h"
|
||||
#include "objects/process.h"
|
||||
#include "objects/thread.h"
|
||||
|
||||
Reference in New Issue
Block a user