Page 1 of 1

PIC Remap on IRQ gives Double Fault

Posted: Sat Oct 24, 2009 11:49 pm
by fmwaseka
I dont know why this keeps on failing... I tried the sample on linux using nasm and gcc and worked fine, but most of my code uses Masm and VC++. I can handle the IDT Exceptions but when I try to set up IRQ I get an error. Here is the code..

Code: Select all

; Assembly.asm-------------------------------------------------------
?Irq0@@YIXXZ proc
	push    32
    jmp     ?IrqCaptured@@YIXXZ
?Irq0@@YIXXZ endp

extrn ?ProcessIRQ@@YIXKPAU_BL_TRAP_CONTEXT@@@Z:near

align 16
?IrqCaptured@@YIXXZ proc
		pusha
	    push    eax
        push    ebx
        push    ecx
        push    edx
        push    esi
        push    edi
        push    ebp
        mov     eax, esp
        add     eax, 48
        push    eax
        mov     eax, cr2
        push    eax
        mov     edx, esp
        call    ?ProcessIRQ@@YIXKPAU_IRQ_CONTEXT@@@Z
        pop    eax
        pop    ebp
        pop    edi
        pop    esi
        pop    edx
        pop    ecx
        pop    ebx
        popa
        iret
?IrqCaptured@@YIXXZ endp

// Irq.cpp --------------------------------------------------------------------------
 extern void Irq0();
 
void *irq_routines[16] =
{
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
};
 
 void InitializeIrq()
 {
	outportb(0x20, 0x11);
	outportb(0xA0, 0x11);

	outportb(0x21, 0x20);
	outportb(0xA1, 0x28);
	
	outportb(0x21, 0x04);
	outportb(0xA1, 0x02);

	outportb(0x21, 0x01);
	outportb(0xA1, 0x01);

	outportb(0x21, 0x0);
	outportb(0xA1, 0x0);

    SetGate(32, (unsigned)Irq0, 0x08, 0x8E);
	
	__asm { sti }
}

void ProcessIRQ(ULONG_PTR Trap, PIRQ_CONTEXT Context)
{
	void (*handler)(PIRQ_CONTEXT Context);

    handler = (void(*)(PIRQ_CONTEXT))irq_routines[Context->Val-32];
    if (handler)
    {
        handler(Context);
    }

    if (Context->Val >= 40)
    {
        outportb(0xA0, 0x20);
    }

    outportb(0x20, 0x20);
}
For some reason I get a Double Fault Error when ever I uncomment __asm { sti }, If I comment it, I get no errors but also no effect :? .. I test it by setting up a timer

Re: PIC Remap on IRQ gives Double Fault

Posted: Mon Oct 26, 2009 3:22 pm
by tantrikwizard
What does your SetGate function look like? Are you loading the IDT from anywhere?

Re: PIC Remap on IRQ gives Double Fault

Posted: Tue Oct 27, 2009 5:34 am
by fmwaseka

Code: Select all

//SetGate
IDTR    idtp;
IDTE    idt[256];

void SetGate(UINT32 num, UINT64 base, UINT8 sel, UINT8 flags)
{
        idt[num].BaseLo  =(UINT16)((base >>  0) & 0xffff);
        idt[num].BaseHi = (UINT16)((base >> 16) & 0xffff);	
        idt[num].Selector = sel;		
        idt[num].Always0 = 0;
        idt[num].Flags = flags;
}
Yes I do call the lidt

Re: PIC Remap on IRQ gives Double Fault

Posted: Tue Oct 27, 2009 11:27 pm
by tantrikwizard
When/where is the IDT being loaded? From your example code it's not being loaded before the STI. My suggestion is to follow one of the countless tutorials that explain this in detail and have been covered extensively here.

Re: PIC Remap on IRQ gives Double Fault

Posted: Wed Oct 28, 2009 3:23 am
by fmwaseka
I load it here

Code: Select all

void InitializeIdt(void)
{
	idtp.Limit = 256*8;
        idtp.Base = (int)&idt;

        /* Clear out the entire IDT, initializing it to zeros */
        memset(&idt, 0, ARRAY_SIZE(idt));

        //Capture exceptions, then printed out in a function called TrapFatalErrors
	for (UINT8 i = 0; i < ARRAY_SIZE(idt); i++) 
            SetGate(i, (((UINT64)FatalErrorCaptured) + i * 8),PM_CODE_SELECTOR,0x8e);
	 
        //Calls the  lidt
	SetIdtr(&idtp);
}
After this is when I try set up IRQ. I am going step by step, but most tutorials are using nasm and not masm.
Here is the sequence
-Setup GDT
-Setup IDT
-Setup IRQ
-Call Sti

Re: PIC Remap on IRQ gives Double Fault

Posted: Wed Oct 28, 2009 12:39 pm
by tantrikwizard
Run it in bochs and put a break point on the sti. Inspect the IDT and GDT and make sure they're valid before enabling.