[solved] Problems with the keyboard buffer

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
User avatar
eaglexrlnk
Posts: 11
Joined: Tue Nov 08, 2011 8:30 am
Location: Ukraine

[solved] Problems with the keyboard buffer

Post 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);
}
Last edited by eaglexrlnk on Mon Dec 26, 2011 11:53 am, edited 3 times in total.
"A
computer program
does what you tell it
to do, not what you
want it to do." --
Greer's Third Law
User avatar
eaglexrlnk
Posts: 11
Joined: Tue Nov 08, 2011 8:30 am
Location: Ukraine

Re: Problems with the keyboard buffer

Post 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.
"A
computer program
does what you tell it
to do, not what you
want it to do." --
Greer's Third Law
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Problems with the keyboard buffer

Post 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.
If a trainstation is where trains stop, what is a workstation ?
User avatar
eaglexrlnk
Posts: 11
Joined: Tue Nov 08, 2011 8:30 am
Location: Ukraine

Re: Problems with the keyboard buffer

Post 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?
"A
computer program
does what you tell it
to do, not what you
want it to do." --
Greer's Third Law
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Problems with the keyboard buffer

Post by gerryg400 »

Yes that's fine. Does it work like this ?
If a trainstation is where trains stop, what is a workstation ?
User avatar
eaglexrlnk
Posts: 11
Joined: Tue Nov 08, 2011 8:30 am
Location: Ukraine

Re: Problems with the keyboard buffer

Post by eaglexrlnk »

Now my system doesn't get freezed, but I still cannot change leds' status.
"A
computer program
does what you tell it
to do, not what you
want it to do." --
Greer's Third Law
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Problems with the keyboard buffer

Post by gerryg400 »

What type of system ? Is it a VM ?
If a trainstation is where trains stop, what is a workstation ?
User avatar
eaglexrlnk
Posts: 11
Joined: Tue Nov 08, 2011 8:30 am
Location: Ukraine

Re: Problems with the keyboard buffer

Post by eaglexrlnk »

No, it does work properly in VM, but it doesn't work on the real hardware.
"A
computer program
does what you tell it
to do, not what you
want it to do." --
Greer's Third Law
evoex
Member
Member
Posts: 103
Joined: Tue Dec 13, 2011 4:11 pm

Re: Problems with the keyboard buffer

Post 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.
User avatar
eaglexrlnk
Posts: 11
Joined: Tue Nov 08, 2011 8:30 am
Location: Ukraine

Re: [solved] Problems with the keyboard buffer

Post 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.
"A
computer program
does what you tell it
to do, not what you
want it to do." --
Greer's Third Law
Post Reply