summaryrefslogtreecommitdiff
path: root/arch/i386/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/pic.c67
-rw-r--r--arch/i386/kernel/syscall.c42
-rw-r--r--arch/i386/kernel/tty.c88
3 files changed, 197 insertions, 0 deletions
diff --git a/arch/i386/kernel/pic.c b/arch/i386/kernel/pic.c
new file mode 100644
index 0000000..69a0785
--- /dev/null
+++ b/arch/i386/kernel/pic.c
@@ -0,0 +1,67 @@
+#include <kernel/pic.h>
+
+void pic_eoi(unsigned char irq) {
+ if (irq >= 8)
+ outb(PIC2_COMMAND, 0x20);
+ outb(PIC1_COMMAND, 0x20);
+}
+
+void pic_remap(void) {
+ unsigned char a1 = inb(PIC1_DATA);
+ unsigned char a2 = inb(PIC2_DATA);
+
+ outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
+ outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
+ outb(PIC1_DATA, PIC1);
+ outb(PIC2_DATA, PIC2);
+ outb(PIC1_DATA, 4);
+ outb(PIC2_DATA, 2);
+ outb(PIC1_DATA, ICW4_8086);
+ outb(PIC2_DATA, ICW4_8086);
+ outb(PIC1_DATA, a1);
+ outb(PIC2_DATA, a2);
+}
+
+static uint16_t __pic_get_irq_reg(int ocw3) {
+ outb(PIC1_COMMAND, ocw3);
+ outb(PIC2_COMMAND, ocw3);
+ return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
+}
+
+uint16_t pic_get_irr(void) {
+ return __pic_get_irq_reg(PIC_READ_IRR);
+}
+
+uint16_t pic_get_isr(void) {
+ return __pic_get_irq_reg(PIC_READ_ISR);
+}
+
+void irq_set_mask(uint8_t irq) {
+ uint16_t port;
+ uint8_t data;
+
+ if (irq < 8) {
+ port = PIC1_DATA;
+ } else {
+ port = PIC2_DATA;
+ irq -= 8;
+ }
+
+ data = inb(port) | (1 << irq);
+ outb(port, data);
+}
+
+void irq_clear_mask(uint8_t irq) {
+ uint16_t port;
+ uint8_t data;
+
+ if (irq < 8) {
+ port = PIC1_DATA;
+ } else {
+ port = PIC2_DATA;
+ irq -= 8;
+ }
+
+ data = inb(port) & ~(1 << irq);
+ outb(port, data);
+}
diff --git a/arch/i386/kernel/syscall.c b/arch/i386/kernel/syscall.c
new file mode 100644
index 0000000..570f0de
--- /dev/null
+++ b/arch/i386/kernel/syscall.c
@@ -0,0 +1,42 @@
+#include <kernel/syscall.h>
+#include <kernel/io.h>
+#include <stddef.h>
+
+void *(*syscall_handlers[30])(struct isr_frame *frame);
+
+void syscall_dispatch(struct isr_frame *frame) {
+ if (syscall_handlers[frame->eax] != NULL)
+ syscall_handlers[frame->eax](frame);
+ else
+ kprintf("Error: Invalid system call number: %d\n", frame->eax);
+ __asm__ volatile("cli;hlt");
+}
+
+void register_syscall(void *handler(struct isr_frame*), int num) {
+ syscall_handlers[num] = handler;
+}
+
+void sys_stop(struct isr_frame *frame) {
+ kprintf("SYSTEM CALL: STOP\n");
+ halt_catch_fire(frame);
+}
+
+void sys_status(struct isr_frame *frame) {
+ kprintf("SYSTEM CALL: STATUS\n");
+ dump_reg(frame);
+}
+
+void dump_reg(struct isr_frame *frame) {
+ kprintf("Registers at interrupt:\n");
+ kprintf("\tEAX = %x\n", frame->eax);
+ kprintf("\tEBX = %x\n", frame->ebx);
+ kprintf("\tECX = %x\n", frame->ecx);
+ kprintf("\tEDX = %x\n", frame->edx);
+ kprintf("\tESI = %x\n", frame->esi);
+ kprintf("\tEDI = %x\n", frame->edi);
+ kprintf("\tESP = %x\n", frame->esp);
+ kprintf("\tEBP = %x\n", frame->ebp);
+ kprintf("\tEIP = %x\n", frame->eip);
+ kprintf("\tEFLAGS = %x\n", frame->eflags);
+ kprintf("Current code selector: %d\n", frame->cs);
+}
diff --git a/arch/i386/kernel/tty.c b/arch/i386/kernel/tty.c
new file mode 100644
index 0000000..f929408
--- /dev/null
+++ b/arch/i386/kernel/tty.c
@@ -0,0 +1,88 @@
+#include <kernel/vga.h>
+#include <kernel/tty.h>
+#include <kernel/string.h>
+#include <stddef.h>
+#include <stdint.h>
+
+static const size_t VGA_WIDTH = 80;
+static const size_t VGA_HEIGHT = 25;
+//static uint16_t *const VGA_MEMORY = (uint16_t*)0xC03FF000;
+static uint16_t *const VGA_MEMORY = (uint16_t*)0xB8000;
+
+static size_t terminal_row;
+static size_t terminal_column;
+static uint8_t terminal_color;
+static uint16_t *terminal_buffer;
+
+void tty_init(void) {
+ terminal_row = 0;
+ terminal_column = 0;
+ terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
+ terminal_buffer = VGA_MEMORY;
+ for (size_t y = 0; y < VGA_HEIGHT; y++) {
+ for (size_t x = 0; x < VGA_WIDTH; x++) {
+ const size_t index = y * VGA_WIDTH + x;
+ terminal_buffer[index] = vga_entry(' ', terminal_color);
+ }
+ }
+}
+
+void tty_setcolor(uint8_t color) {
+ terminal_color = color;
+}
+
+void tty_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) {
+ const size_t index = y * VGA_WIDTH + x;
+ terminal_buffer[index] = vga_entry(c, color);
+}
+
+void terminal_scroll(void) {
+ for (size_t i = 0; i < VGA_HEIGHT; i++) {
+ for (size_t j = 0; j < VGA_WIDTH; j++)
+ terminal_buffer[i * VGA_WIDTH + j] = terminal_buffer[(i+1) * VGA_WIDTH + j];
+ }
+}
+
+void tty_putchar(char c) {
+ unsigned char uc;
+
+ uc = c;
+ switch (uc) {
+ case '\n':
+ terminal_column = 0;
+ if (++terminal_row == VGA_HEIGHT) {
+ terminal_row--;
+ terminal_scroll();
+ }
+ break;
+ case '\t':
+ terminal_column += 4;
+ if (++terminal_column == VGA_WIDTH) {
+ terminal_column = 4;
+ if (++terminal_row == VGA_HEIGHT) {
+ terminal_row--;
+ terminal_scroll();
+ }
+ }
+ break;
+ default:
+ tty_putentryat(uc, terminal_color, terminal_column, terminal_row);
+ if (++terminal_column == VGA_WIDTH) {
+ terminal_column = 0;
+ if (++terminal_row == VGA_HEIGHT) {
+ terminal_row--;
+ terminal_scroll();
+ }
+ }
+ break;
+ }
+}
+
+void tty_write(const char *data, size_t size) {
+ for (size_t i = 0; i < size; i++)
+ tty_putchar(data[i]);
+}
+
+void tty_writestring(const char *data) {
+ tty_write(data, strlen(data));
+}