Keyboard Interrupt

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Whatever5k

Keyboard Interrupt

Post by Whatever5k »

I have built my own IDT with all interrupts having the same ISR (common_isr). common_isr does nothing then print a message "Key pressed"
on the screen...
Ok, I first disable interrupts, unmask IRQ1(keyboard) and enable interrupts...
When I call bochs, there is just one "Key pressed" on the screen. And when I press on the keyboard, no more messages appear. I suppose, that the one message comes even not from the keyboard, but from another interrupt (since every IDT descriptor has the same interrupt
handler).
Why do I not get the "Key pressed" messages?
Curufir

Re:Keyboard Interrupt

Post by Curufir »

Are you clearing the interrupt off the PIC.

Ie.

MOV AL, 0x20
OUT 0x20, AL

Or something similar. Think it won't process another IRQ until that is done.

Curufir
Whatever5k

Re:Keyboard Interrupt

Post by Whatever5k »

Ouch!
I forgot that! Ok, but then, there were endless messages printed out. I figured out, that it was the system clock and disabled that. So now I have the system clock disabled and the keyboard enabled, but when I press a key, no message is printed. Actually, no message of "key pressed" is printed out...
Why?
PlayOS

Re:Keyboard Interrupt

Post by PlayOS »

Need to see some code for this one I think. :)
Whatever5k

Re:Keyboard Interrupt

Post by Whatever5k »

Ok, this is the common_isr:

Code: Select all

common_isr:
            extern testfunc
   call testfunc
   iret
This is the function testfunc():

Code: Select all

void testfunc(void)
{
   asm("cli");
   printk("key pressed/released\n");
   send_eoi(1);
   asm("sti");
}
And this here enables everything:

Code: Select all

/* first, remap the PICs to avoid conflicts with exceptions */
   remap_pics(0x20, 0x28);
   printk("PICs remapped: IRQs starting at interrupt 0x20\n");

   asm("cli");
   disable_irq(0);
   enable_irq(1);
   printk("Enabled IRQ1\n");
   printk("Enabling interrupts\n");
   asm("sti");
Any ideas?
PlayOS

Re:Keyboard Interrupt

Post by PlayOS »

I cant really see a problem, sorry.

However I dont know why you disable/enable interrupts inside of your ISR. Try removing them. I am pretty sure that only exceptions (int0-31) can happen here. :)

Also what is the state of your second PIC are those IRQ's masked out?
Whatever5k

Re:Keyboard Interrupt

Post by Whatever5k »

Removing "sti" and "cli" does not help...
I do nothing with the second PIC. So they are all unmasked (enabled)
PlayOS

Re:Keyboard Interrupt

Post by PlayOS »

Well if one of them goes off then you need to send an End Of Interrupt to PIC2 as well as PIC1.

mov al, 0x20
out 0xa0, al

None of the second lot of IRQs should be going off, but it is worth the try, just disable bit 2 'disable_irq(2)' to disable them and see what happens then.
Whatever5k

Re:Keyboard Interrupt

Post by Whatever5k »

Well, maybe it's helpful to look at the enable/disable_irq() code:

Code: Select all

unsigned short int ocw1 = 0xFFFF;   /* short int = 16 bits */

void remap_pics(int pic1, int pic2)
{
   /* send ICW1 */
   outb(PIC1, ICW1);
   outb(PIC2, ICW1);

   /* send ICW2 */
   outb(PIC1 + 1, pic1);   /* remap
   outb(PIC2 + 2, pic2);      pics */

   /* send ICW3 */
   outb(PIC1 + 1, 4);   /* IRQ2 -> connection to slave */
   outb(PIC2 + 2, 2);

   /* send ICW4 */
   outb(PIC1 + 1, ICW4);
   outb(PIC2 + 1, ICW4);

   /* disable all IRQs */
   outb(PIC1 + 1, 0xFF);
}

/* enable_irq()
 * sends command to PIC to enable an IRQ
 */
void enable_irq(int irq)
{
   ocw1 &= ~(1 << irq);   /* enable propriate bit with shifting to left
               invert the thing to enable the interrupt
               use AND operation to leave the other bits
               as they are
             */
   if (irq < 8)
      outb(PIC1 + 1, ocw1&0xFF);   /* AND with 0xFF to clear the high 8 
                       bits because we send to PIC1
                   */
   else
      outb(PIC2 + 1, ocw1 >> 8);   /* move high 8 bits to low 8 bits
                     since we send to PIC2
                   */
}

/* disable_irq()
 * sends a command to PIC to disable an IRQ
 */
void disable_irq(int irq)
{
   ocw1 |= (1 << irq);   /* shift left to disable the propriate bit
               OR to not change the mask
             */

   if (irq < 8)
      outb(PIC1 + 1, ocw1&0xFF);   /* AND with 0xFF to clear the
                     high 8 bits since we send to PIC1
                   */
   else
      outb(PIC2 + 1, ocw1 >> 8);   /* move high 8 bits to low 8 bits since
                     we send to PIC2
                   */
}

/* send_eoi()
 * sends a EOI to the PICs involved in the IRQ operation
 */
void send_eoi(int irq)
{
   if (irq > 7)
      outb(PIC2, 0x20);
   outb(PIC1, 0x20);
}
What do you think, this should work, shouldn't it?

When I compile it with that code and disable irq 2, there's ONE message printed out, but no more...
PlayOS

Re:Keyboard Interrupt

Post by PlayOS »

Whatever5k wrote: void remap_pics(int pic1, int pic2)
{
......

???/* send ICW2 */
???outb(PIC1 + 1, pic1);???/* remap
???outb(PIC2 + 2, pic2);??? pics */

???/* send ICW3 */
???outb(PIC1 + 1, 4);???/* IRQ2 -> connection to slave */
???outb(PIC2 + 2, 2);

.......
}
shouldn't outb(PIC2 + 2, 2); be outb(PIC2 + 1, 2);

Thats just a first observation (typo's just hate em'), still looking at the rest. :)
Whatever5k

Re:Keyboard Interrupt

Post by Whatever5k »

Ah right...
And...I got it!
Do you know what was wrong? Actually nothing! But: I need to tell the keyboard that I have succesfully received the code...
I did it like that (copy&paste from s.o.'s code):

Code: Select all

int scan;
   register int i;
   
   printk("key pressed/released\n");
   scan = inb(0x60);
   i = inb(0x61);
   outb(0x61, i|0x80);
   outb(0x61, i);
   send_eoi(1);
That's it, now I get a message for every press&release!
Thanks for your help!
PlayOS

Re:Keyboard Interrupt

Post by PlayOS »

Your very welcome, now I can go to bed, its like 2:38am in the morning over here in australia. :)
Whatever5k

Re:Keyboard Interrupt

Post by Whatever5k »

Hehe, sorry for have having kept you so long awaken.
But I'll keep that in mind, I won't forget...
PlayOS

Re:Keyboard Interrupt

Post by PlayOS »

Thats ok, I'm just glad that I could help you. ;D
Post Reply