diff --git a/Makefile b/Makefile index 934ab3a..6333f8b 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ LD=x86_64-elf-ld CC=x86_64-elf-gcc run: image.bin - qemu-system-i386 -drive format=raw,file=$< + qemu-system-i386 -drive format=raw,file=$< -serial mon:stdio debug-preboot: image.bin mbr.elf qemu-system-i386 -drive format=raw,file=$< -s -S & @@ -33,7 +33,8 @@ fs.img: kernel.bin tools/mkfs image.bin: mbr.bin fs.img cat $^ >$@ -kernel.bin: kernel.o console.o drivers/vga.o drivers/keyboard.o string.o drivers/ata.o cpu/vectors.o cpu/idt.o +kernel.bin: kernel.o console.o drivers/vga.o drivers/keyboard.o \ + string.o drivers/ata.o cpu/vectors.o cpu/idt.o drivers/uart.o $(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^ %.o: %.c diff --git a/console.c b/console.c index b45f234..1064b89 100644 --- a/console.c +++ b/console.c @@ -1,13 +1,18 @@ #include "console.h" #include "drivers/vga.h" +#include "drivers/uart.h" void printk(const char* msg) { vga_print_string(msg); + for (; *msg; ++msg) { + uartputc(*msg); + } } void panic(const char* msg) { - printk("Kernel panic: "); + printk("\nKernel panic: "); printk(msg); + asm("cli"); while (1) { asm("hlt"); } diff --git a/cpu/idt.c b/cpu/idt.c index da94d89..7b855a2 100644 --- a/cpu/idt.c +++ b/cpu/idt.c @@ -79,8 +79,7 @@ void trap(registers_t *r) { if (r->int_no < ARRLEN(exception_messages)) { msg = exception_messages[r->int_no]; } - printk(msg); - printk("\n"); + panic(msg); } /* Handle the interrupt in a more modular way */ diff --git a/drivers/uart.c b/drivers/uart.c new file mode 100644 index 0000000..613567f --- /dev/null +++ b/drivers/uart.c @@ -0,0 +1,44 @@ +#include "uart.h" +#include "port.h" + +static int uart; + +enum { + COM1 = 0x3f8, +}; + +void uartinit() { + // Turn off the FIFO + port_byte_out(COM1+2, 0); + + // 9600 baud, 8 data bits, 1 stop bit, parity off. + port_byte_out(COM1+3, 0x80); // Unlock divisor + port_byte_out(COM1+0, 115200/9600); + port_byte_out(COM1+1, 0); + port_byte_out(COM1+3, 0x03); // Lock divisor, 8 data bits. + port_byte_out(COM1+4, 0); + port_byte_out(COM1+1, 0x01); // Enable receive interrupts. + + // If status is 0xFF, no serial port. + if(port_byte_in(COM1+5) == 0xFF) + return; + uart = 1; + + // Acknowledge pre-existing interrupt conditions; + // enable interrupts. + port_byte_in(COM1+2); + port_byte_in(COM1+0); +} + +void +uartputc(char c) +{ + int i; + + if (!uart) + return; + for (i = 0; i < 128 && !(port_byte_in(COM1+5) & 0x20); i++) { + asm("pause"); + } + port_byte_out(COM1+0, c); +} diff --git a/drivers/uart.h b/drivers/uart.h new file mode 100644 index 0000000..dfbc8da --- /dev/null +++ b/drivers/uart.h @@ -0,0 +1,4 @@ +#pragma once + +void uartputc(char c); +void uartinit(); diff --git a/kernel.c b/kernel.c index 35cb1af..2cb823c 100644 --- a/kernel.c +++ b/kernel.c @@ -6,9 +6,11 @@ asm(".asciz \"kernel start\""); #include "drivers/vga.h" #include "drivers/ata.h" #include "drivers/misc.h" +#include "drivers/uart.h" void _start() { init_keyboard(); + uartinit(); load_idt(); sti(); char buf[512]; @@ -20,8 +22,7 @@ void _start() { printk(buf); while (1) { - asm("pause"); + asm("hlt"); } - asm("hlt"); qemu_shutdown(); }