patch-2.1.89 linux/drivers/char/apm_bios.c

Next file: linux/drivers/char/atarimouse.c
Previous file: linux/drivers/char/amigamouse.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.88/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
@@ -27,6 +27,7 @@
  *    Version 1.0 and 1.1
  * May 1996, Version 1.2
  * Feb 1998, Version 1.3
+ * Feb 1998, Version 1.4
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
@@ -46,8 +47,11 @@
  *         The new replacment for it is, but Linux doesn't yet support this.
  *         Alan Cox Linux 2.1.55
  *    1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
+ *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by 
+ *         Dean Gaudet <dgaudet@arctic.org>.
+ *         C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
  *
- * Reference:
+ * APM 1.1 Reference:
  *
  *   Intel Corporation, Microsoft Corporation. Advanced Power Management
  *   (APM) BIOS Interface Specification, Revision 1.1, September 1993.
@@ -58,6 +62,15 @@
  * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc.  It is also
  * available from Microsoft by calling 206.882.8080.]
  *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Intel at:
+ *    http://www.intel.com/IAL/powermgm
+ *  or Microsoft at
+ *    http://www.microsoft.com/windows/thirdparty/hardware/pcfuture.htm
+ * ]
  */
 
 #include <linux/config.h>
@@ -128,6 +141,11 @@
  * problems have been reported when using this option with gpm (if you'd
  * like to debug this, please do so).
  *
+ * CONFIG_APM_IGNORE_MULTIPLE_SUSPEND: The IBM TP560 bios seems to insist
+ * on returning multiple suspend/standby events whenever one occurs.  We
+ * really only need one at a time, so just ignore any beyond the first.
+ * This is probably safe on most laptops.
+ *
  * If you are debugging the APM support for your laptop, note that code for
  * all of these options is contained in this file, so you can #define or
  * #undef these on the next line to avoid recompiling the whole kernel.
@@ -341,6 +359,9 @@
 #endif
 static int			suspends_pending = 0;
 static int			standbys_pending = 0;
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+static int			waiting_for_resume = 0;
+#endif
 
 static long			clock_cmos_diff;
 static int			got_clock_diff = 0;
@@ -350,7 +371,7 @@
 
 static struct timer_list	apm_timer;
 
-static char			driver_version[] = "1.3";	/* no spaces */
+static char			driver_version[] = "1.4";	/* no spaces */
 
 #ifdef APM_DEBUG
 static char *	apm_event_name[] = {
@@ -614,8 +635,15 @@
 		if (as == sender)
 			continue;
 		as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
-		if (as->event_head == as->event_tail)
+		if (as->event_head == as->event_tail) {
+			static int notified;
+
+			if (notified == 0) {
+			    printk( "apm_bios: an event queue overflowed\n" );
+			    notified = 1;
+			}
 			as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+		}
 		as->events[as->event_head] = event;
 		if (!as->suser)
 			continue;
@@ -722,9 +750,23 @@
 	apm_event_t	event;
 
 	while ((event = get_event()) != 0) {
+#ifdef APM_DEBUG
+		if (event <= NR_APM_EVENT_NAME)
+			printk(KERN_DEBUG "APM BIOS received %s notify\n",
+			       apm_event_name[event - 1]);
+		else
+			printk(KERN_DEBUG "APM BIOS received unknown "
+			       "event 0x%02x\n", event);
+#endif
 		switch (event) {
 		case APM_SYS_STANDBY:
 		case APM_USER_STANDBY:
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+			if (waiting_for_resume) {
+			    return;
+			}
+			waiting_for_resume = 1;
+#endif
 			send_event(event, APM_STANDBY_RESUME, NULL);
 			if (standbys_pending <= 0)
 				standby();
@@ -737,6 +779,12 @@
 			break;
 #endif
 		case APM_SYS_SUSPEND:
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+			if (waiting_for_resume) {
+			    return;
+			}
+			waiting_for_resume = 1;
+#endif
 			send_event(event, APM_NORMAL_RESUME, NULL);
 			if (suspends_pending <= 0)
 				suspend();
@@ -745,6 +793,9 @@
 		case APM_NORMAL_RESUME:
 		case APM_CRITICAL_RESUME:
 		case APM_STANDBY_RESUME:
+#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+			waiting_for_resume = 0;
+#endif
 			set_time();
 			send_event(event, 0, NULL);
 			break;
@@ -763,14 +814,6 @@
 			suspend();
 			break;
 		}
-#ifdef APM_DEBUG
-		if (event <= NR_APM_EVENT_NAME)
-			printk(KERN_DEBUG "APM BIOS received %s notify\n",
-			       apm_event_name[event - 1]);
-		else
-			printk(KERN_DEBUG "APM BIOS received unknown event 0x%02x\n",
-			       event);
-#endif
 	}
 }
 
@@ -905,7 +948,7 @@
 	as = fp->private_data;
 	if (check_apm_bios_struct(as, "select"))
 		return 0;
-	poll_wait(&process_list, wait);
+	poll_wait(fp, &process_list, wait);
 	if (!queue_empty(as))
 		return POLLIN | POLLRDNORM;
 	return 0;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov