export AS = yasm
+ASFLAGS = -f elf -g dwarf2
export CC = i686-elf-gcc
QEMU = qemu-system-i386 -monitor stdio
export GIT_REV = $(shell git describe --long HEAD)
-CFLAGS = -std=gnu89 -g -Iinclude/arch/x86 -ffreestanding -DGIT_COMMIT=\"$(GIT_REV)\"
+CFLAGS = -std=gnu11 -g -Iinclude/arch/x86 -ffreestanding -DGIT_COMMIT=\"$(GIT_REV)\"
-KERNEL_OBJ = kernel/entry.o kernel/arch/x86/tty/tty.o kernel/drivers/irq/i8259a.o kernel/arch/x86/irq/idt.o kernel/arch/x86/irq/sample_handler.o kernel/drivers/input/ps2.o kernel/kernel.o
+KERNEL_OBJ = kernel/entry.o kernel/arch/x86/tty/tty.o kernel/drivers/irq/i8259a.o kernel/arch/x86/irq/idt.o kernel/arch/x86/irq/interrupt.o kernel/arch/x86/irq/stub.o kernel/drivers/input/ps2.o kernel/kernel.o
BOOTLOADER_OBJ = boot/x86/mbr boot/x86/vbr-fat32 boot/x86/stage3/LOADER.BIN
default: kernel/kernel.elf bootloader
kernel/kernel.bin: ${KERNEL_OBJ} kernel/linker.ld
$(CC) -ffreestanding -nostdlib -o $@ -T kernel/linker.ld ${KERNEL_OBJ}
-kernel/entry.o: kernel/entry.s
- $(AS) -f elf $< -o $@
-
-kernel/arch/x86/irq/sample_handler.o: kernel/arch/x86/irq/sample_handler.c
- $(CC) $(CFLAGS) -mgeneral-regs-only -c $< -o $@
-
kernel/drivers/input/ps2.o: kernel/drivers/input/ps2.c
kernel/kernel.o: kernel/kernel.c
+AS = yasm
+ASFLAGS = -f bin
default: mbr vbr-fat32 stage3/LOADER.BIN
mbr: mbr.s
uint32_t base; /* starting address of IDT */
} __attribute__((packed));
-extern void idt_set_descriptor(struct idt_descriptor *idt, uint8_t vector, uint16_t segment, uint32_t offset, uint8_t type, uint8_t dpl);
+extern void idt_set_descriptor(struct idt_descriptor *idt, uint8_t vector, uint16_t segment, void (*offset)(void), uint8_t type, uint8_t dpl);
extern inline void load_idt(struct idtr idtr);
extern inline void populate_idtr(struct idtr *idtr, struct idt_descriptor *idt);
--- /dev/null
+#ifndef X86_INTERRUPT_H
+#define X86_INTERRUPT_H
+
+extern int register_interrupt(int irq, int (*handler)(void));
+
+#endif
asm volatile ("lidt %0": : "m" (idtr));
}
-void idt_set_descriptor(struct idt_descriptor *idt, uint8_t vector, uint16_t segment, uint32_t offset, uint8_t type, uint8_t dpl)
+void idt_set_descriptor(struct idt_descriptor *idt, uint8_t vector, uint16_t segment, void (*offset)(void), uint8_t type, uint8_t dpl)
{
struct idt_descriptor *descriptor = &idt[vector];
- descriptor->offset_1 = offset & 0xFFFF;
+ descriptor->offset_1 = (uint32_t) offset & 0xFFFF;
descriptor->segsel = segment;
descriptor->unused = 0;
descriptor->type = type;
descriptor->dpl = dpl;
descriptor->present = 1;
- descriptor->offset_2 = offset >> 16;
+ descriptor->offset_2 = (uint32_t) offset >> 16;
}
inline void populate_idtr(struct idtr *idtr, struct idt_descriptor *idt)
--- /dev/null
+#include <irq/idt.h>
+#include <irq/interrupt.h>
+#include <tty.h>
+#include <stddef.h>
+#include <irq/i8259a.h>
+
+/* This table will hold pointers to our interrupt handlers. */
+static int (*int_handler_table[256])(void);
+
+void int_handler(int interrupt)
+{
+ if (int_handler_table[interrupt] == NULL) {
+ kprint("WARNING: Unhandled interrupt ", 0);
+ kprintb(interrupt);
+ kprint(" occurred!\n", 0);
+ } else {
+ int ret = (*int_handler_table[interrupt])();
+ if (ret) {
+ kprint("WARNING: Error while handling interrupt ", 0);
+ kprintb(interrupt);
+ kprint("!\n", 0);
+ }
+ }
+ if (interrupt >= 0x20) {
+ pic_send_eoi(interrupt - 0x20);
+ }
+}
+
+int register_interrupt(int irq, int (*handler)(void))
+{
+ int_handler_table[irq] = handler;
+ if (irq >= 32 && irq < 48) {
+ pic_unmask(irq-32);
+ }
+ return 0;
+}
+++ /dev/null
-#include <tty.h>
-#include <irq/i8259a.h>
-#include <io.h>
-#include <stdint.h>
-#include <input/ps2.h>
-
-int was_released = 0;
-int is_caps = 0;
-
-typedef uint32_t uword_t;
-
-struct interrupt_frame {
- uword_t ip;
- uword_t cs;
- uword_t flags;
-};
-
-struct abort_frame;
-
-__attribute__((interrupt))
-void keyb_handler(struct interrupt_frame *frame)
-{
- pic_send_eoi(1);
- uint8_t scancode = inb(PS2_DATA_PORT);
- if (was_released) {
- was_released = 0;
- return;
- }
-
- if (scancode == 0xf0) {
- was_released = 1;
- uint8_t scancode = inb(PS2_DATA_PORT);
- if (scancode == 0x12) {
- is_caps = 0;
- }
- return;
- } else {
- if (scancode == 0x12) {
- is_caps = 1;
- return;
- }
- if (!is_caps) {
- kprintc(scancodes[scancode], 0);
- } else {
- kprintc(scancodes[scancode] - ('a'-'A'), 0);
- }
- }
-}
-
-
-__attribute__((interrupt))
-void double_fault(struct abort_frame *frame)
-{
- *(volatile uint32_t *) (0xb8000) = 0xcf28cf3a;
-halt:
- asm volatile ("cli; hlt");
- goto halt;
-}
-
--- /dev/null
+; Stubs for interrupt handlers
+
+bits 32
+section .text
+
+extern int_handler
+
+int_common:
+ cld
+ call int_handler
+ add esp, 4
+ popad
+ iretd
+
+%macro INTERRUPT 1
+global int%1
+int_%1:
+ pushad
+ push dword %1
+ jmp int_common
+%endmacro
+
+%assign i 0
+%rep 48
+INTERRUPT i
+%assign i i+1
+%endrep
+
+; Define flat table containing addresses of handlers
+section .rodata
+global _int_handler_table
+_int_handler_table:
+ %macro INT 1
+ dd int_%1
+ %endmacro
+
+ %assign i 0
+ %rep 48
+ INT i
+ %assign i i+1
+ %endrep
#include <io.h>
#include <input/ps2.h>
#include <bitflags.h>
+#include <irq/interrupt.h>
+
+static int was_released = 0, is_caps = 0;
+
+int ps2_keyb_handler()
+{
+ uint8_t scancode = inb(PS2_DATA_PORT);
+ if (was_released) {
+ was_released = 0;
+ return 0;
+ }
+
+ if (scancode == 0xf0) {
+ was_released = 1;
+ uint8_t scancode = inb(PS2_DATA_PORT);
+ if (scancode == 0x12) {
+ is_caps = 0;
+ }
+ return 0;
+ } else {
+ if (scancode == 0x12) {
+ is_caps = 1;
+ return 0;
+ }
+ if (!is_caps) {
+ kprintc(scancodes[scancode], 0);
+ } else {
+ kprintc(scancodes[scancode] - ('a'-'A'), 0);
+ }
+ }
+ return 0;
+}
int ps2_initialize()
{
uint8_t ccb, is_2channel, port_1_test, port_2_test;
-
+
kprint("ps2: Begin initializing PS/2 controller\n", 0);
outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_2_DISABLE);
ps2_input_wait();
CLEAR(ccb, 0);
CLEAR(ccb, 1);
CLEAR(ccb, 6);
-
+
ps2_input_wait();
outb(PS2_CMD_STS_PORT, PS2_CMD_WRITE_CCB);
ps2_input_wait();
kprint("ps2: Controller self test failed, exiting!\n", 0);
return -1;
};
-
+
ps2_input_wait();
outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_2_ENABLE);
ps2_input_wait();
ps2_input_wait();
outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_1_TEST);
ps2_output_wait();
-
+
if (inb(PS2_DATA_PORT) != 0) {
port_1_test = 0;
kprint("ps2: Port 1 test failed!\n", 0);
if (port_1_test) {
uint8_t resp;
-
+
do {
ps2_input_wait();
outb(PS2_DATA_PORT, PS2_DEV_RESET);
ps2_input_wait();
outb(PS2_DATA_PORT, ccb);
+ if (dev_1_test) register_interrupt(33, &ps2_keyb_handler);
+
if (dev_2_test && dev_1_test) return 1;
else return 0;
}
#include <tty.h>
#include <io.h>
#include <irq/idt.h>
+#include <irq/interrupt.h>
#include <irq/i8259a.h>
#include <input/ps2.h>
-extern void double_fault(struct abort_frame *frame);
-extern void keyb_handler(struct interrupt_frame *frame);
struct idt_descriptor idt[256] __attribute__((aligned(0x10)));
struct idtr idtr __attribute__((aligned(0x10)));
+extern void (*_int_handler_table[48])(void);
void kmain(void)
{
kprint("Welcome to Nameless OS!\nRunning revision: ", 0);
kprint(GIT_COMMIT, 0);
kprint("\n", 0);
+ kprint("Preparing IDT...\n", 0);
+ for (int i=0; i<48; i++) {
+ idt_set_descriptor(idt, i, 0x8, _int_handler_table[i], IDT_INTERRUPT_GATE, 0);
+ }
+ kprint("IDT prepared, loading...\n", 0);
+ populate_idtr(&idtr, idt);
+ load_idt(idtr);
+ kprint("Setting up interrupts...\n", 0);
+ pic_init(0x20, 0x28);
+ pic_mask_all();
ps2_success = ps2_initialize();
switch (ps2_success) {
case -1:
case 1:
kprint("Found two working PS/2 devices\n", 0);
}
- kprint("Preparing IDT...\n", 0);
- idt_set_descriptor(idt, 0x8, 0x8, (uint32_t) double_fault, IDT_TRAP_GATE, 0x0);
- idt_set_descriptor(idt, 0x21, 0x8, (uint32_t) keyb_handler, IDT_INTERRUPT_GATE, 0x0);
- kprint("IDT prepared, loading...\n", 0);
- populate_idtr(&idtr, idt);
- load_idt(idtr);
- kprint("IDT loaded, enabling interrupts...\n", 0);
- pic_init(0x20, 0x28);
- pic_mask_all();
- pic_unmask(1);
asm volatile ("sti");
kprint("All done\n", 0);
while(1);