* [PATCH 2.6 1/3] Take 2: resume support for i8042 (atkbd & psmouse)
@ 2003-12-07 7:27 Dmitry Torokhov
2003-12-07 7:28 ` [PATCH 2.6 2/3] " Dmitry Torokhov
2003-12-07 9:28 ` [PATCH 2.6 1/3] " Vojtech Pavlik
0 siblings, 2 replies; 4+ messages in thread
From: Dmitry Torokhov @ 2003-12-07 7:27 UTC (permalink / raw)
To: linux-kernel; +Cc: Vojtech Pavlik, Pavel Machek, Brian Perkins, Karol Kozimor
Hi,
Here is the 2nd attempt to implement resume for i8042 using serio_reconnect
facility that can be found in -mm kernels. Big thanks to everyone who tested
the first version. The changes from the last patch:
i8042: - now correctly enables keyboard port on resume
- switches active multiplexing controller from Legacy mode back
to Multiplexing mode (4 AUX ports) on resume
- installs resume handlers for both old (pm_dev - APM) and new
(driver model) suspend/resume schemes.
- convert parameter handling to the new style
psmouse: - psmouse_pm_callback removed as i8042 will request reconnect
regardless of whether APM or new PM method is used.
The patched depend on bunch of other changes in input subsystem all of which
can be found here:
http://www.geocities.com/dt_or/input
Should apply cleanly to -test11. If patching -mm tree omit patches 1-6 and 8
as they are already present there.
Dmitry
===================================================================
ChangeSet@1.1514, 2003-12-07 01:48:52-05:00, dtor_core@ameritech.net
Input: - Implement resume methods using serio_reconnect facility
- Register i8042 with sysfs
- Register i8042 with older PM scheme to restore keyboard
and mouse for APM users
- Convert parameter handling to the new style
i8042.c | 520 +++++++++++++++++++++++++++++++++++++++-------------------------
1 files changed, 320 insertions(+), 200 deletions(-)
===================================================================
diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
--- a/drivers/input/serio/i8042.c Sun Dec 7 02:17:56 2003
+++ b/drivers/input/serio/i8042.c Sun Dec 7 02:17:56 2003
@@ -12,11 +12,14 @@
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/config.h>
#include <linux/reboot.h>
#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/pm.h>
#include <linux/serio.h>
#include <asm/io.h>
@@ -25,19 +28,23 @@
MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(i8042_noaux, "1i");
-MODULE_PARM(i8042_nomux, "1i");
-MODULE_PARM(i8042_unlock, "1i");
-MODULE_PARM(i8042_reset, "1i");
-MODULE_PARM(i8042_direct, "1i");
-MODULE_PARM(i8042_dumbkbd, "1i");
-
-static int i8042_reset;
-static int i8042_noaux;
-static int i8042_nomux;
-static int i8042_unlock;
-static int i8042_direct;
-static int i8042_dumbkbd;
+static unsigned int i8042_noaux;
+module_param(i8042_noaux, bool, 0);
+
+static unsigned int i8042_nomux;
+module_param(i8042_nomux, bool, 0);
+
+static unsigned int i8042_unlock;
+module_param(i8042_unlock, bool, 0);
+
+static unsigned int i8042_reset;
+module_param(i8042_reset, bool, 0);
+
+static unsigned int i8042_direct;
+module_param(i8042_direct, bool, 0);
+
+static unsigned int i8042_dumbkbd;
+module_param(i8042_dumbkbd, bool, 0);
#undef DEBUG
#include "i8042.h"
@@ -59,6 +66,9 @@
static unsigned char i8042_initial_ctr;
static unsigned char i8042_ctr;
static unsigned char i8042_mux_open;
+static unsigned char i8042_mux_present;
+static unsigned char i8042_sysdev_initialized;
+static struct pm_dev *i8042_pm_dev;
struct timer_list i8042_timer;
/*
@@ -214,16 +224,41 @@
}
/*
- * i8042_open() is called when a port is open by the higher layer.
- * It allocates the interrupt and enables it in the chip.
+ * i8042_activate_port() enables port on a chip.
*/
-static int i8042_open(struct serio *port)
+static int i8042_activate_port(struct serio *port)
{
struct i8042_values *values = port->driver;
i8042_flush();
+ /*
+ * Enable port again here because it is disabled if we are
+ * resuming (normally it is enabled already).
+ */
+ i8042_ctr &= ~values->disable;
+
+ i8042_ctr |= values->irqen;
+
+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+ i8042_ctr &= ~values->irqen;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * i8042_open() is called when a port is open by the higher layer.
+ * It allocates the interrupt and calls i8042_enable_port.
+ */
+
+static int i8042_open(struct serio *port)
+{
+ struct i8042_values *values = port->driver;
+
if (values->mux != -1)
if (i8042_mux_open++)
return 0;
@@ -234,10 +269,8 @@
goto irq_fail;
}
- i8042_ctr |= values->irqen;
-
- if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
- printk(KERN_ERR "i8042.c: Can't write CTR while opening %s, unregistering the port\n", values->name);
+ if (i8042_activate_port(port)) {
+ printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", values->name);
goto ctr_fail;
}
@@ -246,7 +279,6 @@
return 0;
ctr_fail:
- i8042_ctr &= ~values->irqen;
free_irq(values->irq, i8042_request_irq_cookie);
irq_fail:
@@ -400,146 +432,80 @@
return IRQ_RETVAL(j);
}
+
/*
- * i8042_controller init initializes the i8042 controller, and,
- * most importantly, sets it into non-xlated mode if that's
- * desired.
+ * i8042_enable_mux_mode checks whether the controller has an active
+ * multiplexor and puts the chip into Multiplexed (as opposed to
+ * Legacy) mode.
*/
-
-static int __init i8042_controller_init(void)
+
+static int i8042_enable_mux_mode(struct i8042_values *values, unsigned char *mux_version)
{
+ unsigned char param;
/*
- * Test the i8042. We need to know if it thinks it's working correctly
- * before doing anything else.
+ * Get rid of bytes in the queue.
*/
i8042_flush();
- if (i8042_reset) {
-
- unsigned char param;
-
- if (i8042_command(¶m, I8042_CMD_CTL_TEST)) {
- printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
- return -1;
- }
-
- if (param != I8042_RET_CTL_TEST) {
- printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
- param, I8042_RET_CTL_TEST);
- return -1;
- }
- }
-
/*
- * Save the CTR for restoral on unload / reboot.
+ * Internal loopback test - send three bytes, they should come back from the
+ * mouse interface, the last should be version. Note that we negate mouseport
+ * command responses for the i8042_check_aux() routine.
*/
- if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
- printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
+ param = 0xf0;
+ if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x0f)
+ return -1;
+ param = 0x56;
+ if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xa9)
+ return -1;
+ param = 0xa4;
+ if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == 0x5b)
return -1;
- }
-
- i8042_initial_ctr = i8042_ctr;
-
-/*
- * Disable the keyboard interface and interrupt.
- */
- i8042_ctr |= I8042_CTR_KBDDIS;
- i8042_ctr &= ~I8042_CTR_KBDINT;
+ if (mux_version)
+ *mux_version = ~param;
-/*
- * Handle keylock.
- */
+ return 0;
+}
- if (~i8042_read_status() & I8042_STR_KEYLOCK) {
- if (i8042_unlock)
- i8042_ctr |= I8042_CTR_IGNKEYLOCK;
- else
- printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
- }
/*
- * If the chip is configured into nontranslated mode by the BIOS, don't
- * bother enabling translating and be happy.
+ * i8042_enable_mux_ports enables 4 individual AUX ports after
+ * the controller has been switched into Multiplexed mode
*/
- if (~i8042_ctr & I8042_CTR_XLATE)
- i8042_direct = 1;
-
+static int i8042_enable_mux_ports(struct i8042_values *values)
+{
+ unsigned char param;
+ int i;
/*
- * Set nontranslated mode for the kbd interface if requested by an option.
- * After this the kbd interface becomes a simple serial in/out, like the aux
- * interface is. We don't do this by default, since it can confuse notebook
- * BIOSes.
+ * Disable all muxed ports by disabling AUX.
*/
- if (i8042_direct) {
- i8042_ctr &= ~I8042_CTR_XLATE;
- i8042_kbd_port.type = SERIO_8042;
- }
-
-/*
- * Write CTR back.
- */
+ i8042_ctr |= I8042_CTR_AUXDIS;
+ i8042_ctr &= ~I8042_CTR_AUXINT;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
- printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n");
+ printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n");
return -1;
}
- return 0;
-}
-
/*
- * Here we try to reset everything back to a state in which the BIOS will be
- * able to talk to the hardware when rebooting.
- */
-
-void i8042_controller_cleanup(void)
-{
- int i;
-
- i8042_flush();
-
-/*
- * Reset anything that is connected to the ports.
- */
-
- if (i8042_kbd_values.exists)
- serio_cleanup(&i8042_kbd_port);
-
- if (i8042_aux_values.exists)
- serio_cleanup(&i8042_aux_port);
-
- for (i = 0; i < 4; i++)
- if (i8042_mux_values[i].exists)
- serio_cleanup(i8042_mux_port + i);
-
-/*
- * Reset the controller.
+ * Enable all muxed ports.
*/
- if (i8042_reset) {
- unsigned char param;
-
- if (i8042_command(¶m, I8042_CMD_CTL_TEST))
- printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
+ for (i = 0; i < 4; i++) {
+ i8042_command(¶m, I8042_CMD_MUX_PFX + i);
+ i8042_command(¶m, I8042_CMD_AUX_ENABLE);
}
-/*
- * Restore the original control register setting.
- */
-
- i8042_ctr = i8042_initial_ctr;
-
- if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
- printk(KERN_WARNING "i8042.c: Can't restore CTR.\n");
-
+ return 0;
}
+
/*
* i8042_check_mux() checks whether the controller supports the PS/2 Active
* Multiplexing specification by Synaptics, Phoenix, Insyde and
@@ -548,66 +514,31 @@
static int __init i8042_check_mux(struct i8042_values *values)
{
- unsigned char param;
static int i8042_check_mux_cookie;
- int i;
+ unsigned char mux_version;
/*
* Check if AUX irq is available.
*/
-
if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
"i8042", &i8042_check_mux_cookie))
return -1;
free_irq(values->irq, &i8042_check_mux_cookie);
-/*
- * Get rid of bytes in the queue.
- */
-
- i8042_flush();
-
-/*
- * Internal loopback test - send three bytes, they should come back from the
- * mouse interface, the last should be version. Note that we negate mouseport
- * command responses for the i8042_check_aux() routine.
- */
-
- param = 0xf0;
- if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x0f)
- return -1;
- param = 0x56;
- if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xa9)
- return -1;
- param = 0xa4;
- if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == 0x5b)
+ if (i8042_enable_mux_mode(values, &mux_version))
return -1;
printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n",
- (~param >> 4) & 0xf, ~param & 0xf);
-
-/*
- * Disable all muxed ports by disabling AUX.
- */
-
- i8042_ctr |= I8042_CTR_AUXDIS;
- i8042_ctr &= ~I8042_CTR_AUXINT;
+ (mux_version >> 4) & 0xf, mux_version & 0xf);
- if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
+ if (i8042_enable_mux_ports(values))
return -1;
-/*
- * Enable all muxed ports.
- */
-
- for (i = 0; i < 4; i++) {
- i8042_command(¶m, I8042_CMD_MUX_PFX + i);
- i8042_command(¶m, I8042_CMD_AUX_ENABLE);
- }
-
+ i8042_mux_present = 1;
return 0;
}
+
/*
* i8042_check_aux() applies as much paranoia as it can at detecting
* the presence of an AUX interface.
@@ -683,6 +614,7 @@
return 0;
}
+
/*
* i8042_port_register() marks the device as existing,
* registers it, and reports to the user.
@@ -710,52 +642,194 @@
return 0;
}
+
static void i8042_timer_func(unsigned long data)
{
i8042_interrupt(0, NULL, NULL);
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
}
-#ifndef MODULE
-static int __init i8042_setup_reset(char *str)
-{
- i8042_reset = 1;
- return 1;
-}
-static int __init i8042_setup_noaux(char *str)
-{
- i8042_noaux = 1;
- i8042_nomux = 1;
- return 1;
-}
-static int __init i8042_setup_nomux(char *str)
-{
- i8042_nomux = 1;
- return 1;
-}
-static int __init i8042_setup_unlock(char *str)
+
+/*
+ * i8042_controller init initializes the i8042 controller, and,
+ * most importantly, sets it into non-xlated mode if that's
+ * desired.
+ */
+
+static int i8042_controller_init(void)
{
- i8042_unlock = 1;
- return 1;
+
+ if (i8042_noaux)
+ i8042_nomux = 1;
+/*
+ * Test the i8042. We need to know if it thinks it's working correctly
+ * before doing anything else.
+ */
+
+ i8042_flush();
+
+ if (i8042_reset) {
+
+ unsigned char param;
+
+ if (i8042_command(¶m, I8042_CMD_CTL_TEST)) {
+ printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
+ return -1;
+ }
+
+ if (param != I8042_RET_CTL_TEST) {
+ printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
+ param, I8042_RET_CTL_TEST);
+ return -1;
+ }
+ }
+
+/*
+ * Save the CTR for restoral on unload / reboot.
+ */
+
+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
+ printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
+ return -1;
+ }
+
+ i8042_initial_ctr = i8042_ctr;
+
+/*
+ * Disable the keyboard interface and interrupt.
+ */
+
+ i8042_ctr |= I8042_CTR_KBDDIS;
+ i8042_ctr &= ~I8042_CTR_KBDINT;
+
+/*
+ * Handle keylock.
+ */
+
+ if (~i8042_read_status() & I8042_STR_KEYLOCK) {
+ if (i8042_unlock)
+ i8042_ctr |= I8042_CTR_IGNKEYLOCK;
+ else
+ printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
+ }
+
+/*
+ * If the chip is configured into nontranslated mode by the BIOS, don't
+ * bother enabling translating and be happy.
+ */
+
+ if (~i8042_ctr & I8042_CTR_XLATE)
+ i8042_direct = 1;
+
+/*
+ * Set nontranslated mode for the kbd interface if requested by an option.
+ * After this the kbd interface becomes a simple serial in/out, like the aux
+ * interface is. We don't do this by default, since it can confuse notebook
+ * BIOSes.
+ */
+
+ if (i8042_direct) {
+ i8042_ctr &= ~I8042_CTR_XLATE;
+ i8042_kbd_port.type = SERIO_8042;
+ }
+
+/*
+ * Write CTR back.
+ */
+
+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+ printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n");
+ return -1;
+ }
+
+ return 0;
}
-static int __init i8042_setup_direct(char *str)
+
+
+/*
+ * Here we try to reset everything back to a state in which the BIOS will be
+ * able to talk to the hardware when rebooting.
+ */
+
+void i8042_controller_cleanup(void)
{
- i8042_direct = 1;
- return 1;
+ int i;
+
+ i8042_flush();
+
+/*
+ * Reset anything that is connected to the ports.
+ */
+
+ if (i8042_kbd_values.exists)
+ serio_cleanup(&i8042_kbd_port);
+
+ if (i8042_aux_values.exists)
+ serio_cleanup(&i8042_aux_port);
+
+ for (i = 0; i < 4; i++)
+ if (i8042_mux_values[i].exists)
+ serio_cleanup(i8042_mux_port + i);
+
+/*
+ * Reset the controller.
+ */
+
+ if (i8042_reset) {
+ unsigned char param;
+
+ if (i8042_command(¶m, I8042_CMD_CTL_TEST))
+ printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
+ }
+
+/*
+ * Restore the original control register setting.
+ */
+
+ i8042_ctr = i8042_initial_ctr;
+
+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
+ printk(KERN_WARNING "i8042.c: Can't restore CTR.\n");
+
}
-static int __init i8042_setup_dumbkbd(char *str)
+
+
+/*
+ * Here we try to reset everything back to a state in which suspended
+ */
+
+static int i8042_controller_resume(void)
{
- i8042_dumbkbd = 1;
- return 1;
+ int i;
+
+ if (i8042_controller_init()) {
+ printk(KERN_ERR "i8042: resume failed\n");
+ return -1;
+ }
+
+ if (i8042_mux_present)
+ if (i8042_enable_mux_mode(&i8042_aux_values, NULL) ||
+ i8042_enable_mux_ports(&i8042_aux_values)) {
+ printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't wotk.\n");
+ }
+
+/*
+ * Reconnect anything that was connected to the ports.
+ */
+
+ if (i8042_kbd_values.exists && i8042_activate_port(&i8042_kbd_port) == 0)
+ serio_reconnect(&i8042_kbd_port);
+
+ if (i8042_aux_values.exists && i8042_activate_port(&i8042_aux_port) == 0)
+ serio_reconnect(&i8042_aux_port);
+
+ for (i = 0; i < 4; i++)
+ if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port + i) == 0)
+ serio_reconnect(i8042_mux_port + i);
+
+ return 0;
}
-__setup("i8042_reset", i8042_setup_reset);
-__setup("i8042_noaux", i8042_setup_noaux);
-__setup("i8042_nomux", i8042_setup_nomux);
-__setup("i8042_unlock", i8042_setup_unlock);
-__setup("i8042_direct", i8042_setup_direct);
-__setup("i8042_dumbkbd", i8042_setup_dumbkbd);
-#endif
/*
* We need to reset the 8042 back to original mode on system shutdown,
@@ -777,6 +851,35 @@
0
};
+/*
+ * Resume handler for the new PM scheme (driver model)
+ */
+static int i8042_resume(struct sys_device *dev)
+{
+ return i8042_controller_resume();
+}
+
+static struct sysdev_class kbc_sysclass = {
+ set_kset_name("i8042"),
+ .resume = i8042_resume,
+};
+
+static struct sys_device device_i8042 = {
+ .id = 0,
+ .cls = &kbc_sysclass,
+};
+
+/*
+ * Resume handler for the old PM scheme (APM)
+ */
+static int i8042_pm_callback(struct pm_dev *dev, pm_request_t request, void *dummy)
+{
+ if (request == PM_RESUME)
+ return i8042_controller_resume();
+
+ return 0;
+}
+
static void __init i8042_init_mux_values(struct i8042_values *values, struct serio *port, int index)
{
memcpy(port, &i8042_aux_port, sizeof(struct serio));
@@ -825,6 +928,15 @@
i8042_timer.function = i8042_timer_func;
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
+ if (sysdev_class_register(&kbc_sysclass) == 0) {
+ if (sys_device_register(&device_i8042) == 0)
+ i8042_sysdev_initialized = 1;
+ else
+ sysdev_class_unregister(&kbc_sysclass);
+ }
+
+ i8042_pm_dev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, i8042_pm_callback);
+
register_reboot_notifier(&i8042_notifier);
return 0;
@@ -835,6 +947,14 @@
int i;
unregister_reboot_notifier(&i8042_notifier);
+
+ if (i8042_pm_dev)
+ pm_unregister(i8042_pm_dev);
+
+ if (i8042_sysdev_initialized) {
+ sys_device_unregister(&device_i8042);
+ sysdev_class_unregister(&kbc_sysclass);
+ }
del_timer(&i8042_timer);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2.6 2/3] Take 2: resume support for i8042 (atkbd & psmouse)
2003-12-07 7:27 [PATCH 2.6 1/3] Take 2: resume support for i8042 (atkbd & psmouse) Dmitry Torokhov
@ 2003-12-07 7:28 ` Dmitry Torokhov
2003-12-07 7:29 ` Dmitry Torokhov
2003-12-07 9:28 ` [PATCH 2.6 1/3] " Vojtech Pavlik
1 sibling, 1 reply; 4+ messages in thread
From: Dmitry Torokhov @ 2003-12-07 7:28 UTC (permalink / raw)
To: linux-kernel; +Cc: Vojtech Pavlik, Pavel Machek, Brian Perkins, Karol Kozimor
===================================================================
ChangeSet@1.1515, 2003-12-07 01:57:52-05:00, dtor_core@ameritech.net
Input: Add reconnect method to atkbd to restore keyboard state
after suspend (to be called from i8042 resume function)
atkbd.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 46 insertions(+)
===================================================================
diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
--- a/drivers/input/keyboard/atkbd.c Sun Dec 7 02:18:19 2003
+++ b/drivers/input/keyboard/atkbd.c Sun Dec 7 02:18:19 2003
@@ -686,10 +686,56 @@
printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
}
+/*
+ * atkbd_reconnect() tries to restore keyboard into a sane state and is
+ * most likely called on resume.
+ */
+
+static int atkbd_reconnect(struct serio *serio)
+{
+ struct atkbd *atkbd = serio->private;
+ struct serio_dev *dev = serio->dev;
+ int i;
+
+ if (!dev) {
+ printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
+ return -1;
+ }
+
+ if (atkbd->write) {
+ if (atkbd_probe(atkbd))
+ return -1;
+
+ atkbd->set = atkbd_set_3(atkbd);
+ atkbd_enable(atkbd);
+ } else {
+ atkbd->set = 2;
+ atkbd->id = 0xab00;
+ }
+
+ /*
+ * Here we probably should check if the keyboard has the same set that
+ * it had before and bail out if it's different. But this will most likely
+ * cause new keyboard device be created... and for the user it will look
+ * like keyboard is lost
+ */
+
+ if (atkbd->set == 3)
+ memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
+ else
+ memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
+
+ for (i = 0; i < 512; i++)
+ if (atkbd->keycode[i] && atkbd->keycode[i] < 255)
+ set_bit(atkbd->keycode[i], atkbd->dev.keybit);
+
+ return 0;
+}
static struct serio_dev atkbd_dev = {
.interrupt = atkbd_interrupt,
.connect = atkbd_connect,
+ .reconnect = atkbd_reconnect,
.disconnect = atkbd_disconnect,
.cleanup = atkbd_cleanup,
};
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2.6 2/3] Take 2: resume support for i8042 (atkbd & psmouse)
2003-12-07 7:28 ` [PATCH 2.6 2/3] " Dmitry Torokhov
@ 2003-12-07 7:29 ` Dmitry Torokhov
0 siblings, 0 replies; 4+ messages in thread
From: Dmitry Torokhov @ 2003-12-07 7:29 UTC (permalink / raw)
To: linux-kernel; +Cc: Vojtech Pavlik, Pavel Machek, Brian Perkins, Karol Kozimor
===================================================================
ChangeSet@1.1516, 2003-12-07 02:05:30-05:00, dtor_core@ameritech.net
Input: - Remove psmouse_pm_callback since i8042 now has its own resume
handler which will issue reconnect request
- Do not close/open serio port in psmouse_reconnect since i8042
should restore ports to the proper state before calling reconnect
psmouse-base.c | 35 -----------------------------------
1 files changed, 35 deletions(-)
===================================================================
diff -Nru a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c Sun Dec 7 02:18:36 2003
+++ b/drivers/input/mouse/psmouse-base.c Sun Dec 7 02:18:36 2003
@@ -18,7 +18,6 @@
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
-#include <linux/pm.h>
#include "psmouse.h"
#include "synaptics.h"
#include "logips2pp.h"
@@ -537,28 +536,12 @@
}
/*
- * Reinitialize mouse hardware after software suspend.
- */
-
-static int psmouse_pm_callback(struct pm_dev *dev, pm_request_t request, void *data)
-{
- struct psmouse *psmouse = dev->data;
-
- if (request == PM_RESUME) {
- psmouse->state = PSMOUSE_IGNORE;
- serio_reconnect(psmouse->serio);
- }
- return 0;
-}
-
-/*
* psmouse_connect() is a callback from the serio module when
* an unhandled serio port is found.
*/
static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
{
struct psmouse *psmouse;
- struct pm_dev *pmdev;
if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
(serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
@@ -590,14 +573,6 @@
return;
}
- if (serio->type != SERIO_PS_PSTHRU) {
- pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, psmouse_pm_callback);
- if (pmdev) {
- psmouse->dev.pm_dev = pmdev;
- pmdev->data = psmouse;
- }
- }
-
sprintf(psmouse->devname, "%s %s %s",
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
sprintf(psmouse->phys, "%s/input0",
@@ -635,16 +610,6 @@
if (!dev) {
printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
- return -1;
- }
-
- /* We need to reopen the serio port to reinitialize the i8042 controller */
- serio_close(serio);
- if (serio_open(serio, dev)) {
- /* do a disconnect here as serio_open leaves dev as NULL so disconnect
- * will not be called automatically later
- */
- psmouse_disconnect(serio);
return -1;
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2.6 1/3] Take 2: resume support for i8042 (atkbd & psmouse)
2003-12-07 7:27 [PATCH 2.6 1/3] Take 2: resume support for i8042 (atkbd & psmouse) Dmitry Torokhov
2003-12-07 7:28 ` [PATCH 2.6 2/3] " Dmitry Torokhov
@ 2003-12-07 9:28 ` Vojtech Pavlik
1 sibling, 0 replies; 4+ messages in thread
From: Vojtech Pavlik @ 2003-12-07 9:28 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-kernel, Vojtech Pavlik, Pavel Machek, Brian Perkins,
Karol Kozimor
On Sun, Dec 07, 2003 at 02:27:49AM -0500, Dmitry Torokhov wrote:
Hi!
These look very good. I'll go over them later today and apply them to my
tree. Thanks!
> Hi,
>
> Here is the 2nd attempt to implement resume for i8042 using serio_reconnect
> facility that can be found in -mm kernels. Big thanks to everyone who tested
> the first version. The changes from the last patch:
>
> i8042: - now correctly enables keyboard port on resume
> - switches active multiplexing controller from Legacy mode back
> to Multiplexing mode (4 AUX ports) on resume
> - installs resume handlers for both old (pm_dev - APM) and new
> (driver model) suspend/resume schemes.
> - convert parameter handling to the new style
>
> psmouse: - psmouse_pm_callback removed as i8042 will request reconnect
> regardless of whether APM or new PM method is used.
>
> The patched depend on bunch of other changes in input subsystem all of which
> can be found here:
>
> http://www.geocities.com/dt_or/input
>
> Should apply cleanly to -test11. If patching -mm tree omit patches 1-6 and 8
> as they are already present there.
>
> Dmitry
>
>
> ===================================================================
>
>
> ChangeSet@1.1514, 2003-12-07 01:48:52-05:00, dtor_core@ameritech.net
> Input: - Implement resume methods using serio_reconnect facility
> - Register i8042 with sysfs
> - Register i8042 with older PM scheme to restore keyboard
> and mouse for APM users
> - Convert parameter handling to the new style
>
>
> i8042.c | 520 +++++++++++++++++++++++++++++++++++++++-------------------------
> 1 files changed, 320 insertions(+), 200 deletions(-)
>
>
> ===================================================================
>
>
>
> diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
> --- a/drivers/input/serio/i8042.c Sun Dec 7 02:17:56 2003
> +++ b/drivers/input/serio/i8042.c Sun Dec 7 02:17:56 2003
> @@ -12,11 +12,14 @@
>
> #include <linux/delay.h>
> #include <linux/module.h>
> +#include <linux/moduleparam.h>
> #include <linux/interrupt.h>
> #include <linux/ioport.h>
> #include <linux/config.h>
> #include <linux/reboot.h>
> #include <linux/init.h>
> +#include <linux/sysdev.h>
> +#include <linux/pm.h>
> #include <linux/serio.h>
>
> #include <asm/io.h>
> @@ -25,19 +28,23 @@
> MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
> MODULE_LICENSE("GPL");
>
> -MODULE_PARM(i8042_noaux, "1i");
> -MODULE_PARM(i8042_nomux, "1i");
> -MODULE_PARM(i8042_unlock, "1i");
> -MODULE_PARM(i8042_reset, "1i");
> -MODULE_PARM(i8042_direct, "1i");
> -MODULE_PARM(i8042_dumbkbd, "1i");
> -
> -static int i8042_reset;
> -static int i8042_noaux;
> -static int i8042_nomux;
> -static int i8042_unlock;
> -static int i8042_direct;
> -static int i8042_dumbkbd;
> +static unsigned int i8042_noaux;
> +module_param(i8042_noaux, bool, 0);
> +
> +static unsigned int i8042_nomux;
> +module_param(i8042_nomux, bool, 0);
> +
> +static unsigned int i8042_unlock;
> +module_param(i8042_unlock, bool, 0);
> +
> +static unsigned int i8042_reset;
> +module_param(i8042_reset, bool, 0);
> +
> +static unsigned int i8042_direct;
> +module_param(i8042_direct, bool, 0);
> +
> +static unsigned int i8042_dumbkbd;
> +module_param(i8042_dumbkbd, bool, 0);
>
> #undef DEBUG
> #include "i8042.h"
> @@ -59,6 +66,9 @@
> static unsigned char i8042_initial_ctr;
> static unsigned char i8042_ctr;
> static unsigned char i8042_mux_open;
> +static unsigned char i8042_mux_present;
> +static unsigned char i8042_sysdev_initialized;
> +static struct pm_dev *i8042_pm_dev;
> struct timer_list i8042_timer;
>
> /*
> @@ -214,16 +224,41 @@
> }
>
> /*
> - * i8042_open() is called when a port is open by the higher layer.
> - * It allocates the interrupt and enables it in the chip.
> + * i8042_activate_port() enables port on a chip.
> */
>
> -static int i8042_open(struct serio *port)
> +static int i8042_activate_port(struct serio *port)
> {
> struct i8042_values *values = port->driver;
>
> i8042_flush();
>
> + /*
> + * Enable port again here because it is disabled if we are
> + * resuming (normally it is enabled already).
> + */
> + i8042_ctr &= ~values->disable;
> +
> + i8042_ctr |= values->irqen;
> +
> + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
> + i8042_ctr &= ~values->irqen;
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +
> +/*
> + * i8042_open() is called when a port is open by the higher layer.
> + * It allocates the interrupt and calls i8042_enable_port.
> + */
> +
> +static int i8042_open(struct serio *port)
> +{
> + struct i8042_values *values = port->driver;
> +
> if (values->mux != -1)
> if (i8042_mux_open++)
> return 0;
> @@ -234,10 +269,8 @@
> goto irq_fail;
> }
>
> - i8042_ctr |= values->irqen;
> -
> - if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
> - printk(KERN_ERR "i8042.c: Can't write CTR while opening %s, unregistering the port\n", values->name);
> + if (i8042_activate_port(port)) {
> + printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", values->name);
> goto ctr_fail;
> }
>
> @@ -246,7 +279,6 @@
> return 0;
>
> ctr_fail:
> - i8042_ctr &= ~values->irqen;
> free_irq(values->irq, i8042_request_irq_cookie);
>
> irq_fail:
> @@ -400,146 +432,80 @@
> return IRQ_RETVAL(j);
> }
>
> +
> /*
> - * i8042_controller init initializes the i8042 controller, and,
> - * most importantly, sets it into non-xlated mode if that's
> - * desired.
> + * i8042_enable_mux_mode checks whether the controller has an active
> + * multiplexor and puts the chip into Multiplexed (as opposed to
> + * Legacy) mode.
> */
> -
> -static int __init i8042_controller_init(void)
> +
> +static int i8042_enable_mux_mode(struct i8042_values *values, unsigned char *mux_version)
> {
>
> + unsigned char param;
> /*
> - * Test the i8042. We need to know if it thinks it's working correctly
> - * before doing anything else.
> + * Get rid of bytes in the queue.
> */
>
> i8042_flush();
>
> - if (i8042_reset) {
> -
> - unsigned char param;
> -
> - if (i8042_command(¶m, I8042_CMD_CTL_TEST)) {
> - printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
> - return -1;
> - }
> -
> - if (param != I8042_RET_CTL_TEST) {
> - printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
> - param, I8042_RET_CTL_TEST);
> - return -1;
> - }
> - }
> -
> /*
> - * Save the CTR for restoral on unload / reboot.
> + * Internal loopback test - send three bytes, they should come back from the
> + * mouse interface, the last should be version. Note that we negate mouseport
> + * command responses for the i8042_check_aux() routine.
> */
>
> - if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
> - printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
> + param = 0xf0;
> + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x0f)
> + return -1;
> + param = 0x56;
> + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xa9)
> + return -1;
> + param = 0xa4;
> + if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == 0x5b)
> return -1;
> - }
> -
> - i8042_initial_ctr = i8042_ctr;
> -
> -/*
> - * Disable the keyboard interface and interrupt.
> - */
>
> - i8042_ctr |= I8042_CTR_KBDDIS;
> - i8042_ctr &= ~I8042_CTR_KBDINT;
> + if (mux_version)
> + *mux_version = ~param;
>
> -/*
> - * Handle keylock.
> - */
> + return 0;
> +}
>
> - if (~i8042_read_status() & I8042_STR_KEYLOCK) {
> - if (i8042_unlock)
> - i8042_ctr |= I8042_CTR_IGNKEYLOCK;
> - else
> - printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
> - }
>
> /*
> - * If the chip is configured into nontranslated mode by the BIOS, don't
> - * bother enabling translating and be happy.
> + * i8042_enable_mux_ports enables 4 individual AUX ports after
> + * the controller has been switched into Multiplexed mode
> */
>
> - if (~i8042_ctr & I8042_CTR_XLATE)
> - i8042_direct = 1;
> -
> +static int i8042_enable_mux_ports(struct i8042_values *values)
> +{
> + unsigned char param;
> + int i;
> /*
> - * Set nontranslated mode for the kbd interface if requested by an option.
> - * After this the kbd interface becomes a simple serial in/out, like the aux
> - * interface is. We don't do this by default, since it can confuse notebook
> - * BIOSes.
> + * Disable all muxed ports by disabling AUX.
> */
>
> - if (i8042_direct) {
> - i8042_ctr &= ~I8042_CTR_XLATE;
> - i8042_kbd_port.type = SERIO_8042;
> - }
> -
> -/*
> - * Write CTR back.
> - */
> + i8042_ctr |= I8042_CTR_AUXDIS;
> + i8042_ctr &= ~I8042_CTR_AUXINT;
>
> if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
> - printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n");
> + printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n");
> return -1;
> }
>
> - return 0;
> -}
> -
> /*
> - * Here we try to reset everything back to a state in which the BIOS will be
> - * able to talk to the hardware when rebooting.
> - */
> -
> -void i8042_controller_cleanup(void)
> -{
> - int i;
> -
> - i8042_flush();
> -
> -/*
> - * Reset anything that is connected to the ports.
> - */
> -
> - if (i8042_kbd_values.exists)
> - serio_cleanup(&i8042_kbd_port);
> -
> - if (i8042_aux_values.exists)
> - serio_cleanup(&i8042_aux_port);
> -
> - for (i = 0; i < 4; i++)
> - if (i8042_mux_values[i].exists)
> - serio_cleanup(i8042_mux_port + i);
> -
> -/*
> - * Reset the controller.
> + * Enable all muxed ports.
> */
>
> - if (i8042_reset) {
> - unsigned char param;
> -
> - if (i8042_command(¶m, I8042_CMD_CTL_TEST))
> - printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
> + for (i = 0; i < 4; i++) {
> + i8042_command(¶m, I8042_CMD_MUX_PFX + i);
> + i8042_command(¶m, I8042_CMD_AUX_ENABLE);
> }
>
> -/*
> - * Restore the original control register setting.
> - */
> -
> - i8042_ctr = i8042_initial_ctr;
> -
> - if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
> - printk(KERN_WARNING "i8042.c: Can't restore CTR.\n");
> -
> + return 0;
> }
>
> +
> /*
> * i8042_check_mux() checks whether the controller supports the PS/2 Active
> * Multiplexing specification by Synaptics, Phoenix, Insyde and
> @@ -548,66 +514,31 @@
>
> static int __init i8042_check_mux(struct i8042_values *values)
> {
> - unsigned char param;
> static int i8042_check_mux_cookie;
> - int i;
> + unsigned char mux_version;
>
> /*
> * Check if AUX irq is available.
> */
> -
> if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
> "i8042", &i8042_check_mux_cookie))
> return -1;
> free_irq(values->irq, &i8042_check_mux_cookie);
>
> -/*
> - * Get rid of bytes in the queue.
> - */
> -
> - i8042_flush();
> -
> -/*
> - * Internal loopback test - send three bytes, they should come back from the
> - * mouse interface, the last should be version. Note that we negate mouseport
> - * command responses for the i8042_check_aux() routine.
> - */
> -
> - param = 0xf0;
> - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x0f)
> - return -1;
> - param = 0x56;
> - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xa9)
> - return -1;
> - param = 0xa4;
> - if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == 0x5b)
> + if (i8042_enable_mux_mode(values, &mux_version))
> return -1;
>
> printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n",
> - (~param >> 4) & 0xf, ~param & 0xf);
> -
> -/*
> - * Disable all muxed ports by disabling AUX.
> - */
> -
> - i8042_ctr |= I8042_CTR_AUXDIS;
> - i8042_ctr &= ~I8042_CTR_AUXINT;
> + (mux_version >> 4) & 0xf, mux_version & 0xf);
>
> - if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
> + if (i8042_enable_mux_ports(values))
> return -1;
>
> -/*
> - * Enable all muxed ports.
> - */
> -
> - for (i = 0; i < 4; i++) {
> - i8042_command(¶m, I8042_CMD_MUX_PFX + i);
> - i8042_command(¶m, I8042_CMD_AUX_ENABLE);
> - }
> -
> + i8042_mux_present = 1;
> return 0;
> }
>
> +
> /*
> * i8042_check_aux() applies as much paranoia as it can at detecting
> * the presence of an AUX interface.
> @@ -683,6 +614,7 @@
> return 0;
> }
>
> +
> /*
> * i8042_port_register() marks the device as existing,
> * registers it, and reports to the user.
> @@ -710,52 +642,194 @@
> return 0;
> }
>
> +
> static void i8042_timer_func(unsigned long data)
> {
> i8042_interrupt(0, NULL, NULL);
> mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
> }
>
> -#ifndef MODULE
> -static int __init i8042_setup_reset(char *str)
> -{
> - i8042_reset = 1;
> - return 1;
> -}
> -static int __init i8042_setup_noaux(char *str)
> -{
> - i8042_noaux = 1;
> - i8042_nomux = 1;
> - return 1;
> -}
> -static int __init i8042_setup_nomux(char *str)
> -{
> - i8042_nomux = 1;
> - return 1;
> -}
> -static int __init i8042_setup_unlock(char *str)
> +
> +/*
> + * i8042_controller init initializes the i8042 controller, and,
> + * most importantly, sets it into non-xlated mode if that's
> + * desired.
> + */
> +
> +static int i8042_controller_init(void)
> {
> - i8042_unlock = 1;
> - return 1;
> +
> + if (i8042_noaux)
> + i8042_nomux = 1;
> +/*
> + * Test the i8042. We need to know if it thinks it's working correctly
> + * before doing anything else.
> + */
> +
> + i8042_flush();
> +
> + if (i8042_reset) {
> +
> + unsigned char param;
> +
> + if (i8042_command(¶m, I8042_CMD_CTL_TEST)) {
> + printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
> + return -1;
> + }
> +
> + if (param != I8042_RET_CTL_TEST) {
> + printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
> + param, I8042_RET_CTL_TEST);
> + return -1;
> + }
> + }
> +
> +/*
> + * Save the CTR for restoral on unload / reboot.
> + */
> +
> + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
> + printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
> + return -1;
> + }
> +
> + i8042_initial_ctr = i8042_ctr;
> +
> +/*
> + * Disable the keyboard interface and interrupt.
> + */
> +
> + i8042_ctr |= I8042_CTR_KBDDIS;
> + i8042_ctr &= ~I8042_CTR_KBDINT;
> +
> +/*
> + * Handle keylock.
> + */
> +
> + if (~i8042_read_status() & I8042_STR_KEYLOCK) {
> + if (i8042_unlock)
> + i8042_ctr |= I8042_CTR_IGNKEYLOCK;
> + else
> + printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
> + }
> +
> +/*
> + * If the chip is configured into nontranslated mode by the BIOS, don't
> + * bother enabling translating and be happy.
> + */
> +
> + if (~i8042_ctr & I8042_CTR_XLATE)
> + i8042_direct = 1;
> +
> +/*
> + * Set nontranslated mode for the kbd interface if requested by an option.
> + * After this the kbd interface becomes a simple serial in/out, like the aux
> + * interface is. We don't do this by default, since it can confuse notebook
> + * BIOSes.
> + */
> +
> + if (i8042_direct) {
> + i8042_ctr &= ~I8042_CTR_XLATE;
> + i8042_kbd_port.type = SERIO_8042;
> + }
> +
> +/*
> + * Write CTR back.
> + */
> +
> + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
> + printk(KERN_ERR "i8042.c: Can't write CTR while initializing i8042.\n");
> + return -1;
> + }
> +
> + return 0;
> }
> -static int __init i8042_setup_direct(char *str)
> +
> +
> +/*
> + * Here we try to reset everything back to a state in which the BIOS will be
> + * able to talk to the hardware when rebooting.
> + */
> +
> +void i8042_controller_cleanup(void)
> {
> - i8042_direct = 1;
> - return 1;
> + int i;
> +
> + i8042_flush();
> +
> +/*
> + * Reset anything that is connected to the ports.
> + */
> +
> + if (i8042_kbd_values.exists)
> + serio_cleanup(&i8042_kbd_port);
> +
> + if (i8042_aux_values.exists)
> + serio_cleanup(&i8042_aux_port);
> +
> + for (i = 0; i < 4; i++)
> + if (i8042_mux_values[i].exists)
> + serio_cleanup(i8042_mux_port + i);
> +
> +/*
> + * Reset the controller.
> + */
> +
> + if (i8042_reset) {
> + unsigned char param;
> +
> + if (i8042_command(¶m, I8042_CMD_CTL_TEST))
> + printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
> + }
> +
> +/*
> + * Restore the original control register setting.
> + */
> +
> + i8042_ctr = i8042_initial_ctr;
> +
> + if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
> + printk(KERN_WARNING "i8042.c: Can't restore CTR.\n");
> +
> }
> -static int __init i8042_setup_dumbkbd(char *str)
> +
> +
> +/*
> + * Here we try to reset everything back to a state in which suspended
> + */
> +
> +static int i8042_controller_resume(void)
> {
> - i8042_dumbkbd = 1;
> - return 1;
> + int i;
> +
> + if (i8042_controller_init()) {
> + printk(KERN_ERR "i8042: resume failed\n");
> + return -1;
> + }
> +
> + if (i8042_mux_present)
> + if (i8042_enable_mux_mode(&i8042_aux_values, NULL) ||
> + i8042_enable_mux_ports(&i8042_aux_values)) {
> + printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't wotk.\n");
> + }
> +
> +/*
> + * Reconnect anything that was connected to the ports.
> + */
> +
> + if (i8042_kbd_values.exists && i8042_activate_port(&i8042_kbd_port) == 0)
> + serio_reconnect(&i8042_kbd_port);
> +
> + if (i8042_aux_values.exists && i8042_activate_port(&i8042_aux_port) == 0)
> + serio_reconnect(&i8042_aux_port);
> +
> + for (i = 0; i < 4; i++)
> + if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port + i) == 0)
> + serio_reconnect(i8042_mux_port + i);
> +
> + return 0;
> }
>
> -__setup("i8042_reset", i8042_setup_reset);
> -__setup("i8042_noaux", i8042_setup_noaux);
> -__setup("i8042_nomux", i8042_setup_nomux);
> -__setup("i8042_unlock", i8042_setup_unlock);
> -__setup("i8042_direct", i8042_setup_direct);
> -__setup("i8042_dumbkbd", i8042_setup_dumbkbd);
> -#endif
>
> /*
> * We need to reset the 8042 back to original mode on system shutdown,
> @@ -777,6 +851,35 @@
> 0
> };
>
> +/*
> + * Resume handler for the new PM scheme (driver model)
> + */
> +static int i8042_resume(struct sys_device *dev)
> +{
> + return i8042_controller_resume();
> +}
> +
> +static struct sysdev_class kbc_sysclass = {
> + set_kset_name("i8042"),
> + .resume = i8042_resume,
> +};
> +
> +static struct sys_device device_i8042 = {
> + .id = 0,
> + .cls = &kbc_sysclass,
> +};
> +
> +/*
> + * Resume handler for the old PM scheme (APM)
> + */
> +static int i8042_pm_callback(struct pm_dev *dev, pm_request_t request, void *dummy)
> +{
> + if (request == PM_RESUME)
> + return i8042_controller_resume();
> +
> + return 0;
> +}
> +
> static void __init i8042_init_mux_values(struct i8042_values *values, struct serio *port, int index)
> {
> memcpy(port, &i8042_aux_port, sizeof(struct serio));
> @@ -825,6 +928,15 @@
> i8042_timer.function = i8042_timer_func;
> mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
>
> + if (sysdev_class_register(&kbc_sysclass) == 0) {
> + if (sys_device_register(&device_i8042) == 0)
> + i8042_sysdev_initialized = 1;
> + else
> + sysdev_class_unregister(&kbc_sysclass);
> + }
> +
> + i8042_pm_dev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, i8042_pm_callback);
> +
> register_reboot_notifier(&i8042_notifier);
>
> return 0;
> @@ -835,6 +947,14 @@
> int i;
>
> unregister_reboot_notifier(&i8042_notifier);
> +
> + if (i8042_pm_dev)
> + pm_unregister(i8042_pm_dev);
> +
> + if (i8042_sysdev_initialized) {
> + sys_device_unregister(&device_i8042);
> + sysdev_class_unregister(&kbc_sysclass);
> + }
>
> del_timer(&i8042_timer);
>
--
Vojtech Pavlik
SuSE Labs, SuSE CR
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2003-12-07 9:29 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-12-07 7:27 [PATCH 2.6 1/3] Take 2: resume support for i8042 (atkbd & psmouse) Dmitry Torokhov
2003-12-07 7:28 ` [PATCH 2.6 2/3] " Dmitry Torokhov
2003-12-07 7:29 ` Dmitry Torokhov
2003-12-07 9:28 ` [PATCH 2.6 1/3] " Vojtech Pavlik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox