diff --git a/scripts/run.mk b/scripts/run.mk index 31e557c..5117606 100644 --- a/scripts/run.mk +++ b/scripts/run.mk @@ -4,5 +4,5 @@ run: quark run-qemu .PHONY: run-qemu run-qemu: @echo -e $(ARROW) "Running on qemu..." - @qemu-system-i386 $(BUILD_DIR)/quark.iso + @qemu-system-i386 $(BUILD_DIR)/quark.iso -serial stdio @echo -e $(ARROW) "Finished run" diff --git a/src/kernel/drivers/serial.c b/src/kernel/drivers/serial.c new file mode 100644 index 0000000..12f3099 --- /dev/null +++ b/src/kernel/drivers/serial.c @@ -0,0 +1,42 @@ +#include "serial.h" +#include "../arch/i686/io.h" + +int serial_initialize(uint8_t port){ + i686_outb(port + 1, 0x00); // Disable all interrupts + i686_outb(port + 3, 0x80); // Enable DLAB + i686_outb(port + 0, 0x03); // Divisor high byte (38400 baud) + i686_outb(port + 1, 0x00); // Divisor low byte + i686_outb(port + 3, 0x03); // 8 bits, no parity, one stop bit + i686_outb(port + 2, 0xC7); // Enable FIFO + i686_outb(port + 4, 0x0B); // IRQs enabled, RTS/DSR set + + i686_outb(port + 4, 0x1E); // Loopback mode, test serial chip + i686_outb(port + 0, 0xAE); // Test serial chip sending 0xAE + + if(i686_inb(port + 0) != 0xAE){ // Not working + return 1; + } + + i686_outb(port + 4, 0x0F); // Normal operation mode + return 0; +} + +static int serial_received(uint8_t port){ + return i686_inb(port + 5) & 0x01; +} + +char serial_read(uint8_t port){ + while(!serial_received(port)); + + return i686_inb(port); +} + +static int serial_tx_empty(uint8_t port){ + return i686_inb(port + 5) & 0x20; +} + +void serial_write(uint8_t port, char c){ + while(!serial_tx_empty(port)); + + return i686_outb(port, c); +} diff --git a/src/kernel/drivers/serial.h b/src/kernel/drivers/serial.h new file mode 100644 index 0000000..9b93c0e --- /dev/null +++ b/src/kernel/drivers/serial.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#define COM1 (uint8_t)0x3F8 +#define COM2 (uint8_t)0x2F8 +#define COM3 (uint8_t)0x3E8 +#define COM4 (uint8_t)0x2E8 +#define COM5 (uint8_t)0x5F8 +#define COM6 (uint8_t)0x4F8 +#define COM7 (uint8_t)0x5E8 +#define COM8 (uint8_t)0x4E8 + +int serial_initialize(uint8_t port); +char serial_read(uint8_t port); +void serial_write(uint8_t port, char c); diff --git a/src/kernel/main.c b/src/kernel/main.c index fbe0f93..3a974f8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -3,6 +3,7 @@ #include "hal/hal.h" #include "drivers/timer.h" #include "drivers/keyboard.h" +#include "drivers/serial.h" void __attribute__((cdecl)) kmain(uint64_t magic, uint64_t addr){ hal_initialize(); @@ -10,5 +11,6 @@ void __attribute__((cdecl)) kmain(uint64_t magic, uint64_t addr){ keyboard_initialize(); clear_screen(); + printf("Serial status: %i\n", serial_initialize(COM1)); for(;;); } diff --git a/src/kernel/shell.c b/src/kernel/shell.c index 935bf30..a3b4c22 100644 --- a/src/kernel/shell.c +++ b/src/kernel/shell.c @@ -2,6 +2,7 @@ #include "lib/stdio.h" #include "lib/string.h" #include "lib/memory.h" +#include "drivers/serial.h" int shell_run(char *cmd){ int ret = 0; @@ -22,6 +23,13 @@ int shell_run(char *cmd){ else if(!strcmp(cmd, "clear")){ clear_screen(); } + else if(!strcmp(cmd, "serial")){ + serial_write(COM1, 'H'); + serial_write(COM1, 'E'); + serial_write(COM1, 'L'); + serial_write(COM1, 'L'); + serial_write(COM1, 'O'); + } else{ printf("SHELL: Unknown command \"%s\"\n", cmd); ret = 127;