static unsigned char i8042_mux_present;
static unsigned char i8042_kbd_irq_registered;
static unsigned char i8042_aux_irq_registered;
+static unsigned char i8042_suppress_kbd_ack;
static struct platform_device *i8042_platform_device;
-static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t i8042_interrupt(int irq, void *dev_id);
/*
* The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to
static int i8042_aux_write(struct serio *serio, unsigned char c)
{
struct i8042_port *port = serio->port_data;
- int retval;
-
-/*
- * Send the byte out.
- */
-
- if (port->mux == -1)
- retval = i8042_command(&c, I8042_CMD_AUX_SEND);
- else
- retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux);
-/*
- * Make sure the interrupt happens and the character is received even
- * in the case the IRQ isn't wired, so that we can receive further
- * characters later.
- */
-
- i8042_interrupt(0, NULL, NULL);
- return retval;
+ return i8042_command(&c, port->mux == -1 ?
+ I8042_CMD_AUX_SEND :
+ I8042_CMD_MUX_SEND + port->mux);
}
/*
* to the upper layers.
*/
-static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t i8042_interrupt(int irq, void *dev_id)
{
struct i8042_port *port;
unsigned long flags;
unsigned char str, data;
unsigned int dfl;
unsigned int port_no;
- int ret;
+ int ret = 1;
spin_lock_irqsave(&i8042_lock, flags);
str = i8042_read_status();
dfl = 0;
if (str & I8042_STR_MUXERR) {
dbg("MUX error, status is %02x, data is %02x", str, data);
- switch (data) {
- default:
/*
* When MUXERR condition is signalled the data register can only contain
* 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
- * it is not always the case. Some KBC just get confused which port the
- * data came from and signal error leaving the data intact. They _do not_
- * revert to legacy mode (actually I've never seen KBC reverting to legacy
- * mode yet, when we see one we'll add proper handling).
- * Anyway, we will assume that the data came from the same serio last byte
+ * it is not always the case. Some KBCs also report 0xfc when there is
+ * nothing connected to the port while others sometimes get confused which
+ * port the data came from and signal error leaving the data intact. They
+ * _do not_ revert to legacy mode (actually I've never seen KBC reverting
+ * to legacy mode yet, when we see one we'll add proper handling).
+ * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the
+ * rest assume that the data came from the same serio last byte
* was transmitted (if transmission happened not too long ago).
*/
+
+ switch (data) {
+ default:
if (time_before(jiffies, last_transmit + HZ/10)) {
str = last_str;
break;
}
/* fall through - report timeout */
+ case 0xfc:
case 0xfd:
case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;
case 0xff: dfl = SERIO_PARITY; data = 0xfe; break;
dfl & SERIO_PARITY ? ", bad parity" : "",
dfl & SERIO_TIMEOUT ? ", timeout" : "");
+ if (unlikely(i8042_suppress_kbd_ack))
+ if (port_no == I8042_KBD_PORT_NO &&
+ (data == 0xfa || data == 0xfe)) {
+ i8042_suppress_kbd_ack--;
+ goto out;
+ }
+
if (likely(port->exists))
- serio_interrupt(port->serio, data, dfl, regs);
+ serio_interrupt(port->serio, data, dfl);
- ret = 1;
out:
return IRQ_RETVAL(ret);
}
static struct completion i8042_aux_irq_delivered __devinitdata;
static int i8042_irq_being_tested __devinitdata;
-static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id)
{
unsigned long flags;
unsigned char str, data;
{
int retval = -1;
int irq_registered = 0;
+ int aux_loop_broken = 0;
unsigned long flags;
unsigned char param;
if (i8042_command(¶m, I8042_CMD_AUX_TEST) ||
(param && param != 0xfa && param != 0xff))
return -1;
+
+ aux_loop_broken = 1;
}
/*
* used it for a PCI card or somethig else.
*/
- if (i8042_noloop) {
+ if (i8042_noloop || aux_loop_broken) {
/*
* Without LOOP command we can't test AUX IRQ delivery. Assume the port
* is working and hope we are right.
led ^= 0x01 | 0x04;
while (i8042_read_status() & I8042_STR_IBF)
DELAY;
+ dbg("%02x -> i8042 (panic blink)", 0xed);
+ i8042_suppress_kbd_ack = 2;
i8042_write_data(0xed); /* set leds */
DELAY;
while (i8042_read_status() & I8042_STR_IBF)
DELAY;
DELAY;
+ dbg("%02x -> i8042 (panic blink)", led);
i8042_write_data(led);
DELAY;
last_blink = count;
if (i8042_ports[I8042_KBD_PORT_NO].serio)
i8042_enable_kbd_port();
- i8042_interrupt(0, NULL, NULL);
+ i8042_interrupt(0, NULL);
return 0;
}