Page 1 of 1

problem with irq

Posted: Sun May 11, 2008 1:45 pm
by asdfgh
i have remapped the pic.

but when i press a keyboard button nothing happens..

i have written a function for interrupt 33 which is for keyboard

???

Code: Select all

#define ICW1 0x11
#define PICC1 0x20
#define PICC2 0xA0
#define PICD1 0x21
#define PICD2 0xA1

void idt_install()//install the idt and enable interrupts
{
   kprint("Installing IDT                ");
/*Here is where we set all of our idt entries*/
idt_set_gate(0,cast_uint(isr0),0x08,0x8E);
idt_set_gate(1,cast_uint(isr1),0x08,0x8E);
idt_set_gate(2,cast_uint(isr2),0x08,0x8E);
idt_set_gate(3,cast_uint(isr3),0x08,0x8E);
idt_set_gate(4,cast_uint(isr4),0x08,0x8E);
idt_set_gate(5,cast_uint(isr5),0x08,0x8E);
idt_set_gate(6,cast_uint(isr6),0x08,0x8E);
idt_set_gate(7,cast_uint(isr7),0x08,0x8E);
idt_set_gate(8,cast_uint(isr8),0x08,0x8E);
idt_set_gate(9,cast_uint(isr9),0x08,0x8E);
idt_set_gate(10,cast_uint(isr10),0x08,0x8E);
idt_set_gate(11,cast_uint(isr11),0x08,0x8E);
idt_set_gate(12,cast_uint(isr12),0x08,0x8E);
idt_set_gate(13,cast_uint(isr13),0x08,0x8E);
idt_set_gate(14,cast_uint(isr14),0x08,0x8E);
idt_set_gate(15,cast_uint(isr15),0x08,0x8E);
idt_set_gate(16,cast_uint(isr16),0x08,0x8E);
 
/*********************************************/
     remap_pic();
   idt_set_gate(32,cast_uint(isr32),0x08,0x8E);
   idt_set_gate(33,cast_uint(isr33),0x08,0x8E);
 idt_p.limit = sizeof(struct idt_entry) * 256 -1;
   idt_p.base  = cast_uint(&idt_entries);
   idt_flush();//load the idtr with the idt pointer
   kprint("DONE\n");
}

void remap_pic()//for more info check out brokenthorn tuts
{
outb(PICC1,ICW1);//init pic 1
outb(PICC2,ICW1);//init pic 2
outb(PICD1,0x20);//remap irq0-7 to 0x20-0x27
outb(PICD2,0x28);//remap irq8+ to 0x28+
outb(PICD1,0x4);//ICW3
outb(PICD2,0x2);//ICW3 to second pic
outb(PICD1,0x1);//ICW4
outb(PICD2,0x1);//^
outb(PICD1,0);//null out the register values
outb(PICD2,0);
}

Posted: Sun May 11, 2008 3:51 pm
by Alboin
Did you enable interrupts? (sti)

Posted: Sun May 11, 2008 3:58 pm
by asdfgh
ya... all other interrupts from 0 to 31 are working fine...
but only these irq's are not workking..

Posted: Sun May 11, 2008 7:52 pm
by bewing
The "interrupts" from 0 to 31 are actually called exceptions, and do not need STI. Please check carefully that your STI command really did run -- that truly is the most likely reason that you are not getting IRQs. Are you running in an emulator? If so, check the EFLAGS IF bit.

If you are running this on real hardware, then there is the possibility that you have a machine with APIC enabled. If APIC is enabled, then remapping the PIC does not work the same way, exactly.

Posted: Mon May 12, 2008 1:24 am
by JamesM
The other thing that I can think of is that you're silently handling IRQs (for instance, a PIT timer IRQ on IRQ0) but not ACKing them correctly.

Until you ACK an IRQ, you will not recieve another.

Posted: Mon May 12, 2008 3:11 am
by asdfgh
when i enable sti the timer keeps on executing..... and prints numbers...
when i press keyboard i gives an interrupt only for the first press after which nothing happens

Code: Select all

void timer_isr()
{
	ticks++;
	print_int(ticks);
	outb(0x20, 0x20);
}

void keyboard_isr()
{
kprint("keypressed\n");
outb(0x20, 0x20);
}


Posted: Mon May 12, 2008 3:34 am
by JamesM
asdfgh wrote:when i enable sti the timer keeps on executing..... and prints numbers...
when i press keyboard i gives an interrupt only for the first press after which nothing happens

Code: Select all

void timer_isr()
{
	ticks++;
	print_int(ticks);
	outb(0x20, 0x20);
}

void keyboard_isr()
{
kprint("keypressed\n");
outb(0x20, 0x20);
}

Hi,

This behaviour is correct. The keyboard will only interrupt while its buffer is not full. If its buffer is full and a key is pressed, an interrupt will not occur. You must read port --0x64-- EDIT no, it's 0x60 to empty the buffer.

Cheers,

James

Posted: Mon May 12, 2008 3:38 am
by egos
asdfgh, try this.

1)

Code: Select all

void keyboard_isr()
{
char c = inb(0x60);
kprint("keypressed\n");
outb(0x20, 0x20);
}
2) send command 0xAE or clean bit 4 of command byte.

Posted: Mon May 12, 2008 7:08 am
by CmpXchg
What is more, a keyboard ISR should set the 7-th bit in the port 61h, and then return it to its previous value. Like this:

Code: Select all

in al,61h
push ax
or al,80h
out 61h,al
pop ax
out 61h,al
Unless it's done, the keyboard won't send any more IRQ's.

Posted: Mon May 12, 2008 7:11 am
by JamesM
CmpXchg wrote:What is more, a keyboard ISR should set the 7-th bit in the port 61h, and then return it to its previous value. Like this:

Code: Select all

in al,61h
push ax
or al,80h
out 61h,al
pop ax
out 61h,al
Unless it's done, the keyboard won't send any more IRQ's.
That's incorrect. Port 61h does not need to be touched for IRQs to fire.

Posted: Mon May 12, 2008 7:34 am
by CmpXchg
JamesM wrote:Port 61h does not need to be touched for IRQs to fire.
But James, haven't you written that
JamesM wrote:Until you ACK an IRQ, you will not recieve another.
Port 61h seems to be that missing ACK, besides sending 20h to port 20h.

Of course, I'm not entirely sure it is really so, it's from a book on x86 assembly programming. I will try it out under DOS.

Posted: Mon May 12, 2008 7:53 am
by AJ
I believe that the ACK mentioned in your second quote was referring to writing an EOI port 0x20.

Reading from port 0x60 is enough for the KBC - you do not need to separately send an ACK to port 0x61.

Cheers,
Adam

Posted: Mon May 12, 2008 8:16 am
by JamesM
AJ wrote:I believe that the ACK mentioned in your second quote was referring to writing an EOI port 0x20.
Quite so, sorry for the ambiguity.

Posted: Mon May 12, 2008 12:04 pm
by bewing
CmpXchg wrote:What is more, a keyboard ISR should set the 7-th bit in the port 61h, and then return it to its previous value. Like this:

Code: Select all

in al,61h
push ax
or al,80h
out 61h,al
pop ax
out 61h,al
Unless it's done, the keyboard won't send any more IRQ's.
This is mostly for very old machines.
More accurately, if several scancodes come from the keyboard before the IRQ gets serviced, you are supposed to toggle that "keyboard disable" bit in order to get the next scancode in the buffer. Otherwise, the old keyboard controller chip would keep giving you the same scancode over and over again.
But it is not necessary on anything built after 1995, or something.

Posted: Wed May 14, 2008 7:45 am
by CmpXchg
bewing wrote:Otherwise, the old keyboard controller chip would keep giving you the same scancode over and over again.
Exactly.

So why not to add the following code:

Code: Select all

in al,61h
or al,80h
out 61h,al