Page 1 of 1

Keyboard not working.

Posted: Sat Jul 02, 2011 10:18 pm
by Lionel
Hello!,
I'm sorry about another possibly noobish question.
Anyway, I was following Bran's tutorial. And I was on the last part (keyboard) and when I added it to the list of things to compile and link, everything was ok. But when I run it, I get this:Image
keyboard_handler(); never gets called, so no output is printed.
Could someone help me please?
kb.c

Code: Select all

#include "common.h"

/* KBDUS means US Keyboard Layout. This is a scancode table
*  used to layout a standard US keyboard. I have left some
*  comments in to give you an idea of what key is what, even
*  though I set it's array index to 0. You can change that to
*  whatever you want using a macro, if you wish! */
unsigned char kbdus[128] =
{
    0,  27, '1', '2', '3', '4', '5', '6', '7', '8',	/* 9 */
  '9', '0', '-', '=', '\b',	/* Backspace */
  '\t',			/* Tab */
  'q', 'w', 'e', 'r',	/* 19 */
  't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',		/* Enter key */
    0,			/* 29   - Control */
  'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',	/* 39 */
 '\'', '`',   0,		/* Left shift */
 '\\', 'z', 'x', 'c', 'v', 'b', 'n',			/* 49 */
  'm', ',', '.', '/',   0,					/* Right shift */
  '*',
    0,	/* Alt */
  ' ',	/* Space bar */
    0,	/* Caps lock */
    0,	/* 59 - F1 key ... > */
    0,   0,   0,   0,   0,   0,   0,   0,
    0,	/* < ... F10 */
    0,	/* 69 - Num lock*/
    0,	/* Scroll Lock */
    0,	/* Home key */
    0,	/* Up Arrow */
    0,	/* Page Up */
  '-',
    0,	/* Left Arrow */
    0,
    0,	/* Right Arrow */
  '+',
    0,	/* 79 - End key*/
    0,	/* Down Arrow */
    0,	/* Page Down */
    0,	/* Insert Key */
    0,	/* Delete Key */
    0,   0,   0,
    0,	/* F11 Key */
    0,	/* F12 Key */
    0,	/* All other keys are undefined */
};

/* Handles the keyboard interrupt */
void keyboard_handler(struct regs *r)
{
    unsigned char scancode;

    /* Read from the keyboard's data buffer */
    scancode = kinportb(0x60);

    /* If the top bit of the byte we read from the keyboard is
    *  set, that means that a key has just been released */
    if (scancode & 0x80)
    {
        /* You can use this one to see if the user released the
        *  shift, alt, or control keys... */
    }
    else
    {
        /* Here, a key was just pressed. Please note that if you
        *  hold a key down, you will get repeated key press
        *  interrupts. */

        /* Just to show you how this works, we simply translate
        *  the keyboard scancode into an ASCII value, and then
        *  display it to the screen. You can get creative and
        *  use some flags to see if a shift is pressed and use a
        *  different layout, or you can add another 128 entries
        *  to the above layout to correspond to 'shift' being
        *  held. If shift is held using the larger lookup table,
        *  you would add 128 to the scancode when you look for it */
        putch(kbdus[scancode]);
    }
}

/* Installs the keyboard handler into IRQ1 */
void keyboard_install()
{
    irq_install_handler(1, keyboard_handler);
}
irq.c

Code: Select all

#include "common.h"

/* These are own ISRs that point to our special IRQ handler
*  instead of the regular 'fault_handler' function */
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();

/* This array is actually an array of function pointers. We use
*  this to handle custom IRQ handlers for a given IRQ */
void *irq_routines[16] =
{
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
};

/* This installs a custom IRQ handler for the given IRQ */
void irq_install_handler(int irq, void (*handler)(struct regs *r))
{
    irq_routines[irq] = handler;
    puts("Handler Installed!\n");
}

/* This clears the handler for a given IRQ */
void irq_uninstall_handler(int irq)
{
    irq_routines[irq] = 0;
}

/* Normally, IRQs 0 to 7 are mapped to entries 8 to 15. This
*  is a problem in protected mode, because IDT entry 8 is a
*  Double Fault! Without remapping, every time IRQ0 fires,
*  you get a Double Fault Exception, which is NOT actually
*  what's happening. We send commands to the Programmable
*  Interrupt Controller (PICs - also called the 8259's) in
*  order to make IRQ0 to 15 be remapped to IDT entries 32 to
*  47 */
void irq_remap(void)
{
    koutportb(0x20, 0x11);
    koutportb(0xA0, 0x11);
    koutportb(0x21, 0x20);
    koutportb(0xA1, 0x28);
    koutportb(0x21, 0x04);
    koutportb(0xA1, 0x02);
    koutportb(0x21, 0x01);
    koutportb(0xA1, 0x01);
    koutportb(0x21, 0x0);
    koutportb(0xA1, 0x0);
    putsid(2,"IRQ Installer", "IRQ remapped successfully!");
}

/* We first remap the interrupt controllers, and then we install
*  the appropriate ISRs to the correct entries in the IDT. This
*  is just like installing the exception handlers */
void irq_install()
{
    irq_remap();
    idt_set_gate(32, (unsigned)irq0, 0x08, 0x8E);
    idt_set_gate(33, (unsigned)irq1, 0x08, 0x8E);
    idt_set_gate(34, (unsigned)irq2, 0x08, 0x8E);
    idt_set_gate(35, (unsigned)irq3, 0x08, 0x8E);
    idt_set_gate(36, (unsigned)irq4, 0x08, 0x8E);
    idt_set_gate(37, (unsigned)irq5, 0x08, 0x8E);
    idt_set_gate(38, (unsigned)irq6, 0x08, 0x8E);
    idt_set_gate(39, (unsigned)irq7, 0x08, 0x8E);
    idt_set_gate(40, (unsigned)irq8, 0x08, 0x8E);
    idt_set_gate(41, (unsigned)irq9, 0x08, 0x8E);
    idt_set_gate(42, (unsigned)irq10, 0x08, 0x8E);
    idt_set_gate(43, (unsigned)irq11, 0x08, 0x8E);
    idt_set_gate(44, (unsigned)irq12, 0x08, 0x8E);
    idt_set_gate(45, (unsigned)irq13, 0x08, 0x8E);
    idt_set_gate(46, (unsigned)irq14, 0x08, 0x8E);
    idt_set_gate(47, (unsigned)irq15, 0x08, 0x8E);
    putsid(2,"IRQ Installer", "IRQ has been installed successfully!");
}

/* Each of the IRQ ISRs point to this function, rather than
*  the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
*  to be told when you are done servicing them, so you need
*  to send them an "End of Interrupt" command (0x20). There
*  are two 8259 chips: The first exists at 0x20, the second
*  exists at 0xA0. If the second controller (an IRQ from 8 to
*  15) gets an interrupt, you need to acknowledge the
*  interrupt at BOTH controllers, otherwise, you only send
*  an EOI command to the first controller. If you don't send
*  an EOI, you won't raise any more IRQs */
void irq_handler(struct regs *r)
{
    /* This is a blank function pointer */
    void (*handler)(struct regs *r);

    /* Find out if we have a custom handler to run for this
    *  IRQ, and then finally, run it */
    handler = irq_routines[r->int_no - 32];
    if (handler)
    {
        handler(r);
        putsid(2,"IRQ", "IRQ handled!");
    }

    /* If the IDT entry that was invoked was greater than 40
    *  (meaning IRQ8 - 15), then we need to send an EOI to
    *  the slave controller */
    if (r->int_no >= 40)
    {
        koutportb(0xA0, 0x20);
    }

    /* In either case, we need to send an EOI to the master
    *  interrupt controller too */
    koutportb(0x20, 0x20);
}
I even copied the code exactly from the tutorial(making edits like making outportb koutportb)
I thank you in advance for any help received.
~Lionel

Re: Keyboard not working.

Posted: Sat Jul 02, 2011 10:31 pm
by thepowersgang
Have you enabled interrupts? Is the IDT entry correct? What does bochs say about the keyboard controller state?

Re: Keyboard not working.

Posted: Sat Jul 02, 2011 10:41 pm
by Lionel
I enabled interrupts with __asm__ __volatile__ ("sti");
The IDT has been installed successfully and the entry is correct.
And I use qemu (Shown in screenshot), so I don't know about it's state.

Re: Keyboard not working.

Posted: Sat Jul 02, 2011 11:01 pm
by thepowersgang
That was actually a hint to use bochs as well (I use Qemu mostly nowadays, but for low level bugs, Bochs comes out again)

I remember that I used to hit a bug in Qemu (or, at least my keyboard code did) where I never got an interrupt, try reading from the keyboard data port after enabling the keyboard driver, that may fix things (as it ACKs any interrupts delivered before the handler is assigned)

Re: Keyboard not working.

Posted: Sat Jul 02, 2011 11:09 pm
by Lionel
I always find bochs hard to use. But I'll try it again.

Re: Keyboard not working.

Posted: Sat Jul 02, 2011 11:27 pm
by Lionel
Sorry for the double-post. but bochs does it too.

Re: Keyboard not working.

Posted: Sun Jul 03, 2011 2:00 am
by Karlosoft
My keyboard driver still doesn't work on bochs but I solved lots of problem on real hardware asking a restart of the keyboard with commands.

Re: Keyboard not working.

Posted: Mon Jul 04, 2011 10:20 am
by Luns
In your PIC remap function, it looks a message is supposed to be printed to the screen. Is that the case? Because I don't see the output in your screenshot.

Do you know if your irq_handler function ever gets called?

Re: Keyboard not working.

Posted: Mon Jul 04, 2011 3:16 pm
by Lionel
No, the irq handler is never called.

Re: Keyboard not working.

Posted: Mon Jul 04, 2011 3:39 pm
by Nessphoro
Hmm printf "key pressed" in the keyboard_handler

Re: Keyboard not working.

Posted: Tue Jul 05, 2011 2:57 am
by Lionel
Nevermind about this, I got it working , I don't know that happened but restarting the kernel from scratch helped!