OSDev.org https://forum.osdev.org/ |
|
IRQs doesn't work https://forum.osdev.org/viewtopic.php?f=1&t=57025 |
Page 1 of 1 |
Author: | husaral [ Fri Nov 17, 2023 12:05 pm ] |
Post subject: | IRQs doesn't work |
So I tried to write a basic PIT timer but the interrupt doesn't get called. When I call the handler manually by int command it does work but it doesn't do anything automatically. I am sure my main function never returns as I have set a infinite loop. (I have set up the GDT, IDT and PIC and exceptions does work) The files: irq.s : Code: .section .text .align 4 .macro IRQ index byte .global _irq\index .type _irq\index, @function _irq\index: pushl $0 pushl $\byte jmp isr_wrapper .endm .macro ISR index .global _isr\index .type _isr\index, @function _isr\index: pushl $0 pushl $\index jmp isr_wrapper .endm .macro ISR_ERR index .global _isr\index .type _isr\index, @function _isr\index: pushl $\index jmp isr_wrapper .endm ISR 0 ISR 1 ISR 2 ISR 3 ISR 4 ISR 5 ISR 6 ISR 7 ISR_ERR 8 ISR 9 ISR_ERR 10 ISR_ERR 11 ISR_ERR 12 ISR_ERR 13 ISR_ERR 14 ISR 15 ISR 16 ISR 17 ISR 18 ISR 19 ISR 20 ISR 21 ISR 22 ISR 23 ISR 24 ISR 25 ISR 26 ISR 27 ISR 28 ISR 29 ISR 30 ISR 31 IRQ 0, 32 IRQ 1, 33 IRQ 2, 34 IRQ 3, 35 IRQ 4, 36 IRQ 5, 37 IRQ 6, 38 IRQ 7, 39 IRQ 8, 40 IRQ 9, 41 IRQ 10, 42 IRQ 11, 43 IRQ 12, 44 IRQ 13, 45 IRQ 14, 46 IRQ 15, 47 .extern isr_handler .type isr_handler, @function .global isr_wrapper isr_wrapper: pushal push %esp cld call isr_handler add $4, %esp popal add $8, %esp iretl idt.c : Code: #include <stdint.h> #include <arch/x86/idt.h> #include <arch/x86/regs.h> #include <arch/x86/pic.h> #include <sys/kprint.h> struct InterruptDescriptor { uint16_t offset_low; //Offset bits 0 to 15 uint16_t selector; //A code segment selector in GDT or LDT uint8_t zero; //Just a gap, always set to zero uint8_t type_attributes; //Gate type, DPL and present bit fields uint16_t offset_high; //Offset bits 16 to 31 } __attribute__((packed)); struct IDTPointer{ uint16_t limit; void* base; } __attribute__((packed)); static struct IDTPointer idt_pointer; struct InterruptDescriptor idt[256]; static void (*irq_handler_table[16]) (void); void idt_set_gate(uint8_t num, void* handler, uint16_t selector, uint8_t type_attributes){ idt[num].offset_low = (uint32_t) handler & 0xFFFF; idt[num].selector = selector; idt[num].type_attributes = type_attributes; idt[num].offset_high = ((uint32_t)handler >> 16) & 0xFFFF; } void irq_set_handler(uint8_t irq, void* handler){ irq_handler_table[irq] = handler; } void initialize_idt(void){ idt_pointer.limit = sizeof(idt); idt_pointer.base = &idt; void* isr_handlers[] = {_isr0, _isr1, _isr2, _isr3, _isr4, _isr5, _isr6, _isr7, _isr8, _isr9, _isr10, _isr11, _isr12, _isr13, _isr14, _isr15, _isr16, _isr17, _isr18, _isr19, _isr20, _isr21, _isr22, _isr23, _isr24, _isr25, _isr26, _isr27, _isr28, _isr29, _isr30, _isr31}; for(int i = 0; i < 32; ++i){ idt_set_gate(i, isr_handlers[i], 0x08, 0x8E); } void* irq_handlers[] = {_irq0, _irq1, _irq2, _irq3, _irq4, _irq5, _irq6, _irq7, _irq8, _irq9, _irq10, _irq11, _irq12, _irq13, _irq14, _irq15}; for(int i = 0; i < 16; ++i){ idt_set_gate(i + 32, irq_handlers[i], 0x08, 0x8E); //There are 32 entries before the first IRQ entry } //Load the new IDT asm volatile ("lidt %0" :: "m"(idt_pointer)); } static void _exception(char* message, struct x86Registers* regs){ kprintf(message); kprintf("EAX : 0x%x EBX : 0x%x ECX : 0x%x EDX : 0x%x\n", regs->eax, regs->ebx, regs->ecx, regs->edx); kprintf("ESP : 0x%x EBP : 0x%x ESI : 0x%x EDI : 0x%x\n", regs->esp, regs->ebp, regs->esi, regs->edi); kprintf("EIP : 0x%x CS : 0x%x EFLAGS : 0x%x SS : 0x%x\n", regs->eip, regs->cs, regs->eflags, regs->ss); asm volatile("hlt"); } static void _handle_irq(struct x86Registers* regs, int irq){ irq_handler_table[irq](); acknowledge_irq(irq); } struct x86Registers* isr_handler(struct x86Registers* regs){ switch (regs->interrupt_no){ case 0: _exception("Division by zero\n", regs); break; case 3: _exception("Breakpoint\n", regs); break; case 4: _exception("Overflow\n", regs); break; case 5: _exception("Range exceeded\n", regs); break; case 6: _exception("Invalid opcode\n", regs); break; case 7: _exception("Device not available\n", regs); break; case 8: _exception("Double fault\n", regs); break; case 32: _handle_irq(regs, 0); break; case 33: _handle_irq(regs, 1); break; case 34: _handle_irq(regs, 2); break; case 35: _handle_irq(regs, 3); break; case 36: _handle_irq(regs, 4); break; case 37: _handle_irq(regs, 5); break; case 38: _handle_irq(regs, 6); break; case 39: _handle_irq(regs, 7); break; case 40: _handle_irq(regs, 8); break; case 41: _handle_irq(regs, 9); break; case 42: _handle_irq(regs, 10); break; case 43: _handle_irq(regs, 11); break; case 44: _handle_irq(regs, 12); break; case 45: _handle_irq(regs, 13); break; case 46: _handle_irq(regs, 14); break; case 47: _handle_irq(regs, 15); break; default: kprintf("Interrupt!"); break; } return regs; } pic.c : Code: #include <stdint.h> #include <arch/x86/ports.h> #define PIC1_COMMAND 0x20 #define PIC1_DATA 0x21 #define PIC2_COMMAND 0xA0 #define PIC2_DATA 0xA1 void remap_pic(uint32_t offset1, uint32_t offset2){ uint8_t p1, p2; p1 = inb(PIC1_DATA); p2 = inb(PIC2_DATA); outb(PIC1_COMMAND, 0x11); iowait(); outb(PIC2_COMMAND, 0x11); iowait(); outb(PIC1_DATA, offset1); iowait(); outb(PIC2_DATA, offset2); iowait(); outb(PIC1_DATA, 4); iowait(); outb(PIC2_DATA, 2); iowait(); outb(PIC1_DATA, 0x01); iowait(); outb(PIC2_DATA, 0x01); iowait(); outb(PIC1_DATA, p1); outb(PIC2_DATA, p2); } void unmask_irq(uint8_t irq){ uint16_t port = PIC1_DATA; uint8_t value; if(irq >= 8){ port = PIC2_DATA; irq -= 8; } value = inb(port) & ~(1 << irq); outb(port, value); } void acknowledge_irq(uint8_t irq_no){ if (irq_no >= 8) outb(PIC2_COMMAND, 0x20); outb(PIC1_COMMAND, 0x20); } pit.c : Code: #include <stdint.h> #include <arch/x86/idt.h> #include <arch/x86/regs.h> #include <arch/x86/pic.h> #include <arch/x86/ports.h> #include <sys/kprint.h> void pit_handler(void){ kprintf("PIT\n"); acknowledge_irq(0); } void initialize_pit(void) { irq_set_handler(0, pit_handler); unmask_irq(0); long divisor = 1193180 / 100; outb(0x43, 0x36); outb(0x40, divisor & 0xFF); outb(0x40, (divisor >> 8) & 0xFF); } Thanks for any help. |
Author: | Octocontrabass [ Tue Feb 13, 2024 12:15 pm ] |
Post subject: | Re: IRQs doesn't work |
I know it's been a while, but... did you use STI to enable interrupts? |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |