--- linux-orig/drivers/char/pc_keyb.c	Mon Aug  9 12:04:39 1999
+++ linux/drivers/char/pc_keyb.c	Tue Apr 11 00:52:19 2000
@@ -13,6 +13,8 @@
  * Code fixes to handle mouse ACKs properly.
  * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
  *
+ * Code fixes to *really* handle mouse ACKs properly.
+ * Julian Bradfield <jcb@dcs.ed.ac.uk> 1999-04-30.
  */
 
 #include <linux/config.h>
@@ -75,8 +77,13 @@
 
 static struct aux_queue *queue;	/* Mouse data buffer. */
 static int aux_count = 0;
-/* used when we send commands to the mouse that expect an ACK. */
+/* used when we (as opposed to the user programs using the aux device)
+   send commands to the mouse that expect an ACK. */ 
 static unsigned char mouse_reply_expected = 0;
+/* used to make sure we read acks from the mouse before we
+   write another byte */
+static unsigned char mouse_ack_pending = 0;
+#define MOUSE_ACK_TIMEOUT 5    /* actually, 1 seems to be enough usually */
 
 #define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
 #define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
@@ -386,6 +393,10 @@
 static inline void handle_mouse_event(unsigned char scancode)
 {
 #ifdef CONFIG_PSMOUSE
+        if (mouse_ack_pending)
+	        /* it needn't actually be an ack, it could be an echo;
+		   but every byte sent to the mouse results in a byte back */
+                mouse_ack_pending = 0;
 	if (mouse_reply_expected) {
 		if (scancode == AUX_ACK) {
 			mouse_reply_expected--;
@@ -770,12 +781,23 @@
 static void aux_write_dev(int val)
 {
 	unsigned long flags;
+ 	int loop = 0;
 
 	spin_lock_irqsave(&kbd_controller_lock, flags);
 	kb_wait();
+        /* if we haven't yet received the ack from the previous
+           write, we must wait for it to arrive; otherwise we
+           lose it. (At least, I think this is what is happening.)  */
+        while (mouse_ack_pending && loop++ < MOUSE_ACK_TIMEOUT ) { 
+               mdelay(1);
+               handle_kbd_event();
+ 	}
+ 	if ( mouse_ack_pending )
+                printk(KERN_WARNING "mouse ack timeout\n") ;
 	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
 	kb_wait();
 	kbd_write_output(val);
+ 	mouse_ack_pending = 1;
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 
@@ -785,13 +807,21 @@
 static void aux_write_ack(int val)
 {
 	unsigned long flags;
+ 	int loop = 0;
 
 	spin_lock_irqsave(&kbd_controller_lock, flags);
 	kb_wait();
+        while (mouse_ack_pending && loop++ < MOUSE_ACK_TIMEOUT) { 
+               mdelay(1);
+               handle_kbd_event();
+	}
+	if ( mouse_ack_pending )
+               printk(KERN_WARNING "mouse ack timeout\n") ;
 	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
 	kb_wait();
 	kbd_write_output(val);
-	/* we expect an ACK in response. */
+	mouse_ack_pending = 1;
+	/* we will deal with the ACK ourselves. */
 	mouse_reply_expected++;
 	kb_wait();
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
