patch-2.4.10 linux/drivers/char/pc_keyb.c

Next file: linux/drivers/char/pcmcia/serial_cs.c
Previous file: linux/drivers/char/pc110pad.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.9/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
@@ -31,7 +31,9 @@
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
 #include <linux/smp_lock.h>
+#include <linux/kd.h>
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
@@ -395,6 +397,32 @@
 	    return 0200;
 }
 
+void pckbd_pm_resume(void)
+{
+#if defined CONFIG_PSMOUSE
+       unsigned long flags;
+
+       if (queue) {                    /* Aux port detected */
+               if (aux_count == 0) {   /* Mouse not in use */ 
+                       spin_lock_irqsave(&kbd_controller_lock, flags);
+                       /*
+                        * Dell Lat. C600 A06 enables mouse after resume.
+                        * When user touches the pad, it posts IRQ 12
+                        * (which we do not process), thus holding keyboard.
+                        */
+                       kbd_write_command(KBD_CCMD_MOUSE_DISABLE);
+                       /* kbd_write_cmd(AUX_INTS_OFF); */ /* Config & lock */
+                       kb_wait();
+                       kbd_write_command(KBD_CCMD_WRITE_MODE);
+                       kb_wait();
+                       kbd_write_output(AUX_INTS_OFF);
+                       spin_unlock_irqrestore(&kbd_controller_lock, flags);
+               }
+       }
+#endif       
+}
+
+
 static inline void handle_mouse_event(unsigned char scancode)
 {
 #ifdef CONFIG_PSMOUSE
@@ -519,7 +547,7 @@
 			mdelay(1);
 			if (!--timeout) {
 #ifdef KBD_REPORT_TIMEOUTS
-				printk(KERN_WARNING "keyboard: Timeout - AT keyboard not present?\n");
+				printk(KERN_WARNING "keyboard: Timeout - AT keyboard not present?(%02x)\n", data);
 #endif
 				return 0;
 			}
@@ -602,7 +630,7 @@
 		return 1;
 }
 
-int pckbd_rate(struct kbd_repeat *rep)
+static int pckbd_rate(struct kbd_repeat *rep)
 {
 	if (rep == NULL)
 		return -EINVAL;
@@ -705,6 +733,53 @@
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 
+#if defined(__alpha__)
+/*
+ * Some Alphas cannot mask some/all interrupts, so we have to
+ * make sure not to allow interrupts AT ALL when polling for
+ * specific return values from the keyboard.
+ *
+ * I think this should work on any architecture, but for now, only Alpha.
+ */
+static int kbd_write_command_w_and_wait(int data)
+{
+	unsigned long flags;
+	int input;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_command(data);
+	input = kbd_wait_for_input();
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+	return input;
+}
+
+static int kbd_write_output_w_and_wait(int data)
+{
+	unsigned long flags;
+	int input;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_output(data);
+	input = kbd_wait_for_input();
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+	return input;
+}
+#else
+static int kbd_write_command_w_and_wait(int data)
+{
+	kbd_write_command_w(data);
+	return kbd_wait_for_input();
+}
+
+static int kbd_write_output_w_and_wait(int data)
+{
+	kbd_write_output_w(data);
+	return kbd_wait_for_input();
+}
+#endif /* __alpha__ */
+
 #if defined CONFIG_PSMOUSE
 static void kbd_write_cmd(int cmd)
 {
@@ -788,8 +863,8 @@
 			      | KBD_MODE_KCC);
 
 	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
-	kbd_write_command_w(KBD_CCMD_READ_MODE);
-	if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
+	if (!(kbd_write_command_w_and_wait(KBD_CCMD_READ_MODE) & KBD_MODE_KCC))
+	{
 		/*
 		 * If the controller does not support conversion,
 		 * Set the keyboard to scan-code set 1.
@@ -800,20 +875,16 @@
 		kbd_wait_for_input();
 	}
 
-	
-	kbd_write_output_w(KBD_CMD_ENABLE);
-	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+	if (kbd_write_output_w_and_wait(KBD_CMD_ENABLE) != KBD_REPLY_ACK)
 		return "Enable keyboard: no ACK";
 
 	/*
 	 * Finally, set the typematic rate to maximum.
 	 */
-	kbd_write_output_w(KBD_CMD_SET_RATE);
-	if (kbd_wait_for_input() != KBD_REPLY_ACK)
-		return "Set rate: no ACK";
-	kbd_write_output_w(0x00);
-	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+	if (kbd_write_output_w_and_wait(KBD_CMD_SET_RATE) != KBD_REPLY_ACK)
 		return "Set rate: no ACK";
+	if (kbd_write_output_w_and_wait(0x00) != KBD_REPLY_ACK)
+		return "Set rate: no 2nd ACK";
 
 	return NULL;
 }
@@ -835,6 +906,8 @@
 	psaux_init();
 #endif
 
+	kbd_rate = pckbd_rate;
+
 	/* Ok, finally allocate the IRQ, and off we go.. */
 	kbd_request_irq(keyboard_interrupt);
 }
@@ -1105,13 +1178,20 @@
 
 static int __init psaux_init(void)
 {
+	int retval;
+
 	if (!detect_auxiliary_port())
 		return -EIO;
 
-	misc_register(&psaux_mouse);
+	if ((retval = misc_register(&psaux_mouse)))
+		return retval;
+
 	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-	if (queue == NULL)
-		panic("psaux_init(): out of memory");
+	if (queue == NULL) {
+		printk(KERN_ERR "psaux_init(): out of memory\n");
+		misc_deregister(&psaux_mouse);
+		return -ENOMEM;
+	}
 	memset(queue, 0, sizeof(*queue));
 	queue->head = queue->tail = 0;
 	init_waitqueue_head(&queue->proc_list);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)