manuhg
manuhg

Reputation: 460

IDT done in C is not working

I am not being able to get IDT working because my Interrupt routines are not getting called, especially the keyboard related one when i press a key on keyboard. I am passing the IDT table's special 48 bit pointer's address. I am doing it like

dt_ptr idt_ptr; // defining the pointer
loadidt(dt_ptr *a); // how i am passing the pointer's address to assembly routine

I also don't know whether at least GDT is working or not.

1) what shall i do to get my IDT working. I saw few tutorials too but didn't help 2) How can i verify whether GDT works properly?

Thanks in advance.

EDIT: I am doing this for my own OS. I am doubtful whether my assembly routine is able to properly receive the pointer's address. So i also tried to do lidt using inline assembly but didn't help. I don't know what is wrong. Any clues, idea?

void remap_irqs(void)
{
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);
outbyte('a');

}

void set_idt_gate(uint8 num, unsigned long base, word sel, uint8 flags)
{
IDT[num].offset_low = (base & 0xFFFF);
IDT[num].offset_high = (base >> 16) & 0xFFFF;    
IDT[num].selector = sel;    
IDT[num].zero = 0;
IDT[num].type_attrs = flags;   
}




void init_idt()
{
outbyte('M');   
idt_ptr.limit = (sizeof (idt_entry) * 256) - 1;
idt_ptr.base =(uint32) &IDT;

memset((uint8 *)&IDT, 0, sizeof(idt_entry) * 256);
remap_irqs();
set_idt_gate(0,  (unsigned) irq_0, 0x08, 0x8E);
set_idt_gate(1,  (unsigned) irq_1, 0x08, 0x8E);
//install_isrs();
//install_irqs();   
//idt_load();
//print_message();
lidt(&IDT,idt_ptr.limit);
_LIDT(&idt_ptr);
loadidt(&idt_ptr);
}



void lidt( void * base, unsigned short size )
{
struct
{
    unsigned short length;
    unsigned long base;
} __attribute__((__packed__)) IDTR;

IDTR.length = size;
IDTR.base = (unsigned long)base;
asm( "lidt (%0)"
     : : "p"(&IDTR) );

}

void _LIDT(dt_ptr *ptr)
{
asm("lidt (%0)" : :"p"(ptr));
outbyte('n');
}





void irq_0()
{
//before_interrupt();
ticks+=1;
if(ticks%18==0)
{
    outbyte('+');
    outbyte('1');
}
//after_interrupt();
}

void irq_1()
{
outbyte('a');
//before_interrupt();
irq1_keyb();
//after_interrupt();
}

typedef struct {
uint16 offset_low;    // The lower 16 bits of the address to jump to when this
interrupt occures:// offset 0-15  
uint16 selector;      // Kernel segment selector in IDT
uint8  zero;          // This must always be zero.
uint8  type_attrs;    //gate types, atttribute types etc.   
uint16 offset_high;   // The upper 16 bits of the address to jump to. offset 16-31 
} __attribute__((__packed__)) idt_entry;  


typedef struct  {
uint16 limit;
uint32 base;      // The address of the first element in IDT array.
} __attribute__((__packed__)) dt_ptr;


global loadidt
loadidt:
push ebp
mov ebp,esp     
mov eax,[ebp+8]     
lidt [eax]    
pop ebp     
ret

Upvotes: 0

Views: 962

Answers (1)

Paweł Dziepak
Paweł Dziepak

Reputation: 2112

You set IRQs vector offset to 0x20. That means IRQ0 is mapped to interrupt 0x20, IRQ1 to interrupt 0x21, etc. However, you set your irq handlers to be executed when interrupts 0x00 and 0x01 occur. That's how you should set IDR:

set_idt_gate(0x20,  (unsigned) irq_0, 0x08, 0x8E);
set_idt_gate(0x21,  (unsigned) irq_1, 0x08, 0x8E);

You can find more information regarding PIC here (section Initialization explains exactly what you are doing in remap_irqs function.

Upvotes: 1

Related Questions