Page 1 of 1

Only the first IRQ is handled

Posted: Thu Nov 15, 2007 5:25 pm
by hstagni
OK.
I made the GDT and the IDT, and I´m already handling exceptions. Then, I was trying to test if IDT was working. After remapping the PIC, made something like:
---------------------------------------------------------------------
SetIDTGate(32, (unsigned long)Irq0, CODE_SEG, IS_PRESENT, 0);
SetIDTGate(33, (unsigned long)Irq1, CODE_SEG, IS_PRESENT, 0);

And function Irq0 and Irq1 are:
void Irq0{
puts("IRQ0 fired");
outportb(0x20, 0x20); /*END OF INTERRUPT master controller*/
}
void Irq1{
puts("IRQ1 fired");
outportb(0x20, 0x20); /*END OF INTERRUPT master controller*/
}
------------------------------------------------
I was running it and the only a single message "IRQ0 fired" was on the screen. This was expected, cause I didnt programmed the PIT, so I guess it fires just once(doesnt it?). But I tried to hit some keys and nothing happened.
I know I am missing something but everything seems quite logical to me: I hit a key-> CPU recieves an IRQ-> My IDT is checked and there is my Irq1 function address, but the function is never called.

What am I missing??????????????????????

sorry for my poor english

Posted: Thu Nov 15, 2007 6:59 pm
by synthetix
Hi hstagni, I had this error before and I may be able to help you solve it.

First, if your IRQ stubs are in assembly, look for parameter order inversion:

C handler:

void IRQHandler(unsigned char IRQNumber,unsigned char IRQErrorCode);

Assembly stub:

cli
push IRQNumber
push ErrorCode ; not to do if the irq returns one already
sti

This assembly code passes the parameters in the wrong order, if your dummy error code is 0.
My dummy error code was 32, and I was passing the ISR number (IRQNumber + 32) so that my C handler would substract 32 from it. As you can imagine, I was only getting IRQs for the timer.

It should be:

cli
push ErrorCode ; not to do if the irq returns one already
push IRQNumber
sti

If it still does not work, the sources of your os could be helping. I hope it helps you !

Posted: Thu Nov 15, 2007 10:43 pm
by uglyoldbob
I thought all interrupt handlers had to return using "iret".

Posted: Fri Nov 16, 2007 12:17 am
by pcmattman
Make sure you send the EOI to the controller (output 0x20 to port 0x20 for the first controller, and I can't rememeber what to do for the second one... :shock:).

Posted: Fri Nov 16, 2007 12:57 am
by JackScott
If it is IRQ 0-7, send to master controller only.
If it is IRQ 8-15, send to master and slave controllers.

Posted: Sat Nov 17, 2007 1:13 pm
by sancho1980
by the way, when you're writing an isr for the keyboard, also make sure you actually read the scancode, even if you're "sending it to /dev/null" :-)

Posted: Sun Nov 18, 2007 8:50 am
by hstagni
It Worked! I was missing iret, so I had to write an ASM function that calls the handler that is in an handler array.
Everything worked fine, I was typing, words appeared on screen and the screen was scrolling correctly.

But I have a problem with keyboard now. My ISR for keyboard is storing chars in a queue. Then I made a function getchar():

Code: Select all

int getchar()
{
       while(IsEmpty(&KeyBuffer)); /*while key queue is empty, waits*/
       return Dequeue(&KeyBuffer);
}
It doesnt work
I checked the code hundreds of time. I printed some lines, and I discovered the KeyBuffer queue is **NOT** empty, but my 'kernel' keeps stuck in "while(IsEmpty(&KeyBuffer));".
Then, I writed some putchars inside "while(IsEmpty(&KeyBuffer));" and it magicly worked. Why? Should I put some kind of delay inside this while? Is it normal?


Anyway, thanks a lot for helping me!

Posted: Sun Nov 18, 2007 1:18 pm
by hstagni
Ok, I´ve just read this:
http://publications.gbdirect.co.uk/c_bo ... atile.html

This site has an section showing why keyword volatile was created, and it looks just like my getchar function :D

So, I´ve just add 'volatile' to my Queue struct variables and it worked. Thank u all again.