Add timer
diff --git a/src/Makefile b/src/Makefile
index 511afef..6ce6c27 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -8,7 +8,8 @@
interrupts.o \
log.o \
irq.o \
- pic.o
+ pic.o \
+ timer.o
CFLAGS = -nostdlib -nostdinc -fno-builtin -fno-stack-protector -ffreestanding -m32 -O2 -g
LDFLAGS = -Tlink.ld -melf_i386
ASMFLAGS = -felf
diff --git a/src/descriptor_tables.c b/src/descriptor_tables.c
index a9aa521..86e554a 100644
--- a/src/descriptor_tables.c
+++ b/src/descriptor_tables.c
@@ -1,6 +1,7 @@
#include "descriptor_tables.h"
#include "vga.h"
#include "io.h"
+#include "log.h"
#include "pic.h"
extern void gdt_flush(uint gdt);
@@ -65,13 +66,16 @@
memset(&idt_entries, 0, sizeof(idt_entries));
- vga_write("sizeof(idt_entries) = ");
- vga_putx(sizeof(idt_entries));
- vga_put('\n');
+ // Remap PIC
+ pic_remap();
- vga_write("isr0 = ");
- vga_putx((uint)isrs[0]);
- vga_put('\n');
+ vga_set_color(CYAN, BLACK);
+ for (int i = 0; i < 16; i++)
+ {
+ kprintf("Setting gate irq=%d,\tint=%d\n", i, IRQ_TO_INT(i));
+ idt_set_gate(IRQ_TO_INT(i), (uint)irqs[i], 0x08, 0x8e);
+ }
+ vga_set_color(WHITE, BLACK);
for (int i = 0; i < 32; i++)
{
@@ -80,25 +84,6 @@
idt_flush((uint)&idt_pointer);
- // Remap PIC
-
- outb(PIC1_COMMAND, 0x11);
- outb(PIC2_COMMAND, 0x11);
-
- outb(PIC1_DATA, 0x20);
- outb(PIC2_DATA, 0x28);
- outb(PIC1_DATA, 0x04);
- outb(PIC2_DATA, 0x02);
- outb(PIC1_DATA, 0x01);
- outb(PIC2_DATA, 0x01);
- outb(PIC1_DATA, 0);
- outb(PIC2_DATA, 0);
-
- for (int i = 0; i < 16; i++)
- {
- idt_set_gate(i + 32, (uint)irqs[i], 0x08, 0x8e);
- }
-
vga_write("IDT Initialized!\n");
}
diff --git a/src/idt.s b/src/idt.s
index 756eed4..6ded21b 100644
--- a/src/idt.s
+++ b/src/idt.s
@@ -61,10 +61,10 @@
isr_common:
pusha ; Save all registers
- mov ax, ds
+ mov ax, ds ; Save data segment
push eax
- mov ax, 0x10
+ mov ax, 0x10 ; New segments
mov ds, ax
mov es, ax
mov fs, ax
@@ -72,7 +72,7 @@
call isr_handler
- pop eax
+ pop eax ; Reset segments
mov ds, ax
mov es, ax
mov fs, ax
diff --git a/src/main.c b/src/main.c
index f5b6200..8d2783f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,8 @@
#include "vga.h"
#include "log.h"
+#include "io.h"
#include "descriptor_tables.h"
+#include "timer.h"
int kmain(void *mboot)
{
@@ -15,7 +17,9 @@
vga_write("Setup complete!\n");
vga_set_color(WHITE, BLACK);
- kassert(0, "should fail");
+ asm volatile("sti");
+
+ init_timer(50);
while (1)
{}
diff --git a/src/pic.c b/src/pic.c
index 693c747..f5355a8 100644
--- a/src/pic.c
+++ b/src/pic.c
@@ -1,12 +1,27 @@
#include "pic.h"
+#include "log.h"
#include "io.h"
+#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
+#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
+#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
+#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
+#define ICW1_INIT 0x10 /* Initialization - required! */
+
+#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
+#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
+#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
+#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
+#define ICW4_SFNM 0x10 /* Special fully nested (not) */
+
+
void (* interrupt_handlers[256])(struct registers);
void pic_send_eoi(uchar interrupt)
{
- if (interrupt >= 40)
+ if (interrupt >= IRQ_TO_INT(8))
outb(PIC2_COMMAND, PIC_EOI);
+
outb(PIC1_COMMAND, PIC_EOI);
}
@@ -14,6 +29,8 @@
{
pic_send_eoi(regs.interrupt_number);
+ kprintf("irq_handler called with interrupt %d\n", regs.interrupt_number);
+
if (interrupt_handlers[regs.interrupt_number])
interrupt_handlers[regs.interrupt_number](regs);
}
@@ -22,3 +39,19 @@
{
interrupt_handlers[interrupt] = handler;
}
+
+void pic_remap()
+{
+ 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);
+
+ return;
+}
diff --git a/src/pic.h b/src/pic.h
index ad44216..a8b6d99 100644
--- a/src/pic.h
+++ b/src/pic.h
@@ -12,5 +12,9 @@
#define PIC_EOI 0x20 // End of input
+#define IRQ_TO_INT(irq) ((irq) + 32)
+
void pic_send_eoi(uchar interrupt);
void add_interrupt_handler(uchar interrupt, void (* handler)(struct registers));
+
+void pic_remap();
diff --git a/src/timer.c b/src/timer.c
new file mode 100644
index 0000000..72ff1c6
--- /dev/null
+++ b/src/timer.c
@@ -0,0 +1,33 @@
+#include "timer.h"
+#include "pic.h"
+#include "log.h"
+#include "registers.h"
+#include "io.h"
+
+static ulong tick = 0;
+
+static void timer_cb(struct registers regs)
+{
+ kprintf("Timer tick %d\n", tick++);
+}
+
+void init_timer(uint hz)
+{
+ add_interrupt_handler(IRQ_TO_INT(0), timer_cb);
+
+ uint divisor = TIMER_FREQ / hz;
+
+ kprintf("Divisor is %d\n", divisor);
+
+ outb(0x43, 0x36);
+ io_wait();
+ uchar l = divisor & 0xff,
+ h = (divisor >> 8) & 0xff;
+
+ outb(0x40, l);
+ io_wait();
+ outb(0x40, h);
+ io_wait();
+
+ kprintf("Initialized timer\n");
+}
diff --git a/src/timer.h b/src/timer.h
new file mode 100644
index 0000000..50297c4
--- /dev/null
+++ b/src/timer.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "kint.h"
+
+#define TIMER_FREQ 1193180
+
+void init_timer(uint hz);
diff --git a/src/vga.c b/src/vga.c
index 11f3b9e..06fe608 100644
--- a/src/vga.c
+++ b/src/vga.c
@@ -93,11 +93,12 @@
memset(str, 0, 48);
uint i = 0;
- while (d > 0 && i < 48) // should never be more than 48 digits anyway
+ do
{
str[i++] = (d % 10) + '0';
d /= 10;
}
+ while (d > 0 && i < 48); // should never be more than 48 digits anyway
for (uint j = i; j; j--)
{