OSDev.org

The Place to Start for Operating System Developers
It is currently Sat Apr 27, 2024 12:32 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: IRQs doesn't work
PostPosted: Fri Nov 17, 2023 12:05 pm 
Offline

Joined: Mon Aug 21, 2023 4:46 pm
Posts: 1
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.


Top
 Profile  
 
 Post subject: Re: IRQs doesn't work
PostPosted: Tue Feb 13, 2024 12:15 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5146
I know it's been a while, but... did you use STI to enable interrupts?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], SemrushBot [Bot] and 17 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group