On Thu, Apr 25, 2013 at 07:08:26PM -0400, Kevin O'Connor wrote:
My understanding is that the i8042 has two queues - one for the results of i8042 commands and one for the keyboard. Upon sending an i8042 command any reads from PORT_PS2_DATA will return data from the i8042 queue until that queue is drained. Only after that would a read from PORT_PS2_DATA return data from the keyboard queue. Otherwise, I'm not sure how one could ever reliably read the results from an i8042 command.
The above aside, we can't disable the keyboard before flushing, because we don't know the i8042 exists at all. Also, we can't send an i8042 command without verifying the i8042 is ready for a command (ie, using i8042_command(I8042_CMD_KBD_DISABLE)). However, we can't really do that until we know the i8042 exists - so it's a bit circular.
Thinking about this further, I guess one could move up the existing keyboard disable command with the patch below. That should be safe even if there is no i8042. I'd still like to further understand why keyboard data would be misinterpreted as i8042 data though.
-Kevin
--- a/src/ps2port.c +++ b/src/ps2port.c @@ -424,6 +424,16 @@ ps2_keyboard_setup(void *data) if (ret) return;
+ // Disable keyboard and mouse events. + Ps2ctr = I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; + ret = i8042_command(I8042_CMD_CTL_WCTR, &Ps2ctr); + if (ret) + return; + + ret = i8042_flush(); + if (ret) + return; + // Controller self-test. u8 param[2]; ret = i8042_command(I8042_CMD_CTL_TEST, param); @@ -443,9 +453,6 @@ ps2_keyboard_setup(void *data) return; }
- // Disable keyboard and mouse events. - SET_LOW(Ps2ctr, I8042_CTR_KBDDIS | I8042_CTR_AUXDIS); -
/* ------------------- keyboard side ------------------------*/ /* reset keyboard and self test (keyboard side) */ @@ -479,7 +486,7 @@ ps2_keyboard_setup(void *data) return;
// Keyboard Mode: disable mouse, scan code convert, enable kbd IRQ - SET_LOW(Ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT); + Ps2ctr = I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT;
/* Enable keyboard */ ret = ps2_kbd_command(ATKBD_CMD_ENABLE, NULL);