Page 1 of 1

[solved] Problems with the keyboard buffer

Posted: Mon Dec 19, 2011 1:06 am
by eaglexrlnk
Hello!

While writing own keyboard driver for my OS, I got the problem with keyboard leds - my system just freezes when I try to set them. I've noticed that it happens "thankfully" to the keyboard buffer - it just doesn't get empty. What's the matter?

Thanks,
Alex

/* Added later */
Here's the code:

Code: Select all

kbd_state_t kbd_state;

void kbd_init (void)
{
    kbd_state.shift = FALSE;
    kbd_state.ctrl = FALSE;
    kbd_state.alt = FALSE;
    kbd_state.num_lock = TRUE;
    kbd_state.caps_lock = FALSE;
    kbd_state.scroll_lock = FALSE;
    kbd_state.leds = NUM_LED;
    kbd_state.escaped = 0;
}

void update_kbd_leds (void)
{
    kbd_leds (kbd_state.leds);   /* See the kbd_leds function below */
}

void kbd_process_interrupt(void)
{
    unsigned char scancode, ascii, creg;
    scancode = inportb(0x60);
    switch(scancode) {
        case 0x36:
        case 0x2a:
            kbd_state.shift = TRUE;
            break;
            
        case 0x36+0x80:
        case 0x2a+0x80:
            kbd_state.shift = FALSE;
            break;
            
        case 0x1D:
            kbd_state.ctrl = TRUE;
            break;
            
        case 0x1D+0x80:
            kbd_state.ctrl = FALSE;
            break;
            
        case 0x38:
            kbd_state.alt = TRUE;
            break;
            
        case 0x38+0x80:
            kbd_state.alt = FALSE;
            break;
            
        default:

	    if (kbd_state.escaped) {

		switch (kbd_state.escaped) {

		    case 0xE0:
			switch (scancode) {
			    case 0x48:		//up
				ascii = 0x1C;
				break;

			    case 0x4B:		//left
				ascii = 0x1D;
				break;

			    case 0x4D:		//right
				ascii = 0x1E;
				break;

			    case 0x50:		//down
				ascii = 0x1F;
				break;
			}
			break;
		    
		    default:
			break;
		}
		
		kbd_state.escaped = 0;
	    } else {
		if (scancode == 0xE0) {
		    kbd_state.escaped = 0xE0;
		} else {
		    if(kbd_state.shift) {
			ascii = scancodes_shifted[scancode];
		    } else {
			ascii = scancodes[scancode];
		    }
		}
	    }
            break;
    }
    creg = inportb(0x61);
    creg |= 1;
    outportb(0x61, creg);
    if (scancode < 0x80) {
	keypressed (scancode, ascii);
    }
}

void kbd_wait (void)                      /* This is where we freeze */
{
    while (inportb (0x64) & 2) /* do nothing */;
}

void kbd_leds (unsigned char status)  /* And this is what doesn't work */
{
    kbd_wait ();
    outportb(0x60,0xED);
    kbd_wait ();
    outportb(0x60,status);
}

Re: Problems with the keyboard buffer

Posted: Mon Dec 19, 2011 9:49 am
by eaglexrlnk
Hmm... that's interesting. When I try to change leds status, I get keyboard interrupts with some strange scancodes. One could make conclusion that this is the source of all errors, but my keyboard ISR seems to 'eat' all the scancodes, so I just don't realize why doesn't it work.

P.S. I've downloaded some books from the net. Hope there is something that would help me.

Re: Problems with the keyboard buffer

Posted: Mon Dec 19, 2011 1:14 pm
by gerryg400

Code: Select all

while (inportb (0x64) & 2) /* do nothing */;
You should never do this when talking to hardware. You should calculate how long you expect to wait for the bit to change and then use a counter or timer to break out of the loop if something goes wrong. You can then reset the hardware and try again.

Re: Problems with the keyboard buffer

Posted: Mon Dec 19, 2011 1:44 pm
by eaglexrlnk
gerryg400 wrote:You should calculate how long you expect to wait for the bit to change and then use a counter or timer to break out of the loop if something goes wrong.

Code: Select all

void kbd_wait (void)
{
    unsigned int counter = 0;
    while (inportb (0x64) & 2) {
        if (++counter > KBD_WAIT_TIMEOUT)
            break;
    }
}
Something like this?

Re: Problems with the keyboard buffer

Posted: Mon Dec 19, 2011 2:01 pm
by gerryg400
Yes that's fine. Does it work like this ?

Re: Problems with the keyboard buffer

Posted: Tue Dec 20, 2011 12:04 pm
by eaglexrlnk
Now my system doesn't get freezed, but I still cannot change leds' status.

Re: Problems with the keyboard buffer

Posted: Tue Dec 20, 2011 1:16 pm
by gerryg400
What type of system ? Is it a VM ?

Re: Problems with the keyboard buffer

Posted: Tue Dec 20, 2011 11:14 pm
by eaglexrlnk
No, it does work properly in VM, but it doesn't work on the real hardware.

Re: Problems with the keyboard buffer

Posted: Wed Dec 21, 2011 6:31 am
by evoex
I'm not at all sure about it, but if you have an interrupt handler that also "eats" the input from port 0x64 and also affects it, this code might never be able to read it. Maybe as a quick test you could try disabling interrupts before starting the test, and reenabling it afterwards.

Edit: Ah the interrupt handler is there. And I believe it actually send data to the port.

Re: [solved] Problems with the keyboard buffer

Posted: Mon Dec 26, 2011 12:06 pm
by eaglexrlnk
Finally it works properly)
Many thanks to gerryg400 for his great advice about loop in the kbd_wait function (actually there was such function when I started this topic, but now I have got two ones: kbd_wait_inbuf and kbd_wait_outbuf, but it doesn't matter, they also have such loops) and to evoex for giving right directions on where should I search for the source of all my errors.