Page 1 of 1

Need some help with the Keyboard

Posted: Wed Jun 13, 2007 12:21 am
by Pyrofan1
Okay, I have my IDT and my GDT set up. I know my IDT works because I can create divide by zero exceptions. Now my keyboard isn't work, i.e. it doesn't display the key that was hit like it's suppose to.
I have attached my IRQ files and my keyboard file, I was hoping someone could help me with this.

here's my main.c file

Code: Select all

#include "kernel/video.h"
#include "kernel/memory.h"
#include "kernel/gdt.h"
#include "kernel/idt.h"
#include "kernel/irq.h"
#include "kernel/timer.h"
#include "kernel/keyboard.h"

void _main(void* mbd,unsigned int magic)
{
	clrscr();
	timer_phase(100000);
	gdt_install();
	idt_install();
	irq_install();

	irq_install_handler(1,keyboard_handler);
	irq_install_handler(0,timer_handler);
	
	for(;;);
}

Posted: Wed Jun 13, 2007 1:05 am
by os64dev
the cli statement are not really needed if you use an interrupt descriptor instead of an gate descriptor. Next you don't enable interrupts as far as i could see. And also you need to acknowledge the interrupts.

search the wiki on how to do that.

Posted: Wed Jun 13, 2007 3:54 am
by Pyrofan1
Okay, I changed my code so that I acknowledge the interrupts, but the keyboard still doesn't work. I know interrupts are enabled because I can have code like

Code: Select all

a=a/0;
and that will cause a divide my zero exception.

Posted: Wed Jun 13, 2007 4:11 am
by os64dev
just for the record, your timer interrupt also does not work?

if that is the case did you enable the irq's in port 0x21 and 0xA1?

Posted: Wed Jun 13, 2007 4:16 am
by urxae
Pyrofan1 wrote:I know interrupts are enabled because I can have code like

Code: Select all

a=a/0;
and that will cause a divide my zero exception.
Exceptions aren't controlled by the IF even though they use the IDT. The IF (the flag cleared/set by cli/sti) only controls IRQs. Examples of IRQs are those for the timer, keyboard, floppy, mouse and so on. So if you want to get keyboard interrupts you need to "sti".

Posted: Wed Jun 13, 2007 1:34 pm
by Pyrofan1
Okay now I know I have interrupts enabled because I have asm("sti"); in my code, but it still doesn't work

Code: Select all

#include "kernel/video.h"
#include "kernel/memory.h"
#include "kernel/gdt.h"
#include "kernel/idt.h"
#include "kernel/irq.h"
#include "kernel/timer.h"
#include "kernel/keyboard.h"
#include "kernel/errors.h"

void _main(void* mbd,unsigned int magic)
{
	asm("cli");
	timer_phase(100);
	gdt_install();
	idt_install();
	irq_install();

	irq_install_handler(1,keyboard_handler);
	irq_install_handler(0,timer_handler);
	
	clrscr();

	asm("sti");
	while(1);
}
When I run this code I get
Reserved exception
and my time doesn't work either. I think I'm not remapping the pic properly.

Posted: Wed Jun 13, 2007 3:49 pm
by mathematician
I can't see an EOI anywhere, which you need for any interrupt triggered by hardware external to the processor. If that is missing the timer interrupt will fire once and then the PIC will hang (because it is waiting for you to tell it that processing of the first interrupt is complete).

Somewhere before the iret you need:

mov al, 20h
out 20h, al

For IRQ line 8 and above you also need

mov al, 20h
out 0a0h, al

Maybe you've already got them, or it, but I can't see it anywhere

Posted: Wed Jun 13, 2007 4:09 pm
by Pyrofan1
I do acknowledge the interrupts with this code

Code: Select all

if(irq>=40)
{
	outportb(0xA0, 0x20);
}
outportb(0x20,0x20);

Posted: Wed Jun 13, 2007 4:28 pm
by mathematician
You don't seem to be clearing the stack after the call to irq_handler. (In C the called function will not do the job for you.)

Posted: Wed Jun 13, 2007 4:54 pm
by Pyrofan1
I thought that's what iret does

Posted: Wed Jun 13, 2007 5:30 pm
by mathematician
It will pop whatever registers were (automatically) pushed when the interrupt was called, but not anything pushed after it was called.

BTW the interrupt flag is automatically cleared when an interrupt is generated, so cli isn't strictly necessary.

Posted: Wed Jun 13, 2007 9:39 pm
by Pyrofan1
Okay, I did that and now I can press a key and have it displayed, but when I'm using the qwerty layout, it prints the qwerty key and the same key on a dvorak keyboard and when i'm using the dvorak layout I get the key and a weird character or with certain keys, the letter disappears. I have attached my code.

Posted: Thu Jun 14, 2007 4:06 am
by urxae
Pyrofan1 wrote:Okay, I did that and now I can press a key and have it displayed, but when I'm using the qwerty layout, it prints the qwerty key and the same key on a dvorak keyboard and when i'm using the dvorak layout I get the key and a weird character or with certain keys, the letter disappears. I have attached my code.
Actually, I'd wager when using a qwerty layout it prints the qwerty key when you press it and the dvorak key when you release it, correct?
And the "weird character" on dvorak only shows up when you release as well?
You forgot to filter out the release codes, which are "0x80 | code" which is "128 + code" (since the top bit of the actual code is always 0). This causes your array index to be out of bounds when you try to translate them to ascii, and so you're accessing memory after the keymap. The qwerty map is followed directly by the dvorak map, so you get extra "dvorak characters" when you release keys. After the dvorak map is some other stuff, which when interpreted as a keymap causes the "weird characters" or control codes when you release keys while using a dvorak layout.
If you have no need for the release codes (yet), just put a big "if (scancode < 0x80) {}" around the if-statement (including else clause) in your keyboard_handler.