Re: i8042 access timings

From: Andries Brouwer
Date: Thu Jan 27 2005 - 15:25:55 EST


On Thu, Jan 27, 2005 at 08:23:07AM +0200, Jaco Kroon wrote:

> i8042_check_aux: param_in=0x5a, command=AUX_LOOP, param_out=5a <= -1
> i8042_check_aux: param_in=??, command=AUX_TEST, param_out=a5 <= 0

The code is

param = 0x5a;
if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0xa5) {
if (i8042_command(&param, I8042_CMD_AUX_TEST)
|| (param && param != 0xfa && param != 0xff))
return -1;
}

where
#define I8042_CMD_AUX_LOOP 0x11d3: write d3, write 5a, read ->param
#define I8042_CMD_AUX_TEST 0x01a9: write a9, read ->param

In my docs (http://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html#ss10.3)
d3 is classified under "Obscure, probably obsolete, commands".
The reason is that there is hardware that does not implement d3.
Originally it was special to MCA. Later it was also used as part of
the Synaptics multiplexing handshake.

Now you read one byte after the command a9 and get a5 - clearly the 5a
that was written and complemented. So it looks like the d3 really worked.

The first i8042_command() returned -1, but it really wrote the 5a,
so it did i8042_write_command(d3) and i8042_write_data(5a) and then
the i8042_wait_read() returned -1, a timeout.

Since the byte was there to read, the flag was lost that indicated
that data was available. Hmm. Sequence of actions:

inb(64); // until bit 1 clear
outb(d3, 64);
inb(64); // until bit 1 clear
outb(5a, 60);
inb(64); // until bit 0 set - timeout

inb(64); // until bit 1 clear
outb(a9, 64);
inb(64); // until bit 0 set
inb(64); // test for AUX
inb(60);

I am afraid I don't understand what happens.
One can imagine that the second inb(64) comes too quickly
so that we write the 5a too quickly. But all happens as it
should: the d3 is executed, the 5a is moved from input buffer
to output buffer, the AUXB bit is set, only the ready flag never comes,
not within I8042_CTL_TIMEOUT=10000 times 50 usec, that is 0.5 sec.

By the way, I have some old docs that describe sending a command by
repeat inb(64) until bit 1 clear
outb(cmd, 64)
repeat inb(64) until bit 1 set
and we only do the first half.

Andries
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/