I am working recently on ISR and IRQ handling. My code is based on James'm tutorial, but i use gas instead of nasm.
ISRs are working okay, but I am not receiving any IRQ. I've tried tu use Bran's code, but also IRQs didn't work. I've tested my os on qemu-system-i386 and virtualbox. What's wrong? Have I mapped PIC in wrong way? Or just my irq handler function in asm is wrong?
Here is my code:
interrupt.S
Code: Select all
.global isr0
isr0:
cli
pushl $0
pushl $0
jmp isr_common_stub
.global isr1
isr1:
cli
pushl $0
pushl $1
jmp isr_common_stub
.global isr2
isr2:
cli
pushl $0
pushl $2
jmp isr_common_stub
.global isr3
isr3:
cli
pushl $0
pushl $3
jmp isr_common_stub
.global isr4
isr4:
cli
pushl $0
pushl $4
jmp isr_common_stub
.global isr5
isr5:
cli
pushl $0
pushl $5
jmp isr_common_stub
.global isr6
isr6:
cli
pushl $0
pushl $6
jmp isr_common_stub
.global isr7
isr7:
cli
pushl $0
pushl $7
jmp isr_common_stub
.global isr8
isr8:
cli
pushl $8
jmp isr_common_stub
.global isr9
isr9:
cli
pushl $0
pushl $9
jmp isr_common_stub
.global isr10
isr10:
cli
pushl $10
jmp isr_common_stub
.global isr11
isr11:
cli
pushl $11
jmp isr_common_stub
.global isr12
isr12:
cli
pushl $12
jmp isr_common_stub
.global isr13
isr13:
cli
pushl $13
jmp isr_common_stub
.global isr14
isr14:
cli
pushl $14
jmp isr_common_stub
.global isr15
isr15:
cli
pushl $0
pushl $15
jmp isr_common_stub
.global isr16
isr16:
cli
pushl $0
pushl $16
jmp isr_common_stub
.global isr17
isr17:
cli
pushl $0
pushl $17
jmp isr_common_stub
.global isr18
isr18:
cli
pushl $0
pushl $18
jmp isr_common_stub
.global isr19
isr19:
cli
pushl $0
pushl $19
jmp isr_common_stub
.global isr20
isr20:
cli
pushl $0
pushl $20
jmp isr_common_stub
.global isr21
isr21:
cli
pushl $0
pushl $21
jmp isr_common_stub
.global isr22
isr22:
cli
pushl $0
pushl $22
jmp isr_common_stub
.global isr23
isr23:
cli
pushl $0
pushl $23
jmp isr_common_stub
.global isr24
isr24:
cli
pushl $0
pushl $24
jmp isr_common_stub
.global isr25
isr25:
cli
pushl $0
pushl $25
jmp isr_common_stub
.global isr26
isr26:
cli
pushl $0
pushl $26
jmp isr_common_stub
.global isr27
isr27:
cli
pushl $0
pushl $27
jmp isr_common_stub
.global isr28
isr28:
cli
pushl $0
pushl $28
jmp isr_common_stub
.global isr29
isr29:
cli
pushl $0
pushl $29
jmp isr_common_stub
.global isr30
isr30:
cli
pushl $0
pushl $30
jmp isr_common_stub
.global isr31
isr31:
cli
pushl $0
pushl $31
jmp isr_common_stub
.global irq0
irq0:
cli
pushl $0
pushl $32
jmp irq_common_stub
.global irq1
irq1:
cli
push $0
push $33
jmp irq_common_stub
.global irq2
irq2:
cli
pushl $0
pushl $34
jmp irq_common_stub
.global irq3
irq3:
cli
pushl $0
pushl $35
jmp irq_common_stub
.global irq4
irq4:
cli
pushl $0
pushl $36
jmp irq_common_stub
.global irq5
irq5:
cli
pushl $0
pushl $37
jmp irq_common_stub
.global irq6
irq6:
cli
pushl $0
pushl $38
jmp irq_common_stub
.global irq7
irq7:
cli
pushl $0
pushl $39
jmp irq_common_stub
.global irq8
irq8:
cli
pushl $0
pushl $40
jmp irq_common_stub
.global irq9
irq9:
pushl $0
pushl $41
jmp irq_common_stub
.global irq10
irq10:
cli
pushl $0
pushl $42
jmp irq_common_stub
.global irq11
irq11:
cli
pushl $0
pushl $43
jmp irq_common_stub
.global irq12
irq12:
cli
pushl $0
pushl $44
jmp irq_common_stub
.global irq13
irq13:
cli
pushl $0
pushl $45
jmp irq_common_stub
.global irq14
irq14:
cli
pushl $0
pushl $46
jmp irq_common_stub
.global irq15
irq15:
cli
pushl $0
pushl $47
jmp irq_common_stub
.extern isr_handler
isr_common_stub:
pushal
mov %ds, %ax
pushl %eax
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
call isr_handler
popl %ebx
mov %bx, %ds
mov %bx, %es
mov %bx, %fs
mov %bx, %gs
popal
add $8, %esp
sti
iret
.extern irq_handler
irq_common_stub:
pusha
mov %ds, %ax
push %eax
mov $0x10, %ax
mov %eax, %ds
mov %eax, %es
mov %eax, %fs
mov %eax, %gs
call irq_handler
pop %ebx
mov %ebx, %ds
mov %ebx, %es
mov %ebx, %fs
mov %ebx, %gs
popa
add $0x8, %esp
sti
iret
Code: Select all
#include <loki/system.h>
extern void idt_flush(uint32_t);
extern void idt_set_gate(uint8_t, uint32_t, uint16_t, uint8_t);
idt_entry_t idt_entries[255];
idt_ptr_t idt_ptr;
isr_t interrupt_handlers[256];
void init_idt()
{
idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
idt_ptr.base = (uint32_t)&idt_entries;
for(int i=0;i<255;i++)
{
idt_entries[i].base_lo = 0;
idt_entries[i].sel = 0;
idt_entries[i].always0 = 0;
idt_entries[i].flags = 0;
idt_entries[i].base_hi = 0;
}
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( 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);
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);
init_msg("setting IDT");
}
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
{
idt_entries[num].base_lo = base & 0xFFFF;
idt_entries[num].base_hi = (base >> 16) & 0xFFFF;
idt_entries[num].sel = sel;
idt_entries[num].always0 = 0;
idt_entries[num].flags = flags;
}
void register_interrupt_handler(uint8_t n, isr_t handler)
{
interrupt_handlers[n] = handler;
}
void isr_handler(registers_t regs)
{
kprintf("Received interrupt: 0x%x\n", (uint32_t) regs.int_no);
if (interrupt_handlers[regs.int_no] != 0)
{
isr_t handler = interrupt_handlers[regs.int_no];
handler(regs);
}
}
void irq_handler(registers_t regs)
{
if (regs.int_no >= 40)
{
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
if (interrupt_handlers[regs.int_no] != 0)
{
isr_t handler = interrupt_handlers[regs.int_no];
handler(regs);
}
}
uint32_t tick = 0;
void timer_callback(registers_t regs)
{
tick++;
kprintf("Tick: 0x%x \n", (uint32_t) tick);
}
void init_timer(uint32_t frequency)
{
register_interrupt_handler(IRQ0, &timer_callback);
uint32_t divisor = 1193180 / frequency;
outb(0x43, 0x36);
uint8_t l = (uint8_t)(divisor & 0xFF);
uint8_t h = (uint8_t)( (divisor>>8) & 0xFF );
outb(0x40, l);
outb(0x40, h);
}
Code: Select all
#include <loki/system.h>
#ifndef idt_h
#define idt_h
#define IRQ0 32
#define IRQ1 33
#define IRQ2 34
#define IRQ3 35
#define IRQ4 36
#define IRQ5 37
#define IRQ6 38
#define IRQ7 39
#define IRQ8 40
#define IRQ9 41
#define IRQ10 42
#define IRQ11 43
#define IRQ12 44
#define IRQ13 45
#define IRQ14 46
struct idt_entry
{
uint16_t base_lo;
uint16_t sel;
uint8_t always0;
uint8_t flags;
uint16_t base_hi;
} __attribute__((packed));
typedef struct idt_entry idt_entry_t;
struct idt_ptr
{
uint16_t limit;
uint32_t base;
} __attribute__((packed));
typedef struct idt_ptr idt_ptr_t;
typedef struct registers
{
uint32_t ds;
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t int_no, err_code;
uint32_t eip, cs, eflags, useresp, ss;
} registers_t;
void init_idt();
extern void isr0 ();
extern void isr1 ();
extern void isr2 ();
extern void isr3 ();
extern void isr4 ();
extern void isr5 ();
extern void isr6 ();
extern void isr7 ();
extern void isr8 ();
extern void isr9 ();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
typedef void (*isr_t)(registers_t);
void register_interrupt_handler(uint8_t n, isr_t handler);
void init_timer(uint32_t frequency);
void timer_callback(registers_t regs);
//void init_irq();
void irq_install_handler(int irq, void (*handler)(struct registers *r));
void irq_uninstall_handler(int irq);
void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags);
#endif
Wrozowski