aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/idt-as.S6
-rw-r--r--kernel/idt.c23
-rw-r--r--kernel/include/gdt.h4
-rw-r--r--kernel/include/idt.h23
-rw-r--r--kernel/include/irq.h21
-rw-r--r--kernel/include/isr.h46
-rw-r--r--kernel/irq-as.S139
-rw-r--r--kernel/irq.c84
-rw-r--r--kernel/isr-as.S213
-rw-r--r--kernel/isr.c48
10 files changed, 605 insertions, 2 deletions
diff --git a/kernel/idt-as.S b/kernel/idt-as.S
new file mode 100644
index 0000000..d1ab7e2
--- /dev/null
+++ b/kernel/idt-as.S
@@ -0,0 +1,6 @@
+ .global idt_flush
+ .type idt_flush, @function
+idt_flush: # prototype: void idt_flush(uint32)
+ movl 4(%esp), %eax
+ lidt (%eax)
+ ret
diff --git a/kernel/idt.c b/kernel/idt.c
new file mode 100644
index 0000000..e1ff72f
--- /dev/null
+++ b/kernel/idt.c
@@ -0,0 +1,23 @@
+#include <stdint.h>
+#include <string.h>
+#include "idt.h"
+
+void idt_set_gate(uint8_t idx, uint32_t base, uint16_t sel, uint8_t flags)
+{
+ idt[idx].base_lo = base & 0xFFFF;
+ idt[idx].base_hi = base >> 16;
+ idt[idx].sel = sel;
+ idt[idx].zero = 0;
+ idt[idx].flags = flags;
+}
+
+void idt_init(void)
+{
+ printf("idt_init()");
+ idt_pt.limit = sizeof(idt) - 1;
+ idt_pt.base = (uint32_t)&idt;
+
+ memset(&idt, 0, sizeof(idt));
+
+ idt_flush((uint32_t)&idt_pt);
+}
diff --git a/kernel/include/gdt.h b/kernel/include/gdt.h
index e93c92a..4cf7c4f 100644
--- a/kernel/include/gdt.h
+++ b/kernel/include/gdt.h
@@ -10,7 +10,7 @@ struct gdt_entry {
} __attribute__((packed));
struct gdt_ptr {
- uint8_t limit;
+ uint16_t limit;
uint32_t base;
} __attribute__((packed));
@@ -18,6 +18,6 @@ struct gdt_entry gdt[3];
struct gdt_ptr gp;
/* assembly */
-extern void gdt_flush(struct gdt_ptr*);
+extern void gdt_flush(uint32_t);
void gdt_init(void);
diff --git a/kernel/include/idt.h b/kernel/include/idt.h
new file mode 100644
index 0000000..8041025
--- /dev/null
+++ b/kernel/include/idt.h
@@ -0,0 +1,23 @@
+#include <stdint.h>
+
+struct idt_entry {
+ uint16_t base_lo;
+ uint16_t sel;
+ uint8_t zero;
+ uint8_t flags;
+ uint16_t base_hi;
+} __attribute__((packed));
+
+struct idt_ptr {
+ uint16_t limit;
+ uint32_t base;
+};
+
+struct idt_entry idt[0x100];
+struct idt_ptr idt_pt;
+
+void idt_init(void);
+
+extern void idt_flush(uint32_t);
+
+void idt_set_gate(uint8_t idx, uint32_t base, uint16_t sel, uint8_t flags);
diff --git a/kernel/include/irq.h b/kernel/include/irq.h
new file mode 100644
index 0000000..1dcbc17
--- /dev/null
+++ b/kernel/include/irq.h
@@ -0,0 +1,21 @@
+extern void _irq0(void);
+extern void _irq1(void);
+extern void _irq2(void);
+extern void _irq3(void);
+extern void _irq4(void);
+extern void _irq5(void);
+extern void _irq6(void);
+extern void _irq7(void);
+extern void _irq8(void);
+extern void _irq9(void);
+extern void _irq10(void);
+extern void _irq11(void);
+extern void _irq12(void);
+extern void _irq13(void);
+extern void _irq14(void);
+extern void _irq15(void);
+
+struct regs_t;
+
+void irq_set_handler(int irq, void (*handler)(struct regs_t*));
+void irq_init(void);
diff --git a/kernel/include/isr.h b/kernel/include/isr.h
new file mode 100644
index 0000000..d3543af
--- /dev/null
+++ b/kernel/include/isr.h
@@ -0,0 +1,46 @@
+#include <stdint.h>
+
+/* these are all implemented in isr-as.S */
+extern void _isr0(void);
+extern void _isr1(void);
+extern void _isr2(void);
+extern void _isr3(void);
+extern void _isr4(void);
+extern void _isr5(void);
+extern void _isr6(void);
+extern void _isr7(void);
+extern void _isr8(void);
+extern void _isr9(void);
+extern void _isr10(void);
+extern void _isr11(void);
+extern void _isr12(void);
+extern void _isr13(void);
+extern void _isr14(void);
+extern void _isr15(void);
+extern void _isr16(void);
+extern void _isr17(void);
+extern void _isr18(void);
+extern void _isr19(void);
+extern void _isr20(void);
+extern void _isr21(void);
+extern void _isr22(void);
+extern void _isr23(void);
+extern void _isr24(void);
+extern void _isr25(void);
+extern void _isr26(void);
+extern void _isr27(void);
+extern void _isr28(void);
+extern void _isr29(void);
+extern void _isr30(void);
+extern void _isr31(void);
+
+/* installs all the ISR's */
+void isr_init(void);
+
+/* This defines what the stack looks like after an ISR was running */
+struct regs_t {
+ uint32_t gs, fs, es, ds; /* pushed the segs last */
+ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */
+ uint32_t int_no, err_code; /* our 'push byte #' and ecodes do this */
+ uint32_t eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */
+};
diff --git a/kernel/irq-as.S b/kernel/irq-as.S
new file mode 100644
index 0000000..12de4b6
--- /dev/null
+++ b/kernel/irq-as.S
@@ -0,0 +1,139 @@
+ .extern irq_handler
+
+irq_stub:
+
+ pusha
+ push %ds
+ push %es
+ push %fs
+ push %gs
+ mov $0x10, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %esp, %eax
+ push %eax
+ mov $irq_handler, %eax
+ call *%eax
+ pop %eax
+ pop %gs
+ pop %fs
+ pop %es
+ pop %ds
+ popa
+ addl $8, %esp
+ iret
+
+ .global _irq0
+ .global _irq1
+ .global _irq2
+ .global _irq3
+ .global _irq4
+ .global _irq5
+ .global _irq6
+ .global _irq7
+ .global _irq8
+ .global _irq9
+ .global _irq10
+ .global _irq11
+ .global _irq12
+ .global _irq13
+ .global _irq14
+ .global _irq15
+
+_irq0:
+ cli
+ push $0
+ push $32
+ jmp irq_stub
+
+_irq1:
+ cli
+ push $0
+ push $33
+ jmp irq_stub
+
+_irq2:
+ cli
+ push $0
+ push $34
+ jmp irq_stub
+
+_irq3:
+ cli
+ push $0
+ push $35
+ jmp irq_stub
+
+_irq4:
+ cli
+ push $0
+ push $36
+ jmp irq_stub
+
+_irq5:
+ cli
+ push $0
+ push $37
+ jmp irq_stub
+
+_irq6:
+ cli
+ push $0
+ push $38
+ jmp irq_stub
+
+_irq7:
+ cli
+ push $0
+ push $39
+ jmp irq_stub
+
+_irq8:
+ cli
+ push $0
+ push $40
+ jmp irq_stub
+
+_irq9:
+ cli
+ push $0
+ push $41
+ jmp irq_stub
+
+_irq10:
+ cli
+ push $0
+ push $42
+ jmp irq_stub
+
+_irq11:
+ cli
+ push $0
+ push $43
+ jmp irq_stub
+
+_irq12:
+ cli
+ push $0
+ push $44
+ jmp irq_stub
+
+_irq13:
+ cli
+ push $0
+ push $45
+ jmp irq_stub
+
+_irq14:
+ cli
+ push $0
+ push $46
+ jmp irq_stub
+
+_irq15:
+ cli
+ push $0
+ push $47
+ jmp irq_stub
diff --git a/kernel/irq.c b/kernel/irq.c
new file mode 100644
index 0000000..5f0a3f5
--- /dev/null
+++ b/kernel/irq.c
@@ -0,0 +1,84 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include "idt.h"
+#include "io.h"
+#include "irq.h"
+#include "isr.h"
+
+static void *irq_callbacks[16] = { NULL };
+
+void irq_set_handler(int irq, void (*handler)(struct regs_t*))
+{
+ if(irq < 16 && irq >= 0)
+ irq_callbacks[irq] = handler;
+}
+
+void irq_reset_handler(int irq)
+{
+ if(irq < 16 && irq >= 0)
+ irq_callbacks[irq] = NULL;
+}
+
+void irq_remap(void)
+{
+ outb(0x20, 0x11);
+ outb(0xA0, 0x11);
+ outb(0x21, 0x20);
+ outb(0xA1, 0x28);
+ outb(0x21, 0x04);
+ outb(0xA1, 0x02);
+ outb(0x21, 0x01);
+ outb(0xA1, 0x01);
+ outb(0x21, 0x0);
+ outb(0xA1, 0x0);
+}
+
+void irq_init(void)
+{
+ irq_remap();
+
+ printf("irq_init()");
+
+ idt_set_gate(32, (uint32_t)_irq0, 0x08, 0x8E);
+ idt_set_gate(33, (uint32_t)_irq1, 0x08, 0x8E);
+ idt_set_gate(34, (uint32_t)_irq2, 0x08, 0x8E);
+ idt_set_gate(35, (uint32_t)_irq3, 0x08, 0x8E);
+ idt_set_gate(36, (uint32_t)_irq4, 0x08, 0x8E);
+ idt_set_gate(37, (uint32_t)_irq5, 0x08, 0x8E);
+ idt_set_gate(38, (uint32_t)_irq6, 0x08, 0x8E);
+ idt_set_gate(39, (uint32_t)_irq7, 0x08, 0x8E);
+ idt_set_gate(40, (uint32_t)_irq8, 0x08, 0x8E);
+ idt_set_gate(41, (uint32_t)_irq9, 0x08, 0x8E);
+ idt_set_gate(42, (uint32_t)_irq10, 0x08, 0x8E);
+ idt_set_gate(43, (uint32_t)_irq11, 0x08, 0x8E);
+ idt_set_gate(44, (uint32_t)_irq12, 0x08, 0x8E);
+ idt_set_gate(45, (uint32_t)_irq13, 0x08, 0x8E);
+ idt_set_gate(46, (uint32_t)_irq14, 0x08, 0x8E);
+ idt_set_gate(47, (uint32_t)_irq15, 0x08, 0x8E);
+}
+
+void irq_handler(struct regs_t *regs)
+{
+ void (*handler)(struct regs_t *r);
+
+ handler = irq_callbacks[regs->int_no - 32];
+
+ printf("IRQ called\n");
+
+ if(handler)
+ {
+ handler(regs);
+ }
+
+ /* If the IDT entry that was invoked was greater than 40
+ * (meaning IRQ8 - 15), then we need to send an EOI to
+ * the slave controller */
+ if (regs->int_no >= 40)
+ {
+ outb(0xA0, 0x20);
+ }
+
+ /* send an EOI to the master controller */
+ outb(0x20, 0x20);
+}
diff --git a/kernel/isr-as.S b/kernel/isr-as.S
new file mode 100644
index 0000000..53e15b4
--- /dev/null
+++ b/kernel/isr-as.S
@@ -0,0 +1,213 @@
+isr_handler:
+ pusha
+ push %ds
+ push %es
+ push %fs
+ push %gs
+ mov $0x10, %ax # Load the Kernel Data Segment descriptor!
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %esp, %eax # Push us the stack
+ push %eax
+ mov $isr_handler, %eax
+ call *%eax
+ pop %eax
+ pop %gs
+ pop %fs
+ pop %es
+ pop %ds
+ popa
+ add $8, %esp
+ iret
+
+ # stub ISR's:
+ .global _isr0
+ .global _isr1
+ .global _isr2
+ .global _isr3
+ .global _isr4
+ .global _isr5
+ .global _isr6
+ .global _isr7
+ .global _isr8
+ .global _isr9
+ .global _isr10
+ .global _isr11
+ .global _isr12
+ .global _isr13
+ .global _isr14
+ .global _isr15
+ .global _isr16
+ .global _isr17
+ .global _isr18
+ .global _isr19
+ .global _isr20
+ .global _isr21
+ .global _isr22
+ .global _isr23
+ .global _isr24
+ .global _isr25
+ .global _isr26
+ .global _isr27
+ .global _isr28
+ .global _isr29
+ .global _isr30
+ .global _isr31
+# Interrupts 8, 10, 11, 12, 13, and 14 push error codes onto the stack
+
+_isr0:
+ cli
+ push $0
+ push $0
+ jmp isr_handler
+_isr1:
+ cli
+ push $0
+ push $1
+ jmp isr_handler
+_isr2:
+ cli
+ push $0
+ push $2
+ jmp isr_handler
+_isr3:
+ cli
+ push $0
+ push $3
+ jmp isr_handler
+_isr4:
+ cli
+ push $0
+ push $4
+ jmp isr_handler
+_isr5:
+ cli
+ push $0
+ push $5
+ jmp isr_handler
+_isr6:
+ cli
+ push $0
+ push $6
+ jmp isr_handler
+_isr7:
+ cli
+ push $0
+ push $7
+ jmp isr_handler
+_isr8:
+ cli
+ push $8
+ jmp isr_handler
+_isr9:
+ cli
+ push $0
+ push $9
+ jmp isr_handler
+_isr10:
+ cli
+ push $10
+ jmp isr_handler
+_isr11:
+ cli
+ push $11
+ jmp isr_handler
+_isr12:
+ cli
+ push $12
+ jmp isr_handler
+_isr13:
+ cli
+ push $13
+ jmp isr_handler
+_isr14:
+ cli
+ push $14
+ jmp isr_handler
+_isr15:
+ cli
+ push $0
+ push $15
+ jmp isr_handler
+_isr16:
+ cli
+ push $0
+ push $16
+ jmp isr_handler
+_isr17:
+ cli
+ push $0
+ push $17
+ jmp isr_handler
+_isr18:
+ cli
+ push $0
+ push $18
+ jmp isr_handler
+_isr19:
+ cli
+ push $0
+ push $19
+ jmp isr_handler
+_isr20:
+ cli
+ push $0
+ push $20
+ jmp isr_handler
+_isr21:
+ cli
+ push $0
+ push $21
+ jmp isr_handler
+_isr22:
+ cli
+ push $0
+ push $22
+ jmp isr_handler
+_isr23:
+ cli
+ push $0
+ push $23
+ jmp isr_handler
+_isr24:
+ cli
+ push $0
+ push $24
+ jmp isr_handler
+_isr25:
+ cli
+ push $0
+ push $25
+ jmp isr_handler
+_isr26:
+ cli
+ push $0
+ push $26
+ jmp isr_handler
+_isr27:
+ cli
+ push $0
+ push $27
+ jmp isr_handler
+_isr28:
+ cli
+ push $0
+ push $28
+ jmp isr_handler
+_isr29:
+ cli
+ push $0
+ push $29
+ jmp isr_handler
+_isr30:
+ cli
+ push $0
+ push $30
+ jmp isr_handler
+_isr31:
+ cli
+ push $0
+ push $31
+ jmp isr_handler
diff --git a/kernel/isr.c b/kernel/isr.c
new file mode 100644
index 0000000..fabbf80
--- /dev/null
+++ b/kernel/isr.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include "isr.h"
+#include "idt.h"
+
+void isr_handle(struct regs_t *regs)
+{
+ if(regs->int_no < 32)
+ {
+ printf("received exception!\n");
+ }
+}
+
+void isr_init(void)
+{
+ printf("ISR init");
+ idt_set_gate(0, (uint32_t)_isr0, 0x08, 0x8E);
+ idt_set_gate(1, (uint32_t)_isr1, 0x08, 0x8E);
+ idt_set_gate(2, (uint32_t)_isr2, 0x08, 0x8E);
+ idt_set_gate(3, (uint32_t)_isr3, 0x08, 0x8E);
+ idt_set_gate(4, (uint32_t)_isr4, 0x08, 0x8E);
+ idt_set_gate(5, (uint32_t)_isr5, 0x08, 0x8E);
+ idt_set_gate(6, (uint32_t)_isr6, 0x08, 0x8E);
+ idt_set_gate(7, (uint32_t)_isr7, 0x08, 0x8E);
+ idt_set_gate(8, (uint32_t)_isr8, 0x08, 0x8E);
+ idt_set_gate(9, (uint32_t)_isr9, 0x08, 0x8E);
+ idt_set_gate(10, (uint32_t)_isr10, 0x08, 0x8E);
+ idt_set_gate(11, (uint32_t)_isr11, 0x08, 0x8E);
+ idt_set_gate(12, (uint32_t)_isr12, 0x08, 0x8E);
+ idt_set_gate(13, (uint32_t)_isr13, 0x08, 0x8E);
+ idt_set_gate(14, (uint32_t)_isr14, 0x08, 0x8E);
+ idt_set_gate(15, (uint32_t)_isr15, 0x08, 0x8E);
+ idt_set_gate(16, (uint32_t)_isr16, 0x08, 0x8E);
+ idt_set_gate(17, (uint32_t)_isr17, 0x08, 0x8E);
+ idt_set_gate(18, (uint32_t)_isr18, 0x08, 0x8E);
+ idt_set_gate(19, (uint32_t)_isr19, 0x08, 0x8E);
+ idt_set_gate(20, (uint32_t)_isr20, 0x08, 0x8E);
+ idt_set_gate(21, (uint32_t)_isr21, 0x08, 0x8E);
+ idt_set_gate(22, (uint32_t)_isr22, 0x08, 0x8E);
+ idt_set_gate(23, (uint32_t)_isr23, 0x08, 0x8E);
+ idt_set_gate(24, (uint32_t)_isr24, 0x08, 0x8E);
+ idt_set_gate(25, (uint32_t)_isr25, 0x08, 0x8E);
+ idt_set_gate(26, (uint32_t)_isr26, 0x08, 0x8E);
+ idt_set_gate(27, (uint32_t)_isr27, 0x08, 0x8E);
+ idt_set_gate(28, (uint32_t)_isr28, 0x08, 0x8E);
+ idt_set_gate(29, (uint32_t)_isr29, 0x08, 0x8E);
+ idt_set_gate(30, (uint32_t)_isr30, 0x08, 0x8E);
+ idt_set_gate(31, (uint32_t)_isr31, 0x08, 0x8E);
+}