|
From: Vojtech P. <vo...@us...> - 2002-07-10 22:34:03
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/serio
In directory usw-pr-cvs1:/tmp/cvs-serv27583/linux/drivers/input/serio
Modified Files:
i8042.c i8042.h serio.c
Log Message:
Sync input drivers to the BK tree.
Index: i8042.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/input/serio/i8042.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- i8042.c 10 Jul 2002 20:45:54 -0000 1.23
+++ i8042.c 10 Jul 2002 22:34:00 -0000 1.24
@@ -70,6 +70,7 @@
static struct serio i8042_aux_port;
static unsigned char i8042_initial_ctr;
static unsigned char i8042_ctr;
+struct timer_list i8042_timer;
#ifdef I8042_DEBUG_IO
static unsigned long i8042_start;
@@ -243,7 +244,7 @@
* mode tend to trash their CTR when doing the AUX_SEND command.
*/
- retval += i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR);
+ retval |= i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR);
/*
* Make sure the interrupt happens and the character is received even
@@ -251,7 +252,7 @@
* characters later.
*/
- i8042_interrupt(0, port, NULL);
+ i8042_interrupt(0, NULL, NULL);
return retval;
}
@@ -269,28 +270,23 @@
*/
if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) {
- printk(KERN_ERR "i8042.c: Can't get irq %d for %s\n", values->irq, values->name);
+ printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name);
+ values->exists = 0;
+ serio_unregister_port(port);
return -1;
}
/*
- * Enable the device and its interrupt.
+ * Enable the interrupt.
*/
i8042_ctr |= values->irqen;
- i8042_ctr &= ~values->disable;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
printk(KERN_ERR "i8042.c: Can't write CTR while opening %s.\n", values->name);
return -1;
}
-/*
- * Flush buffers
- */
-
- i8042_flush();
-
return 0;
}
@@ -304,11 +300,10 @@
struct i8042_values *values = port->driver;
/*
- * Disable the device and its interrupt.
+ * Disable the interrupt.
*/
i8042_ctr &= ~values->irqen;
- i8042_ctr |= values->disable;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
printk(KERN_ERR "i8042.c: Can't write CTR while closing %s.\n", values->name);
@@ -374,26 +369,29 @@
{
unsigned long flags;
unsigned char str, data;
+ unsigned int dfl;
spin_lock_irqsave(&i8042_lock, flags);
while ((str = inb(I8042_STATUS_REG)) & I8042_STR_OBF) {
data = inb(I8042_DATA_REG);
+ dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
+ ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
#ifdef I8042_DEBUG_IO
- printk(KERN_DEBUG "i8042.c: %02x <- i8042 (interrupt-%s) [%d]\n",
- data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", (int) (jiffies - i8042_start));
+ printk(KERN_DEBUG "i8042.c: %02x <- i8042 (interrupt-%s, %d) [%d]\n",
+ data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq, (int) (jiffies - i8042_start));
#endif
if (i8042_aux_values.exists && (str & I8042_STR_AUXDATA)) {
- serio_interrupt(&i8042_aux_port, data, 0);
+ serio_interrupt(&i8042_aux_port, data, dfl);
} else {
if (i8042_kbd_values.exists) {
if (!i8042_direct) {
if (data > 0x7f) {
if (test_and_clear_bit(data & 0x7f, i8042_unxlate_seen)) {
- serio_interrupt(&i8042_kbd_port, 0xf0, 0);
+ serio_interrupt(&i8042_kbd_port, 0xf0, dfl);
data = i8042_unxlate_table[data & 0x7f];
}
} else {
@@ -401,7 +399,7 @@
data = i8042_unxlate_table[data];
}
}
- serio_interrupt(&i8042_kbd_port, data, 0);
+ serio_interrupt(&i8042_kbd_port, data, dfl);
}
}
}
@@ -524,6 +522,8 @@
void i8042_controller_cleanup(void)
{
+ i8042_flush();
+
/*
* Reset the controller.
*/
@@ -565,6 +565,19 @@
{
unsigned char param;
+/*
+ * Check if AUX irq is available. If it isn't, then there is no point
+ * in trying to detect AUX presence.
+ */
+
+ if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL))
+ return -1;
+ free_irq(values->irq, NULL);
+
+/*
+ * Get rid of bytes in the queue.
+ */
+
i8042_flush();
/*
@@ -637,6 +650,32 @@
return 0;
}
+static void i8042_timer_func(unsigned long data)
+{
+ i8042_interrupt(0, NULL, NULL);
+ mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
+}
+
+static void __init i8042_start_polling(void)
+{
+ i8042_ctr &= ~I8042_CTR_KBDDIS;
+ if (i8042_aux_values.exists)
+ i8042_ctr &= ~I8042_CTR_AUXDIS;
+
+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+ printk(KERN_WARNING "i8042.c: Can't write CTR while starting polling.\n");
+ return;
+ }
+
+ i8042_timer.function = i8042_timer_func;
+ mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
+}
+
+static void __exit i8042_stop_polling(void)
+{
+ del_timer(&i8042_timer);
+}
+
/*
* Module init and cleanup functions.
*/
@@ -677,6 +716,15 @@
i8042_start = jiffies;
#endif
+/*
+ * On ix86 platforms touching the i8042 data register region can do really
+ * bad things. Because of this the region is always reserved on ix86 boxes.
+ */
+#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__)
+ if (!request_region(I8042_DATA_REG, 16, "i8042"))
+ return -EBUSY;
+#endif
+
if (i8042_controller_init())
return -ENODEV;
@@ -685,20 +733,18 @@
if (!i8042_noaux && !i8042_check_aux(&i8042_aux_values, &i8042_aux_port))
i8042_port_register(&i8042_aux_values, &i8042_aux_port);
-/*
- * On ix86 platforms touching the i8042 data register region can do really
- * bad things. Because of this the region is always reserved on ix86 boxes.
- */
-#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__)
- request_region(I8042_DATA_REG, 16, "i8042");
-#endif
+ i8042_start_polling();
+
register_reboot_notifier(&i8042_notifier);
+
return 0;
}
void __exit i8042_exit(void)
{
unregister_reboot_notifier(&i8042_notifier);
+
+ i8042_stop_polling();
if (i8042_kbd_values.exists)
serio_unregister_port(&i8042_kbd_port);
@@ -707,6 +753,7 @@
serio_unregister_port(&i8042_aux_port);
i8042_controller_cleanup();
+
#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__)
release_region(I8042_DATA_REG, 16);
#endif
Index: i8042.h
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/input/serio/i8042.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- i8042.h 10 Jul 2002 18:08:04 -0000 1.11
+++ i8042.h 10 Jul 2002 22:34:00 -0000 1.12
@@ -28,12 +28,6 @@
*/
/*
- * If you want to reset your i8042 upon boot, define this.
- */
-
-#undef I8042_RESET
-
-/*
* If you want to trace all the i/o the i8042 module does for
* debugging purposes, define this.
*/
@@ -61,6 +55,15 @@
*/
#define I8042_CTL_TIMEOUT 10000
+
+/*
+ * When the device isn't opened and it's interrupts aren't used, we poll it at
+ * regular intervals to see if any characters arrived. If yes, we can start
+ * probing for any mouse / keyboard connected. This is the period of the
+ * polling.
+ */
+
+#define I8042_POLL_PERIOD HZ/20
/*
* Register numbers.
Index: serio.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/input/serio/serio.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- serio.c 10 Jul 2002 18:08:04 -0000 1.16
+++ serio.c 10 Jul 2002 22:34:00 -0000 1.17
@@ -111,6 +111,14 @@
wake_up(&serio_wait);
}
+void serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
+{
+ if (serio->dev && serio->dev->interrupt)
+ serio->dev->interrupt(serio, data, flags);
+ else
+ serio_rescan(serio);
+}
+
void serio_register_port(struct serio *serio)
{
serio->next = serio_list;
|