From 34aad175e9c90dcd9f49dc72b0d0f230d508a994 Mon Sep 17 00:00:00 2001 From: Ali Mashtizadeh Date: Sun, 13 Jul 2014 13:04:14 -0700 Subject: [PATCH] Serial support --- sys/SConscript | 1 + sys/dev/console.c | 22 ++++++++++ sys/dev/x86/sercons.c | 96 +++++++++++++++++++++++++++++++++++++++++++ sys/dev/x86/sercons.h | 8 ++++ 4 files changed, 127 insertions(+) diff --git a/sys/SConscript b/sys/SConscript index e6d0edd..b2eca15 100644 --- a/sys/SConscript +++ b/sys/SConscript @@ -20,6 +20,7 @@ src_amd64 = [ "amd64/ioapic.c", "amd64/irq.c", "dev/x86/debugcons.c", + "dev/x86/sercons.c", "dev/x86/vgacons.c", "dev/x86/ide.c", ] diff --git a/sys/dev/console.c b/sys/dev/console.c index c0eee2a..f66b34d 100644 --- a/sys/dev/console.c +++ b/sys/dev/console.c @@ -3,21 +3,42 @@ #include "console.h" #include "x86/vgacons.h" +#include "x86/sercons.h" #include "x86/debugcons.h" +/* + * Initialize console devices for debugging purposes. At this point interrupts + * and device state is not initialized. + */ void Console_Init() { VGA_Init(); + Serial_Init(); DebugConsole_Init(); Console_Puts("Castor Operating System\n"); } +/* + * Setup interrupts and input devices that may not be ready + */ +void +Console_LateInit() +{ + Serial_LateInit(); +} + +void +Console_Getc(char ch) +{ +} + void Console_Putc(char ch) { VGA_Putc(ch); + Serial_Putc(ch); DebugConsole_Putc(ch); } @@ -25,6 +46,7 @@ void Console_Puts(const char *str) { VGA_Puts(str); + Serial_Puts(str); DebugConsole_Puts(str); } diff --git a/sys/dev/x86/sercons.c b/sys/dev/x86/sercons.c index e69de29..b6bf95d 100644 --- a/sys/dev/x86/sercons.c +++ b/sys/dev/x86/sercons.c @@ -0,0 +1,96 @@ + +#include + +#include +#include + +#include "ioport.h" +#include "sercons.h" + +#define COM1_BASE 0x3F8 +#define COM2_BASE 0x2F8 +#define COM3_BASE 0x3E8 +#define COM4_BASE 0x2E8 + +#define COM1_IRQ 4 +#define COM2_IRQ 3 +#define COM3_IRQ 4 +#define COM4_IRQ 3 + +// Inputs +#define UART_OFFSET_DATA 0 /* Data Register */ +#define UART_OFFSET_IER 1 /* Interrupt Enable Register */ +#define UART_OFFSET_IIR 2 /* Interrupt Identification & FIFO Control */ +#define UART_OFFSET_LCR 3 /* Line Control Register */ +#define UART_LCR_DLAB 0x80 +#define UART_LCR_8N1 0x03 +#define UART_OFFSET_MCR 4 /* Modem Control Register */ +#define UART_OFFSET_LSR 5 /* Line Status Register */ +#define UART_OFFSET_MSR 6 /* Modem Status Register */ +#define UART_OFFSET_SR 7 /* Scratch Register */ + +#define UART_OFFSET_DIVLO 0 /* Divisors DLAB == 1 */ +#define UART_OFFSET_DIVHI 1 + +IRQHandler handler; +uint16_t base; +uint8_t irq; + +void Serial_Init(void) +{ + base = COM1_BASE; + irq = COM1_IRQ; + + // Disable interrupts + outb(base + UART_OFFSET_IER, 0); + + // Enable DLAB + outb(base + UART_OFFSET_LCR, UART_LCR_DLAB); + outb(base + UART_OFFSET_DIVLO, 1); // 115200 Baud + outb(base + UART_OFFSET_DIVLO, 0); + outb(base + UART_OFFSET_LCR, UART_LCR_8N1); + + // Enable interrupts + outb(base + UART_OFFSET_IIR, 0xC7); + outb(base + UART_OFFSET_MCR, 0x0B); +} + +void Serial_LateInit(void) +{ + handler.irq = irq; + handler.cb = &Serial_Interrupt; + handler.arg = NULL; + + IRQ_Register(irq, &handler); +} + +void Serial_Interrupt(void *arg) +{ + kprintf("Serial interrupt!\n"); +} + +char Serial_Getc() +{ + while ((inb(base + UART_OFFSET_LSR) & 0x01) == 0) + { + // Timeout! + } + return inb(base + UART_OFFSET_DATA); +} + +void Serial_Putc(char ch) +{ + while ((inb(base + UART_OFFSET_LSR) & 0x20) == 0) + { + // Timeout! + } + outb(base + UART_OFFSET_DATA, ch); +} + +void Serial_Puts(const char *str) +{ + const char *p = str; + while (*p != '\0') + Serial_Putc(*p++); +} + diff --git a/sys/dev/x86/sercons.h b/sys/dev/x86/sercons.h index e69de29..d676d41 100644 --- a/sys/dev/x86/sercons.h +++ b/sys/dev/x86/sercons.h @@ -0,0 +1,8 @@ + +void Serial_Init(void); +void Serial_LateInit(void); +void Serial_Interrupt(void *arg); +char Serial_Getc(); +void Serial_Putc(char ch); +void Serial_Puts(const char *str); +