From e4200782ac9017bbe7c3f90b2668e7d513785158 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Thu, 8 Nov 2018 21:11:45 +0100 Subject: [PATCH] Add Serial driver --- core/irq_handler.c | 7 ++++++ core/main.c | 4 ++++ drivers/serial.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/serial.h | 6 +++++ 4 files changed, 72 insertions(+) create mode 100644 drivers/serial.c create mode 100644 drivers/serial.h diff --git a/core/irq_handler.c b/core/irq_handler.c index 971f699..2d8dda4 100644 --- a/core/irq_handler.c +++ b/core/irq_handler.c @@ -3,6 +3,7 @@ #include "irq.h" #include "keyboard.h" #include "pic.h" +#include "serial.h" #include "vga.h" // Need GCC > 6 @@ -20,3 +21,9 @@ __attribute__((interrupt)) void timer_handler(struct interrupt_frame *frame) printIntDetails(timeCnt++, RED, BLACK, 20, VGA_HEIGHT - 1); (void)frame; } + +__attribute__((interrupt)) void serial_handler(struct interrupt_frame *frame) +{ + EOIIrq(IRQ_COM1); + serial_do_irq((int)frame); +} diff --git a/core/main.c b/core/main.c index b1ac5da..131c35f 100644 --- a/core/main.c +++ b/core/main.c @@ -8,6 +8,7 @@ #include "mem.h" #include "multiboot.h" #include "pit.h" +#include "serial.h" #include "stdarg.h" #include "vga.h" @@ -61,6 +62,9 @@ void kmain(unsigned long magic, unsigned long addr) exceptionSetRoutine(EXCEPTION_DOUBLE_FAULT, print_handler); // Enabling the HW interrupts asm volatile("sti\n"); + printf("Init Serial\n"); + initSerial(115200); + int count = 0; while (1) { printIntDetails(count++, GREEN, BLACK, 0, VGA_HEIGHT - 1); diff --git a/drivers/serial.c b/drivers/serial.c new file mode 100644 index 0000000..b398b71 --- /dev/null +++ b/drivers/serial.c @@ -0,0 +1,55 @@ +#include "serial.h" +#include "io.h" +#include "irq.h" + +#define PORT 0x3f8 /* COM1 */ +#define SERIAL_MAX_SPEED 115200 + +/* The type of parity. */ +#define UART_NO_PARITY 0x00 +#define UART_ODD_PARITY 0x08 +#define UART_EVEN_PARITY 0x18 + +/* The type of word length. */ +#define UART_5BITS_WORD 0x00 +#define UART_6BITS_WORD 0x01 +#define UART_7BITS_WORD 0x02 +#define UART_8BITS_WORD 0x03 + +/* The type of the length of stop bit. */ +#define UART_1_STOP_BIT 0x00 +#define UART_2_STOP_BITS 0x04 + +void initSerial(int speed) +{ + unsigned short div = SERIAL_MAX_SPEED / speed; + outb(PORT + 1, 0x00); // Disable all interrupts + outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(PORT + 0, div & 0xFF); // Set divisor lo byte + outb(PORT + 1, div >> 8); // Set divisor hi byte + outb(PORT + 3, + UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT); // 8 bits, no parity, one stop bit + outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold + outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set +} + +int isTransmitEmpty() +{ + return inb(PORT + 5) & 0x20; +} + +void writeSerial(char a) +{ + while (isTransmitEmpty() == 0) + ; + + outb(PORT, a); +} + +void serial_do_irq(int level){ + if(level == IRQ_COM1){ + char c = inb(PORT + 5) & 1; + writeSerial(c); + } + return; +} diff --git a/drivers/serial.h b/drivers/serial.h new file mode 100644 index 0000000..0389b71 --- /dev/null +++ b/drivers/serial.h @@ -0,0 +1,6 @@ +#pragma once + + +void initSerial(int speed); +void writeSerial(char a); +void serial_do_irq(int level);