I expect this code to print out a ton of "Tick" messages but instead, it just prints out the following
The first two show that I made it past the timer init. The fact that printing works (even for manually triggered interrupts) and that I should be printing "irq hit" if I was getting to irq_handle indicates to me that I'm not managing to get into irq0 like I wanted. I'm not particularlly sure why I'm not getting there though. Any idea what I might be doing wrong?setting up timer
registering interrupt handler
Unhandled Interupt: 0x03
Unhandled Interupt: 0x04
(Chunks of my code that I think are relevant posted below)
kernel_main
Code: Select all
void kernel_main(void) {
gdt_init();
idt_init();
t_init();
timer_init(100);
asm volatile ("int $0x3");
asm volatile ("int $0x4");
}
Code: Select all
.global irq_handler
.type irq_handler, @function
irq_common_stub:
pusha
mov %ds, %ax
push %eax
push %esp
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
call irq_handler
add $0x04, %esp
pop %eax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
popa
add $0x08,%esp
iret
.macro make_iqr n irqn
.global irq\n
.type irq\n, @function
irq\n:
cli
push $0
push $\irqn
jmp irq_common_stub
.endm
make_iqr 0,32
...
make_iqr 15,47
Code: Select all
void idt_init() {
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
idt_ptr.base = (uint32_t)&idt_entries;
kmemset((void *)&idt_entries, 0, sizeof(idt_entry_t) * 256);
kmemset((void *)&interrupt_handlers, 0, sizeof(isr_t) * 256);
// Remap the irq tables
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);
idt_set_gate(0, (uint32_t)isr0, 0x08, 0x8E);
...
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);
idt_flush((uint32_t)&idt_ptr);
}
Code: Select all
void isr_handler(registers_t *regs) {
if (interrupt_handlers[regs->int_no])
interrupt_handlers[regs->int_no](regs);
else {
term_t *term = t_curterm();
static const char *lookup = "0123456789ABCDEF";
t_print(term, "\n\nUnhandled interrupt: 0x");
t_putchar(term, lookup[(regs->int_no >> 4) & 0xF]);
t_putchar(term, lookup[regs->int_no & 0xF]);
t_print(term, "\n");
}
}
void register_interrupt_handler(uint8_t n, isr_t h) {
t_print(t_curterm(), "registering interrupt handler\n");
interrupt_handlers[n] = h;
}
void irq_handler(registers_t *regs);
void irq_handler(registers_t *regs) {
t_print(t_curterm(), "irq hit\n");
if (regs->int_no >= 40) {
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
if (interrupt_handlers[regs->int_no] != 0)
interrupt_handlers[regs->int_no](regs);
}
Code: Select all
static void timer_callback(registers_t* regs) {
term_t *term = t_curterm();
t_print(term, "Tick\n");
tick++;
}
void timer_init(uint16_t frequency) {
t_print(t_curterm(), "setting up timer\n");
// Firstly, register our timer callback.
register_interrupt_handler(IRQ0, &timer_callback);
// The value we send to the PIT is the value to divide it's input clock
// (1193180 Hz) by, to get our required frequency. Important to note is
// that the divisor must be small enough to fit into 16-bits.
uint32_t divisor = 1193180 / frequency;
// Send the command byte.
outb(0x43, 0x36);
// Divisor has to be sent byte-wise, so split here into upper/lower bytes.
uint8_t l = (uint8_t)(divisor & 0xFF);
uint8_t h = (uint8_t)((divisor >> 8) & 0xFF);
// Send the frequency divisor.
outb(0x40, l);
outb(0x40, h);
}