Waiting for keyboard response interrupt when setting up

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
Sanchezman
Posts: 18
Joined: Wed Nov 12, 2014 3:48 pm

Waiting for keyboard response interrupt when setting up

Post by Sanchezman »

I've started work on my Keyboard driver, and I'm having an issue when I'm trying to send commands to the device during initialization.

Here is my function to write a one-byte command (with no required data) to the keyboard.

Code: Select all

//Sends a command byte to the keyboard.
kbd_response_t send_command_byte(uint8_t cmd){

  int i = 0;

  kbd_response_t toreturn = {true, RESEND};
  
  do{
    bool waserror = send_byte_to_kbd(cmd);
    received_interrupt = false;
    //No error when sending the byte?  Then check for the response
    if(!waserror){
      
      //Loop until out keyboard interrupt says we received a response
      while(!received_interrupt);
      
      uint8_t response = inb(PS2_DATA_REG);
      
      //If we didn't get asked for a resend, then it was sent successfully
      if(response != RESEND){
	toreturn.send_error = false;
	toreturn.response_code = response;
	return toreturn;
      }
    }
  }
  while(i < MAX_RESEND_ATTEMPTS);

  //Return a keyboard response saying we encountered an error
  return toreturn;
}
Here's my keyboard interrupt handler:

Code: Select all

void handle_keyboard_interrupt(){
  if(!initialized){
    received_interrupt = true;
    return;
  }
  
  //Read the scan code
}
What I do is if I'm sending a command during initialization, I send the command and then wait in an indefinite while loop. When I receive my next keyboard interrupt, I then modify the boolean controlling the inescapable while loop such that the loop will end when I return from the interrupt. My problem is, however, that although the interrupt saying that the keyboard has read my command fires, the loop doesn't terminate. I'm assuming that this is because my loop is too fast. If I slow down the code by printing text before entering the loop (And allowing the interrupt to fire before entering the loop at all) or by doing something like printing text within the loop (And slowing it down to let it work) then there is no problem.

Obviously then, the problem is the way I wait for the interrupt to occur. I suppose my question is: What's the best way to wait for the interrupt? Should I just find some way to slow down the loop, or is it better practice to wait for the interrupt in a different way?
Octocontrabass
Member
Member
Posts: 5588
Joined: Mon Mar 25, 2013 7:01 pm

Re: Waiting for keyboard response interrupt when setting up

Post by Octocontrabass »

Code: Select all

while(!received_interrupt);
My crystal ball says you forgot a "volatile" keyword somewhere, so the compiler thinks that the loop has no exit condition and optimizes it to be truly infinite.

At some point, you should also consider what to do if the interrupt never fires.
Sanchezman
Posts: 18
Joined: Wed Nov 12, 2014 3:48 pm

Re: Waiting for keyboard response interrupt when setting up

Post by Sanchezman »

Octocontrabass wrote:My crystal ball says you forgot a "volatile" keyword somewhere, so the compiler thinks that the loop has no exit condition and optimizes it to be truly infinite.
Thank you. That did indeed do the trick.
Sanchezman
Posts: 18
Joined: Wed Nov 12, 2014 3:48 pm

Re: Waiting for keyboard response interrupt when setting up

Post by Sanchezman »

Looks like I may have spoken too quickly.

After testing the keyboard driver on a real machine as well as another VM, I run into the following issue:

If I sit and wait forever for the interrupt to fire in the send command function, it never does. However, if I exit the send command function after adding in code to allow timing out, then the next interrupt I receive is the correct response to the self test. It doesn't seem to make a difference how long I wait to time out. The interrupt never seems to fire until I've exited the function.
Octocontrabass
Member
Member
Posts: 5588
Joined: Mon Mar 25, 2013 7:01 pm

Re: Waiting for keyboard response interrupt when setting up

Post by Octocontrabass »

Code: Select all

    bool waserror = send_byte_to_kbd(cmd);
    received_interrupt = false;
Do you know what a race condition is?
Sanchezman
Posts: 18
Joined: Wed Nov 12, 2014 3:48 pm

Re: Waiting for keyboard response interrupt when setting up

Post by Sanchezman »

I don't know how I missed that. Thanks.

It turns out I had a few other problems with the way I was setting up my driver:

1. I was not sending the PS/2 controller configuration command + configuration byte properly. This was causing issues further down the line when I was expecting interrupts, but it was a simple fix.

2. How I waited for the Keyboard self test results. The PS/2 Keyboard command for self test was worded such that I expected the next interrupt to yield the results of the test. Instead, I get an acknowledgement of the command first, then the results. As such, I now have my self test wait for the interrupt and see if it's a test result or an ACK (If it's a RESEND, I try two more times). If it's a test result, I'm done, and if it's an ACK, I wait for the next interrupt to tell me the results.

It seems to be working now in Qemu, Virtualbox, and on my machine.
Post Reply