Page 1 of 1

Keyboard BAT returns 0xFA

Posted: Tue Jun 01, 2010 9:36 am
by chibicitiberiu
Okay, so I know that a successful BAT test for the keyboard, returns 0xAA. But this is not the case on another computer... it returns 0xFA, that is ACK. Is that normal? Why doesn't it respond to an ECHO command send right after the BAT...?

Here is the code:

Code: Select all

void kb_test()
{
      char hex[] = "0123456789ABCDEF";
      byte temp=0;

      puts("\nTHIS WILL TEST FEW COMMANDS OF THE PS/2 KEYBOARD.\n");
      

      puts("\nResetting the keyboard... ");
      //while ((inportb(0x64)&2)!=0);
      outportb(0x60, 0xFF);
      while ((inportb(0x64)&4)==0);            
      temp = inportb(0x60);
      putc_font('[', 0x07, 0x02);
      putc_font(hex[temp/16], 0x07, 0x02);
      putc_font(hex[temp%16], 0x07, 0x02);
      putc_font(']', 0x07, 0x02);


      puts("\nEcho... ");
      while ((inportb(0x64)&2)!=0);
      outportb(0x60, 0xEE);
      if (inportb(0x60) == 0xEE) puts_font("[OK]    ", 0x07, 0x02);

      
      puts("\nSet LEDs - SCROLL on... ");
      while ((inportb(0x64)&2)!=0);
      outportb(0x60, 0xED);
      while ((inportb(0x64)&2)!=0);
      outportb(0x60, 1);
      if (inportb(0x60) == 0xFA) puts_font("[ACK]    ", 0x07, 0x02);


      puts("\nGet current scancode set... ");
      while ((inportb(0x64)&2)!=0);
      outportb(0x60, 0xF0);
      while ((inportb(0x64)&2)!=0);
      outportb(0x60, 0);

      temp = inportb(0x60);
      putc_font('[', 0x07, 0x02);
      putc_font(hex[temp/16], 0x07, 0x02);
      putc_font(hex[temp%16], 0x07, 0x02);
      putc_font(']', 0x07, 0x02);
      
      
      puts("\nTurning on 2 leds (don't know which ones :P)... ");
      while ((inportb(0x64)&2)!=0);
      outportb(0x60, 0xED);
      while ((inportb(0x64)&2)!=0);
      outportb(0x60, (byte)1|2);
      if (inportb(0x60) == 0xFA) puts_font("[ACK]    ", 0x07, 0x02);

}
I know this code is a big mess... but it should work

I also had trouble with the instruction
while ((inportb(0x64)&2)!=0);
that was commented before starting the BAT test. It was running an infinite loop.


And by the way, the testbed is a COMPAQ, Pentium 2, 400 MHz, 128MB RAM.
The keyboard is a bit buggy, it had some... accidents :D... like hot tea all over it. It also gives an error on the POST screen, but I skip that by pressing F1, and it works fine.

Re: Keyboard BAT returns 0xFA

Posted: Wed Jun 02, 2010 3:19 am
by chibicitiberiu
Hmmm... I discovered that after sending command 0xFF to the keyboard, it sends back the following responses: 0xFA (ack), 0xFE and when it finishes 0xAA (that is successful BAT). Bit4 from the keyboard status doesn't tell if the BAT test is done or not, so the other instructions, like echo, were trying to send a command while the keyboard was testing, that resulted of course in failure.

But still, it doesn't explain why that commented
while ((inportb(0x64)&2) != 0)
doesn't work. (the one just before sending command 0xFF).

Re: Keyboard BAT returns 0xFA

Posted: Wed Jun 02, 2010 4:11 am
by Nugget
I happen to have a copy of "The Undocumented PC" open in front of me at the moment, so I thought I'd take a look...

In general, when checking status from port 0x64, you should check bit1 (0x02) is zero before doing any write to port 0x60 or 0x64, to check that the input buffer is ready for a write, and check bit0 (0x01) is one before doing any read from port 0x60, to check that there is a byte ready to read. Your code appears to be missing some of these, so best to check they're in the right places.

Bit2 (0x04) is documented as: 0=Power-on caused reset, 1=Successful completion of self-test. Sounds like that should get set to one once the self-test is finished, but I think you still need to check bit0 before reading the 0xAA result.

I'm not sure why the line you've commented out is getting stuck. It should be fine. Are you sure that's where the problem is?

Re: Keyboard BAT returns 0xFA

Posted: Wed Jun 02, 2010 4:14 am
by chibicitiberiu
Nugget wrote:I happen to have a copy of "The Undocumented PC" open in front of me at the moment, so I thought I'd take a look...

In general, you should check bit1 (0x02) is zero before doing any write to port 0x60 or 0x64, to check that the input buffer is ready for a write, and check bit0 (0x01) is one before doing any read from port 0x60, to check that there is a byte ready to read. Your code appears to be missing some of these, so best to check they're in the right places.

Bit2 (0x04) is documented as: 0=Power-on caused reset, 1=Successful completion of self-test. Sounds like that should get set to one once the self-test is finished, but I think you still need to check bit0 before reading the 0xAA result.

I'm not sure why the line you've commented out is getting stuck. It should be fine. Are you sure that's where the problem is?
Yes, i'm sure. The puts instruction just before it works, but it doesn't reach the lines where it displays the return code.

Re: Keyboard BAT returns 0xFA

Posted: Wed Jun 02, 2010 4:39 am
by gerryg400
I use a function like this. I think it's good policy not to rely on HW to get you out of the loop. I do a similar thing when waiting for apics etc. I probably should have some sort of recovery mechanism although in this case you're about to reset anyway so it doesn't matter.

Code: Select all

void i8042_empty_inbuf() {

	long cnt = 100000;

	while ((inportb(0x64) & 0x02)  && --cnt)
		;
}

Re: Keyboard BAT returns 0xFA

Posted: Wed Jun 02, 2010 9:18 am
by Nugget
The example code in the book also has a lot of code relating to timeouts. More interesting is a line that does an IN on port 0x60 before checking bit1 and writing the command to port 0x60.

You could try doing a read on port 0x60 at the start of your code. Maybe there's something in the buffer and won't let you continue until you've read it.