[POWERPC] Remove unused do_signal export
[linux-2.6] / arch / i386 / kernel / apm.c
1 /* -*- linux-c -*-
2  * APM BIOS driver for Linux
3  * Copyright 1994-2001 Stephen Rothwell (sfr@canb.auug.org.au)
4  *
5  * Initial development of this driver was funded by NEC Australia P/L
6  *      and NEC Corporation
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2, or (at your option) any
11  * later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * October 1995, Rik Faith (faith@cs.unc.edu):
19  *    Minor enhancements and updates (to the patch set) for 1.3.x
20  *    Documentation
21  * January 1996, Rik Faith (faith@cs.unc.edu):
22  *    Make /proc/apm easy to format (bump driver version)
23  * March 1996, Rik Faith (faith@cs.unc.edu):
24  *    Prohibit APM BIOS calls unless apm_enabled.
25  *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
26  * April 1996, Stephen Rothwell (sfr@canb.auug.org.au)
27  *    Version 1.0 and 1.1
28  * May 1996, Version 1.2
29  * Feb 1998, Version 1.3
30  * Feb 1998, Version 1.4
31  * Aug 1998, Version 1.5
32  * Sep 1998, Version 1.6
33  * Nov 1998, Version 1.7
34  * Jan 1999, Version 1.8
35  * Jan 1999, Version 1.9
36  * Oct 1999, Version 1.10
37  * Nov 1999, Version 1.11
38  * Jan 2000, Version 1.12
39  * Feb 2000, Version 1.13
40  * Nov 2000, Version 1.14
41  * Oct 2001, Version 1.15
42  * Jan 2002, Version 1.16
43  * Oct 2002, Version 1.16ac
44  *
45  * History:
46  *    0.6b: first version in official kernel, Linux 1.3.46
47  *    0.7: changed /proc/apm format, Linux 1.3.58
48  *    0.8: fixed gcc 2.7.[12] compilation problems, Linux 1.3.59
49  *    0.9: only call bios if bios is present, Linux 1.3.72
50  *    1.0: use fixed device number, consolidate /proc/apm into this file,
51  *         Linux 1.3.85
52  *    1.1: support user-space standby and suspend, power off after system
53  *         halted, Linux 1.3.98
54  *    1.2: When resetting RTC after resume, take care so that the time
55  *         is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
56  *         <jtoth@princeton.edu>); improve interaction between
57  *         screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
58  *    1.2a:Simple change to stop mysterious bug reports with SMP also added
59  *         levels to the printk calls. APM is not defined for SMP machines.
60  *         The new replacment for it is, but Linux doesn't yet support this.
61  *         Alan Cox Linux 2.1.55
62  *    1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
63  *    1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
64  *         Dean Gaudet <dgaudet@arctic.org>.
65  *         C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
66  *    1.5: Fix segment register reloading (in case of bad segments saved
67  *         across BIOS call).
68  *         Stephen Rothwell
69  *    1.6: Cope with complier/assembler differences.
70  *         Only try to turn off the first display device.
71  *         Fix OOPS at power off with no APM BIOS by Jan Echternach
72  *                   <echter@informatik.uni-rostock.de>
73  *         Stephen Rothwell
74  *    1.7: Modify driver's cached copy of the disabled/disengaged flags
75  *         to reflect current state of APM BIOS.
76  *         Chris Rankin <rankinc@bellsouth.net>
77  *         Reset interrupt 0 timer to 100Hz after suspend
78  *         Chad Miller <cmiller@surfsouth.com>
79  *         Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE
80  *         Richard Gooch <rgooch@atnf.csiro.au>
81  *         Allow boot time disabling of APM
82  *         Make boot messages far less verbose by default
83  *         Make asm safer
84  *         Stephen Rothwell
85  *    1.8: Add CONFIG_APM_RTC_IS_GMT
86  *         Richard Gooch <rgooch@atnf.csiro.au>
87  *         change APM_NOINTS to CONFIG_APM_ALLOW_INTS
88  *         remove dependency on CONFIG_PROC_FS
89  *         Stephen Rothwell
90  *    1.9: Fix small typo.  <laslo@wodip.opole.pl>
91  *         Try to cope with BIOS's that need to have all display
92  *         devices blanked and not just the first one.
93  *         Ross Paterson <ross@soi.city.ac.uk>
94  *         Fix segment limit setting it has always been wrong as
95  *         the segments needed to have byte granularity.
96  *         Mark a few things __init.
97  *         Add hack to allow power off of SMP systems by popular request.
98  *         Use CONFIG_SMP instead of __SMP__
99  *         Ignore BOUNCES for three seconds.
100  *         Stephen Rothwell
101  *   1.10: Fix for Thinkpad return code.
102  *         Merge 2.2 and 2.3 drivers.
103  *         Remove APM dependencies in arch/i386/kernel/process.c
104  *         Remove APM dependencies in drivers/char/sysrq.c
105  *         Reset time across standby.
106  *         Allow more inititialisation on SMP.
107  *         Remove CONFIG_APM_POWER_OFF and make it boot time
108  *         configurable (default on).
109  *         Make debug only a boot time parameter (remove APM_DEBUG).
110  *         Try to blank all devices on any error.
111  *   1.11: Remove APM dependencies in drivers/char/console.c
112  *         Check nr_running to detect if we are idle (from
113  *         Borislav Deianov <borislav@lix.polytechnique.fr>)
114  *         Fix for bioses that don't zero the top part of the
115  *         entrypoint offset (Mario Sitta <sitta@al.unipmn.it>)
116  *         (reported by Panos Katsaloulis <teras@writeme.com>).
117  *         Real mode power off patch (Walter Hofmann
118  *         <Walter.Hofmann@physik.stud.uni-erlangen.de>).
119  *   1.12: Remove CONFIG_SMP as the compiler will optimize
120  *         the code away anyway (smp_num_cpus == 1 in UP)
121  *         noted by Artur Skawina <skawina@geocities.com>.
122  *         Make power off under SMP work again.
123  *         Fix thinko with initial engaging of BIOS.
124  *         Make sure power off only happens on CPU 0
125  *         (Paul "Rusty" Russell <rusty@rustcorp.com.au>).
126  *         Do error notification to user mode if BIOS calls fail.
127  *         Move entrypoint offset fix to ...boot/setup.S
128  *         where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
129  *         Remove smp-power-off. SMP users must now specify
130  *         "apm=power-off" on the kernel command line. Suggested
131  *         by Jim Avera <jima@hal.com>, modified by Alan Cox
132  *         <alan@lxorguk.ukuu.org.uk>.
133  *         Register the /proc/apm entry even on SMP so that
134  *         scripts that check for it before doing power off
135  *         work (Jim Avera <jima@hal.com>).
136  *   1.13: Changes for new pm_ interfaces (Andy Henroid
137  *         <andy_henroid@yahoo.com>).
138  *         Modularize the code.
139  *         Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
140  *         is now the way life works).
141  *         Fix thinko in suspend() (wrong return).
142  *         Notify drivers on critical suspend.
143  *         Make kapmd absorb more idle time (Pavel Machek <pavel@suse.cz>
144  *         modified by sfr).
145  *         Disable interrupts while we are suspended (Andy Henroid
146  *         <andy_henroid@yahoo.com> fixed by sfr).
147  *         Make power off work on SMP again (Tony Hoyle
148  *         <tmh@magenta-logic.com> and <zlatko@iskon.hr>) modified by sfr.
149  *         Remove CONFIG_APM_SUSPEND_BOUNCE.  The bounce ignore
150  *         interval is now configurable.
151  *   1.14: Make connection version persist across module unload/load.
152  *         Enable and engage power management earlier.
153  *         Disengage power management on module unload.
154  *         Changed to use the sysrq-register hack for registering the
155  *         power off function called by magic sysrq based upon discussions
156  *         in irc://irc.openprojects.net/#kernelnewbies
157  *         (Crutcher Dunnavant <crutcher+kernel@datastacks.com>).
158  *         Make CONFIG_APM_REAL_MODE_POWER_OFF run time configurable.
159  *         (Arjan van de Ven <arjanv@redhat.com>) modified by sfr.
160  *         Work around byte swap bug in one of the Vaio's BIOS's
161  *         (Marc Boucher <marc@mbsi.ca>).
162  *         Exposed the disable flag to dmi so that we can handle known
163  *         broken APM (Alan Cox <alan@redhat.com>).
164  *   1.14ac: If the BIOS says "I slowed the CPU down" then don't spin
165  *         calling it - instead idle. (Alan Cox <alan@redhat.com>)
166  *         If an APM idle fails log it and idle sensibly
167  *   1.15: Don't queue events to clients who open the device O_WRONLY.
168  *         Don't expect replies from clients who open the device O_RDONLY.
169  *         (Idea from Thomas Hood)
170  *         Minor waitqueue cleanups. (John Fremlin <chief@bandits.org>)
171  *   1.16: Fix idle calling. (Andreas Steinmetz <ast@domdv.de> et al.)
172  *         Notify listeners of standby or suspend events before notifying
173  *         drivers. Return EBUSY to ioctl() if suspend is rejected.
174  *         (Russell King <rmk@arm.linux.org.uk> and Thomas Hood)
175  *         Ignore first resume after we generate our own resume event
176  *         after a suspend (Thomas Hood)
177  *         Daemonize now gets rid of our controlling terminal (sfr).
178  *         CONFIG_APM_CPU_IDLE now just affects the default value of
179  *         idle_threshold (sfr).
180  *         Change name of kernel apm daemon (as it no longer idles) (sfr).
181  *   1.16ac: Fix up SMP support somewhat. You can now force SMP on and we
182  *         make _all_ APM calls on the CPU#0. Fix unsafe sign bug.
183  *         TODO: determine if its "boot CPU" or "CPU0" we want to lock to.
184  *
185  * APM 1.1 Reference:
186  *
187  *   Intel Corporation, Microsoft Corporation. Advanced Power Management
188  *   (APM) BIOS Interface Specification, Revision 1.1, September 1993.
189  *   Intel Order Number 241704-001.  Microsoft Part Number 781-110-X01.
190  *
191  * [This document is available free from Intel by calling 800.628.8686 (fax
192  * 916.356.6100) or 800.548.4725; or via anonymous ftp from
193  * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc.  It is also
194  * available from Microsoft by calling 206.882.8080.]
195  *
196  * APM 1.2 Reference:
197  *   Intel Corporation, Microsoft Corporation. Advanced Power Management
198  *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
199  *
200  * [This document is available from Microsoft at:
201  *    http://www.microsoft.com/whdc/archive/amp_12.mspx]
202  */
203
204 #include <linux/module.h>
205
206 #include <linux/poll.h>
207 #include <linux/types.h>
208 #include <linux/stddef.h>
209 #include <linux/timer.h>
210 #include <linux/fcntl.h>
211 #include <linux/slab.h>
212 #include <linux/stat.h>
213 #include <linux/proc_fs.h>
214 #include <linux/seq_file.h>
215 #include <linux/miscdevice.h>
216 #include <linux/apm_bios.h>
217 #include <linux/init.h>
218 #include <linux/time.h>
219 #include <linux/sched.h>
220 #include <linux/pm.h>
221 #include <linux/pm_legacy.h>
222 #include <linux/capability.h>
223 #include <linux/device.h>
224 #include <linux/kernel.h>
225 #include <linux/smp.h>
226 #include <linux/dmi.h>
227 #include <linux/suspend.h>
228 #include <linux/kthread.h>
229
230 #include <asm/system.h>
231 #include <asm/uaccess.h>
232 #include <asm/desc.h>
233 #include <asm/i8253.h>
234 #include <asm/paravirt.h>
235 #include <asm/reboot.h>
236
237 #include "io_ports.h"
238
239 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
240 extern int (*console_blank_hook)(int);
241 #endif
242
243 /*
244  * The apm_bios device is one of the misc char devices.
245  * This is its minor number.
246  */
247 #define APM_MINOR_DEV   134
248
249 /*
250  * See Documentation/Config.help for the configuration options.
251  *
252  * Various options can be changed at boot time as follows:
253  * (We allow underscores for compatibility with the modules code)
254  *      apm=on/off                      enable/disable APM
255  *          [no-]allow[-_]ints          allow interrupts during BIOS calls
256  *          [no-]broken[-_]psr          BIOS has a broken GetPowerStatus call
257  *          [no-]realmode[-_]power[-_]off       switch to real mode before
258  *                                              powering off
259  *          [no-]debug                  log some debugging messages
260  *          [no-]power[-_]off           power off on shutdown
261  *          [no-]smp                    Use apm even on an SMP box
262  *          bounce[-_]interval=<n>      number of ticks to ignore suspend
263  *                                      bounces
264  *          idle[-_]threshold=<n>       System idle percentage above which to
265  *                                      make APM BIOS idle calls. Set it to
266  *                                      100 to disable.
267  *          idle[-_]period=<n>          Period (in 1/100s of a second) over
268  *                                      which the idle percentage is
269  *                                      calculated.
270  */
271
272 /* KNOWN PROBLEM MACHINES:
273  *
274  * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
275  *                         [Confirmed by TI representative]
276  * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
277  *                    [Confirmed by BIOS disassembly]
278  *                    [This may work now ...]
279  * P: Toshiba 1950S: battery life information only gets updated after resume
280  * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
281  *      broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
282  * ?: AcerNote-950: oops on reading /proc/apm - workaround is a WIP
283  *      Neale Banks <neale@lowendale.com.au> December 2000
284  *
285  * Legend: U = unusable with APM patches
286  *         P = partially usable with APM patches
287  */
288
289 /*
290  * Define as 1 to make the driver always call the APM BIOS busy
291  * routine even if the clock was not reported as slowed by the
292  * idle routine.  Otherwise, define as 0.
293  */
294 #define ALWAYS_CALL_BUSY   1
295
296 /*
297  * Define to make the APM BIOS calls zero all data segment registers (so
298  * that an incorrect BIOS implementation will cause a kernel panic if it
299  * tries to write to arbitrary memory).
300  */
301 #define APM_ZERO_SEGS
302
303 #include "apm.h"
304
305 /*
306  * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
307  * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
308  * David Chen <chen@ctpa04.mit.edu>
309  */
310 #undef INIT_TIMER_AFTER_SUSPEND
311
312 #ifdef INIT_TIMER_AFTER_SUSPEND
313 #include <linux/timex.h>
314 #include <asm/io.h>
315 #include <linux/delay.h>
316 #endif
317
318 /*
319  * Need to poll the APM BIOS every second
320  */
321 #define APM_CHECK_TIMEOUT       (HZ)
322
323 /*
324  * Ignore suspend events for this amount of time after a resume
325  */
326 #define DEFAULT_BOUNCE_INTERVAL         (3 * HZ)
327
328 /*
329  * Maximum number of events stored
330  */
331 #define APM_MAX_EVENTS          20
332
333 /*
334  * The per-file APM data
335  */
336 struct apm_user {
337         int             magic;
338         struct apm_user *       next;
339         unsigned int    suser: 1;
340         unsigned int    writer: 1;
341         unsigned int    reader: 1;
342         unsigned int    suspend_wait: 1;
343         int             suspend_result;
344         int             suspends_pending;
345         int             standbys_pending;
346         int             suspends_read;
347         int             standbys_read;
348         int             event_head;
349         int             event_tail;
350         apm_event_t     events[APM_MAX_EVENTS];
351 };
352
353 /*
354  * The magic number in apm_user
355  */
356 #define APM_BIOS_MAGIC          0x4101
357
358 /*
359  * idle percentage above which bios idle calls are done
360  */
361 #ifdef CONFIG_APM_CPU_IDLE
362 #define DEFAULT_IDLE_THRESHOLD  95
363 #else
364 #define DEFAULT_IDLE_THRESHOLD  100
365 #endif
366 #define DEFAULT_IDLE_PERIOD     (100 / 3)
367
368 /*
369  * Local variables
370  */
371 static struct {
372         unsigned long   offset;
373         unsigned short  segment;
374 }                               apm_bios_entry;
375 static int                      clock_slowed;
376 static int                      idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD;
377 static int                      idle_period __read_mostly = DEFAULT_IDLE_PERIOD;
378 static int                      set_pm_idle;
379 static int                      suspends_pending;
380 static int                      standbys_pending;
381 static int                      ignore_sys_suspend;
382 static int                      ignore_normal_resume;
383 static int                      bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL;
384
385 static int                      debug __read_mostly;
386 static int                      smp __read_mostly;
387 static int                      apm_disabled = -1;
388 #ifdef CONFIG_SMP
389 static int                      power_off;
390 #else
391 static int                      power_off = 1;
392 #endif
393 #ifdef CONFIG_APM_REAL_MODE_POWER_OFF
394 static int                      realmode_power_off = 1;
395 #else
396 static int                      realmode_power_off;
397 #endif
398 #ifdef CONFIG_APM_ALLOW_INTS
399 static int                      allow_ints = 1;
400 #else
401 static int                      allow_ints;
402 #endif
403 static int                      broken_psr;
404
405 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
406 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
407 static struct apm_user *        user_list;
408 static DEFINE_SPINLOCK(user_list_lock);
409 static const struct desc_struct bad_bios_desc = { 0, 0x00409200 };
410
411 static const char               driver_version[] = "1.16ac";    /* no spaces */
412
413 static struct task_struct *kapmd_task;
414
415 /*
416  *      APM event names taken from the APM 1.2 specification. These are
417  *      the message codes that the BIOS uses to tell us about events
418  */
419 static const char *     const apm_event_name[] = {
420         "system standby",
421         "system suspend",
422         "normal resume",
423         "critical resume",
424         "low battery",
425         "power status change",
426         "update time",
427         "critical suspend",
428         "user standby",
429         "user suspend",
430         "system standby resume",
431         "capabilities change"
432 };
433 #define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
434
435 typedef struct lookup_t {
436         int     key;
437         char *  msg;
438 } lookup_t;
439
440 /*
441  *      The BIOS returns a set of standard error codes in AX when the
442  *      carry flag is set.
443  */
444  
445 static const lookup_t error_table[] = {
446 /* N/A  { APM_SUCCESS,          "Operation succeeded" }, */
447         { APM_DISABLED,         "Power management disabled" },
448         { APM_CONNECTED,        "Real mode interface already connected" },
449         { APM_NOT_CONNECTED,    "Interface not connected" },
450         { APM_16_CONNECTED,     "16 bit interface already connected" },
451 /* N/A  { APM_16_UNSUPPORTED,   "16 bit interface not supported" }, */
452         { APM_32_CONNECTED,     "32 bit interface already connected" },
453         { APM_32_UNSUPPORTED,   "32 bit interface not supported" },
454         { APM_BAD_DEVICE,       "Unrecognized device ID" },
455         { APM_BAD_PARAM,        "Parameter out of range" },
456         { APM_NOT_ENGAGED,      "Interface not engaged" },
457         { APM_BAD_FUNCTION,     "Function not supported" },
458         { APM_RESUME_DISABLED,  "Resume timer disabled" },
459         { APM_BAD_STATE,        "Unable to enter requested state" },
460 /* N/A  { APM_NO_EVENTS,        "No events pending" }, */
461         { APM_NO_ERROR,         "BIOS did not set a return code" },
462         { APM_NOT_PRESENT,      "No APM present" }
463 };
464 #define ERROR_COUNT     ARRAY_SIZE(error_table)
465
466 /**
467  *      apm_error       -       display an APM error
468  *      @str: information string
469  *      @err: APM BIOS return code
470  *
471  *      Write a meaningful log entry to the kernel log in the event of
472  *      an APM error.
473  */
474  
475 static void apm_error(char *str, int err)
476 {
477         int     i;
478
479         for (i = 0; i < ERROR_COUNT; i++)
480                 if (error_table[i].key == err) break;
481         if (i < ERROR_COUNT)
482                 printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg);
483         else
484                 printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n",
485                         str, err);
486 }
487
488 /*
489  * Lock APM functionality to physical CPU 0
490  */
491  
492 #ifdef CONFIG_SMP
493
494 static cpumask_t apm_save_cpus(void)
495 {
496         cpumask_t x = current->cpus_allowed;
497         /* Some bioses don't like being called from CPU != 0 */
498         set_cpus_allowed(current, cpumask_of_cpu(0));
499         BUG_ON(smp_processor_id() != 0);
500         return x;
501 }
502
503 static inline void apm_restore_cpus(cpumask_t mask)
504 {
505         set_cpus_allowed(current, mask);
506 }
507
508 #else
509
510 /*
511  *      No CPU lockdown needed on a uniprocessor
512  */
513  
514 #define apm_save_cpus()         (current->cpus_allowed)
515 #define apm_restore_cpus(x)     (void)(x)
516
517 #endif
518
519 /*
520  * These are the actual BIOS calls.  Depending on APM_ZERO_SEGS and
521  * apm_info.allow_ints, we are being really paranoid here!  Not only
522  * are interrupts disabled, but all the segment registers (except SS)
523  * are saved and zeroed this means that if the BIOS tries to reference
524  * any data without explicitly loading the segment registers, the kernel
525  * will fault immediately rather than have some unforeseen circumstances
526  * for the rest of the kernel.  And it will be very obvious!  :-) Doing
527  * this depends on CS referring to the same physical memory as DS so that
528  * DS can be zeroed before the call. Unfortunately, we can't do anything
529  * about the stack segment/pointer.  Also, we tell the compiler that
530  * everything could change.
531  *
532  * Also, we KNOW that for the non error case of apm_bios_call, there
533  * is no useful data returned in the low order 8 bits of eax.
534  */
535
536 static inline unsigned long __apm_irq_save(void)
537 {
538         unsigned long flags;
539         local_save_flags(flags);
540         if (apm_info.allow_ints) {
541                 if (irqs_disabled_flags(flags))
542                         local_irq_enable();
543         } else
544                 local_irq_disable();
545
546         return flags;
547 }
548
549 #define apm_irq_save(flags) \
550         do { flags = __apm_irq_save(); } while (0)
551
552 static inline void apm_irq_restore(unsigned long flags)
553 {
554         if (irqs_disabled_flags(flags))
555                 local_irq_disable();
556         else if (irqs_disabled())
557                 local_irq_enable();
558 }
559
560 #ifdef APM_ZERO_SEGS
561 #       define APM_DECL_SEGS \
562                 unsigned int saved_fs; unsigned int saved_gs;
563 #       define APM_DO_SAVE_SEGS \
564                 savesegment(fs, saved_fs); savesegment(gs, saved_gs)
565 #       define APM_DO_RESTORE_SEGS \
566                 loadsegment(fs, saved_fs); loadsegment(gs, saved_gs)
567 #else
568 #       define APM_DECL_SEGS
569 #       define APM_DO_SAVE_SEGS
570 #       define APM_DO_RESTORE_SEGS
571 #endif
572
573 /**
574  *      apm_bios_call   -       Make an APM BIOS 32bit call
575  *      @func: APM function to execute
576  *      @ebx_in: EBX register for call entry
577  *      @ecx_in: ECX register for call entry
578  *      @eax: EAX register return
579  *      @ebx: EBX register return
580  *      @ecx: ECX register return
581  *      @edx: EDX register return
582  *      @esi: ESI register return
583  *
584  *      Make an APM call using the 32bit protected mode interface. The
585  *      caller is responsible for knowing if APM BIOS is configured and
586  *      enabled. This call can disable interrupts for a long period of
587  *      time on some laptops.  The return value is in AH and the carry
588  *      flag is loaded into AL.  If there is an error, then the error
589  *      code is returned in AH (bits 8-15 of eax) and this function
590  *      returns non-zero.
591  */
592  
593 static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
594         u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
595 {
596         APM_DECL_SEGS
597         unsigned long           flags;
598         cpumask_t               cpus;
599         int                     cpu;
600         struct desc_struct      save_desc_40;
601         struct desc_struct      *gdt;
602
603         cpus = apm_save_cpus();
604         
605         cpu = get_cpu();
606         gdt = get_cpu_gdt_table(cpu);
607         save_desc_40 = gdt[0x40 / 8];
608         gdt[0x40 / 8] = bad_bios_desc;
609
610         apm_irq_save(flags);
611         APM_DO_SAVE_SEGS;
612         apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi);
613         APM_DO_RESTORE_SEGS;
614         apm_irq_restore(flags);
615         gdt[0x40 / 8] = save_desc_40;
616         put_cpu();
617         apm_restore_cpus(cpus);
618         
619         return *eax & 0xff;
620 }
621
622 /**
623  *      apm_bios_call_simple    -       make a simple APM BIOS 32bit call
624  *      @func: APM function to invoke
625  *      @ebx_in: EBX register value for BIOS call
626  *      @ecx_in: ECX register value for BIOS call
627  *      @eax: EAX register on return from the BIOS call
628  *
629  *      Make a BIOS call that returns one value only, or just status.
630  *      If there is an error, then the error code is returned in AH
631  *      (bits 8-15 of eax) and this function returns non-zero. This is
632  *      used for simpler BIOS operations. This call may hold interrupts
633  *      off for a long time on some laptops.
634  */
635
636 static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
637 {
638         u8                      error;
639         APM_DECL_SEGS
640         unsigned long           flags;
641         cpumask_t               cpus;
642         int                     cpu;
643         struct desc_struct      save_desc_40;
644         struct desc_struct      *gdt;
645
646         cpus = apm_save_cpus();
647         
648         cpu = get_cpu();
649         gdt = get_cpu_gdt_table(cpu);
650         save_desc_40 = gdt[0x40 / 8];
651         gdt[0x40 / 8] = bad_bios_desc;
652
653         apm_irq_save(flags);
654         APM_DO_SAVE_SEGS;
655         error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax);
656         APM_DO_RESTORE_SEGS;
657         apm_irq_restore(flags);
658         gdt[0x40 / 8] = save_desc_40;
659         put_cpu();
660         apm_restore_cpus(cpus);
661         return error;
662 }
663
664 /**
665  *      apm_driver_version      -       APM driver version
666  *      @val:   loaded with the APM version on return
667  *
668  *      Retrieve the APM version supported by the BIOS. This is only
669  *      supported for APM 1.1 or higher. An error indicates APM 1.0 is
670  *      probably present.
671  *
672  *      On entry val should point to a value indicating the APM driver
673  *      version with the high byte being the major and the low byte the
674  *      minor number both in BCD
675  *
676  *      On return it will hold the BIOS revision supported in the
677  *      same format.
678  */
679
680 static int apm_driver_version(u_short *val)
681 {
682         u32     eax;
683
684         if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax))
685                 return (eax >> 8) & 0xff;
686         *val = eax;
687         return APM_SUCCESS;
688 }
689
690 /**
691  *      apm_get_event   -       get an APM event from the BIOS
692  *      @event: pointer to the event
693  *      @info: point to the event information
694  *
695  *      The APM BIOS provides a polled information for event
696  *      reporting. The BIOS expects to be polled at least every second
697  *      when events are pending. When a message is found the caller should
698  *      poll until no more messages are present.  However, this causes
699  *      problems on some laptops where a suspend event notification is
700  *      not cleared until it is acknowledged.
701  *
702  *      Additional information is returned in the info pointer, providing
703  *      that APM 1.2 is in use. If no messges are pending the value 0x80
704  *      is returned (No power management events pending).
705  */
706  
707 static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
708 {
709         u32     eax;
710         u32     ebx;
711         u32     ecx;
712         u32     dummy;
713
714         if (apm_bios_call(APM_FUNC_GET_EVENT, 0, 0, &eax, &ebx, &ecx,
715                         &dummy, &dummy))
716                 return (eax >> 8) & 0xff;
717         *event = ebx;
718         if (apm_info.connection_version < 0x0102)
719                 *info = ~0; /* indicate info not valid */
720         else
721                 *info = ecx;
722         return APM_SUCCESS;
723 }
724
725 /**
726  *      set_power_state -       set the power management state
727  *      @what: which items to transition
728  *      @state: state to transition to
729  *
730  *      Request an APM change of state for one or more system devices. The
731  *      processor state must be transitioned last of all. what holds the
732  *      class of device in the upper byte and the device number (0xFF for
733  *      all) for the object to be transitioned.
734  *
735  *      The state holds the state to transition to, which may in fact
736  *      be an acceptance of a BIOS requested state change.
737  */
738  
739 static int set_power_state(u_short what, u_short state)
740 {
741         u32     eax;
742
743         if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax))
744                 return (eax >> 8) & 0xff;
745         return APM_SUCCESS;
746 }
747
748 /**
749  *      set_system_power_state - set system wide power state
750  *      @state: which state to enter
751  *
752  *      Transition the entire system into a new APM power state.
753  */
754  
755 static int set_system_power_state(u_short state)
756 {
757         return set_power_state(APM_DEVICE_ALL, state);
758 }
759
760 /**
761  *      apm_do_idle     -       perform power saving
762  *
763  *      This function notifies the BIOS that the processor is (in the view
764  *      of the OS) idle. It returns -1 in the event that the BIOS refuses
765  *      to handle the idle request. On a success the function returns 1
766  *      if the BIOS did clock slowing or 0 otherwise.
767  */
768  
769 static int apm_do_idle(void)
770 {
771         u32     eax;
772         u8      ret = 0;
773         int     idled = 0;
774         int     polling;
775
776         polling = !!(current_thread_info()->status & TS_POLLING);
777         if (polling) {
778                 current_thread_info()->status &= ~TS_POLLING;
779                 /*
780                  * TS_POLLING-cleared state must be visible before we
781                  * test NEED_RESCHED:
782                  */
783                 smp_mb();
784         }
785         if (!need_resched()) {
786                 idled = 1;
787                 ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax);
788         }
789         if (polling)
790                 current_thread_info()->status |= TS_POLLING;
791
792         if (!idled)
793                 return 0;
794
795         if (ret) {
796                 static unsigned long t;
797
798                 /* This always fails on some SMP boards running UP kernels.
799                  * Only report the failure the first 5 times.
800                  */
801                 if (++t < 5)
802                 {
803                         printk(KERN_DEBUG "apm_do_idle failed (%d)\n",
804                                         (eax >> 8) & 0xff);
805                         t = jiffies;
806                 }
807                 return -1;
808         }
809         clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
810         return clock_slowed;
811 }
812
813 /**
814  *      apm_do_busy     -       inform the BIOS the CPU is busy
815  *
816  *      Request that the BIOS brings the CPU back to full performance. 
817  */
818  
819 static void apm_do_busy(void)
820 {
821         u32     dummy;
822
823         if (clock_slowed || ALWAYS_CALL_BUSY) {
824                 (void) apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy);
825                 clock_slowed = 0;
826         }
827 }
828
829 /*
830  * If no process has really been interested in
831  * the CPU for some time, we want to call BIOS
832  * power management - we probably want
833  * to conserve power.
834  */
835 #define IDLE_CALC_LIMIT   (HZ * 100)
836 #define IDLE_LEAKY_MAX    16
837
838 static void (*original_pm_idle)(void) __read_mostly;
839
840 /**
841  * apm_cpu_idle         -       cpu idling for APM capable Linux
842  *
843  * This is the idling function the kernel executes when APM is available. It 
844  * tries to do BIOS powermanagement based on the average system idle time.
845  * Furthermore it calls the system default idle routine.
846  */
847
848 static void apm_cpu_idle(void)
849 {
850         static int use_apm_idle; /* = 0 */
851         static unsigned int last_jiffies; /* = 0 */
852         static unsigned int last_stime; /* = 0 */
853
854         int apm_idle_done = 0;
855         unsigned int jiffies_since_last_check = jiffies - last_jiffies;
856         unsigned int bucket;
857
858 recalc:
859         if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
860                 use_apm_idle = 0;
861                 last_jiffies = jiffies;
862                 last_stime = current->stime;
863         } else if (jiffies_since_last_check > idle_period) {
864                 unsigned int idle_percentage;
865
866                 idle_percentage = current->stime - last_stime;
867                 idle_percentage *= 100;
868                 idle_percentage /= jiffies_since_last_check;
869                 use_apm_idle = (idle_percentage > idle_threshold);
870                 if (apm_info.forbid_idle)
871                         use_apm_idle = 0;
872                 last_jiffies = jiffies;
873                 last_stime = current->stime;
874         }
875
876         bucket = IDLE_LEAKY_MAX;
877
878         while (!need_resched()) {
879                 if (use_apm_idle) {
880                         unsigned int t;
881
882                         t = jiffies;
883                         switch (apm_do_idle()) {
884                         case 0: apm_idle_done = 1;
885                                 if (t != jiffies) {
886                                         if (bucket) {
887                                                 bucket = IDLE_LEAKY_MAX;
888                                                 continue;
889                                         }
890                                 } else if (bucket) {
891                                         bucket--;
892                                         continue;
893                                 }
894                                 break;
895                         case 1: apm_idle_done = 1;
896                                 break;
897                         default: /* BIOS refused */
898                                 break;
899                         }
900                 }
901                 if (original_pm_idle)
902                         original_pm_idle();
903                 else
904                         default_idle();
905                 jiffies_since_last_check = jiffies - last_jiffies;
906                 if (jiffies_since_last_check > idle_period)
907                         goto recalc;
908         }
909
910         if (apm_idle_done)
911                 apm_do_busy();
912 }
913
914 /**
915  *      apm_power_off   -       ask the BIOS to power off
916  *
917  *      Handle the power off sequence. This is the one piece of code we
918  *      will execute even on SMP machines. In order to deal with BIOS
919  *      bugs we support real mode APM BIOS power off calls. We also make
920  *      the SMP call on CPU0 as some systems will only honour this call
921  *      on their first cpu.
922  */
923  
924 static void apm_power_off(void)
925 {
926         unsigned char   po_bios_call[] = {
927                 0xb8, 0x00, 0x10,       /* movw  $0x1000,ax  */
928                 0x8e, 0xd0,             /* movw  ax,ss       */
929                 0xbc, 0x00, 0xf0,       /* movw  $0xf000,sp  */
930                 0xb8, 0x07, 0x53,       /* movw  $0x5307,ax  */
931                 0xbb, 0x01, 0x00,       /* movw  $0x0001,bx  */
932                 0xb9, 0x03, 0x00,       /* movw  $0x0003,cx  */
933                 0xcd, 0x15              /* int   $0x15       */
934         };
935
936         /* Some bioses don't like being called from CPU != 0 */
937         if (apm_info.realmode_power_off)
938         {
939                 (void)apm_save_cpus();
940                 machine_real_restart(po_bios_call, sizeof(po_bios_call));
941         }
942         else
943                 (void) set_system_power_state(APM_STATE_OFF);
944 }
945
946 #ifdef CONFIG_APM_DO_ENABLE
947
948 /**
949  *      apm_enable_power_management - enable BIOS APM power management
950  *      @enable: enable yes/no
951  *
952  *      Enable or disable the APM BIOS power services. 
953  */
954  
955 static int apm_enable_power_management(int enable)
956 {
957         u32     eax;
958
959         if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
960                 return APM_NOT_ENGAGED;
961         if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
962                         enable, &eax))
963                 return (eax >> 8) & 0xff;
964         if (enable)
965                 apm_info.bios.flags &= ~APM_BIOS_DISABLED;
966         else
967                 apm_info.bios.flags |= APM_BIOS_DISABLED;
968         return APM_SUCCESS;
969 }
970 #endif
971
972 /**
973  *      apm_get_power_status    -       get current power state
974  *      @status: returned status
975  *      @bat: battery info
976  *      @life: estimated life
977  *
978  *      Obtain the current power status from the APM BIOS. We return a
979  *      status which gives the rough battery status, and current power
980  *      source. The bat value returned give an estimate as a percentage
981  *      of life and a status value for the battery. The estimated life
982  *      if reported is a lifetime in secodnds/minutes at current powwer
983  *      consumption.
984  */
985  
986 static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
987 {
988         u32     eax;
989         u32     ebx;
990         u32     ecx;
991         u32     edx;
992         u32     dummy;
993
994         if (apm_info.get_power_status_broken)
995                 return APM_32_UNSUPPORTED;
996         if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0,
997                         &eax, &ebx, &ecx, &edx, &dummy))
998                 return (eax >> 8) & 0xff;
999         *status = ebx;
1000         *bat = ecx;
1001         if (apm_info.get_power_status_swabinminutes) {
1002                 *life = swab16((u16)edx);
1003                 *life |= 0x8000;
1004         } else
1005                 *life = edx;
1006         return APM_SUCCESS;
1007 }
1008
1009 #if 0
1010 static int apm_get_battery_status(u_short which, u_short *status,
1011                                   u_short *bat, u_short *life, u_short *nbat)
1012 {
1013         u32     eax;
1014         u32     ebx;
1015         u32     ecx;
1016         u32     edx;
1017         u32     esi;
1018
1019         if (apm_info.connection_version < 0x0102) {
1020                 /* pretend we only have one battery. */
1021                 if (which != 1)
1022                         return APM_BAD_DEVICE;
1023                 *nbat = 1;
1024                 return apm_get_power_status(status, bat, life);
1025         }
1026
1027         if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
1028                         &ebx, &ecx, &edx, &esi))
1029                 return (eax >> 8) & 0xff;
1030         *status = ebx;
1031         *bat = ecx;
1032         *life = edx;
1033         *nbat = esi;
1034         return APM_SUCCESS;
1035 }
1036 #endif
1037
1038 /**
1039  *      apm_engage_power_management     -       enable PM on a device
1040  *      @device: identity of device
1041  *      @enable: on/off
1042  *
1043  *      Activate or deactive power management on either a specific device
1044  *      or the entire system (%APM_DEVICE_ALL).
1045  */
1046  
1047 static int apm_engage_power_management(u_short device, int enable)
1048 {
1049         u32     eax;
1050
1051         if ((enable == 0) && (device == APM_DEVICE_ALL)
1052             && (apm_info.bios.flags & APM_BIOS_DISABLED))
1053                 return APM_DISABLED;
1054         if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
1055                 return (eax >> 8) & 0xff;
1056         if (device == APM_DEVICE_ALL) {
1057                 if (enable)
1058                         apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
1059                 else
1060                         apm_info.bios.flags |= APM_BIOS_DISENGAGED;
1061         }
1062         return APM_SUCCESS;
1063 }
1064
1065 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1066
1067 /**
1068  *      apm_console_blank       -       blank the display
1069  *      @blank: on/off
1070  *
1071  *      Attempt to blank the console, firstly by blanking just video device
1072  *      zero, and if that fails (some BIOSes don't support it) then it blanks
1073  *      all video devices. Typically the BIOS will do laptop backlight and
1074  *      monitor powerdown for us.
1075  */
1076  
1077 static int apm_console_blank(int blank)
1078 {
1079         int error = APM_NOT_ENGAGED; /* silence gcc */
1080         int i;
1081         u_short state;
1082         static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
1083
1084         state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
1085
1086         for (i = 0; i < ARRAY_SIZE(dev); i++) {
1087                 error = set_power_state(dev[i], state);
1088
1089                 if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
1090                         return 1;
1091
1092                 if (error == APM_NOT_ENGAGED)
1093                         break;
1094         }
1095
1096         if (error == APM_NOT_ENGAGED) {
1097                 static int tried;
1098                 int eng_error;
1099                 if (tried++ == 0) {
1100                         eng_error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1101                         if (eng_error) {
1102                                 apm_error("set display", error);
1103                                 apm_error("engage interface", eng_error);
1104                                 return 0;
1105                         } else
1106                                 return apm_console_blank(blank);
1107                 }
1108         }
1109         apm_error("set display", error);
1110         return 0;
1111 }
1112 #endif
1113
1114 static int queue_empty(struct apm_user *as)
1115 {
1116         return as->event_head == as->event_tail;
1117 }
1118
1119 static apm_event_t get_queued_event(struct apm_user *as)
1120 {
1121         if (++as->event_tail >= APM_MAX_EVENTS)
1122                 as->event_tail = 0;
1123         return as->events[as->event_tail];
1124 }
1125
1126 static void queue_event(apm_event_t event, struct apm_user *sender)
1127 {
1128         struct apm_user *       as;
1129
1130         spin_lock(&user_list_lock);
1131         if (user_list == NULL)
1132                 goto out;
1133         for (as = user_list; as != NULL; as = as->next) {
1134                 if ((as == sender) || (!as->reader))
1135                         continue;
1136                 if (++as->event_head >= APM_MAX_EVENTS)
1137                         as->event_head = 0;
1138
1139                 if (as->event_head == as->event_tail) {
1140                         static int notified;
1141
1142                         if (notified++ == 0)
1143                             printk(KERN_ERR "apm: an event queue overflowed\n");
1144                         if (++as->event_tail >= APM_MAX_EVENTS)
1145                                 as->event_tail = 0;
1146                 }
1147                 as->events[as->event_head] = event;
1148                 if ((!as->suser) || (!as->writer))
1149                         continue;
1150                 switch (event) {
1151                 case APM_SYS_SUSPEND:
1152                 case APM_USER_SUSPEND:
1153                         as->suspends_pending++;
1154                         suspends_pending++;
1155                         break;
1156
1157                 case APM_SYS_STANDBY:
1158                 case APM_USER_STANDBY:
1159                         as->standbys_pending++;
1160                         standbys_pending++;
1161                         break;
1162                 }
1163         }
1164         wake_up_interruptible(&apm_waitqueue);
1165 out:
1166         spin_unlock(&user_list_lock);
1167 }
1168
1169 static void reinit_timer(void)
1170 {
1171 #ifdef INIT_TIMER_AFTER_SUSPEND
1172         unsigned long flags;
1173
1174         spin_lock_irqsave(&i8253_lock, flags);
1175         /* set the clock to HZ */
1176         outb_p(0x34, PIT_MODE);         /* binary, mode 2, LSB/MSB, ch 0 */
1177         udelay(10);
1178         outb_p(LATCH & 0xff, PIT_CH0);  /* LSB */
1179         udelay(10);
1180         outb(LATCH >> 8, PIT_CH0);      /* MSB */
1181         udelay(10);
1182         spin_unlock_irqrestore(&i8253_lock, flags);
1183 #endif
1184 }
1185
1186 static int suspend(int vetoable)
1187 {
1188         int             err;
1189         struct apm_user *as;
1190
1191         if (pm_send_all(PM_SUSPEND, (void *)3)) {
1192                 /* Vetoed */
1193                 if (vetoable) {
1194                         if (apm_info.connection_version > 0x100)
1195                                 set_system_power_state(APM_STATE_REJECT);
1196                         err = -EBUSY;
1197                         ignore_sys_suspend = 0;
1198                         printk(KERN_WARNING "apm: suspend was vetoed.\n");
1199                         goto out;
1200                 }
1201                 printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
1202         }
1203
1204         device_suspend(PMSG_SUSPEND);
1205         local_irq_disable();
1206         device_power_down(PMSG_SUSPEND);
1207
1208         local_irq_enable();
1209
1210         save_processor_state();
1211         err = set_system_power_state(APM_STATE_SUSPEND);
1212         ignore_normal_resume = 1;
1213         restore_processor_state();
1214
1215         local_irq_disable();
1216         reinit_timer();
1217
1218         if (err == APM_NO_ERROR)
1219                 err = APM_SUCCESS;
1220         if (err != APM_SUCCESS)
1221                 apm_error("suspend", err);
1222         err = (err == APM_SUCCESS) ? 0 : -EIO;
1223         device_power_up();
1224         local_irq_enable();
1225         device_resume();
1226         pm_send_all(PM_RESUME, (void *)0);
1227         queue_event(APM_NORMAL_RESUME, NULL);
1228  out:
1229         spin_lock(&user_list_lock);
1230         for (as = user_list; as != NULL; as = as->next) {
1231                 as->suspend_wait = 0;
1232                 as->suspend_result = err;
1233         }
1234         spin_unlock(&user_list_lock);
1235         wake_up_interruptible(&apm_suspend_waitqueue);
1236         return err;
1237 }
1238
1239 static void standby(void)
1240 {
1241         int     err;
1242
1243         local_irq_disable();
1244         device_power_down(PMSG_SUSPEND);
1245         local_irq_enable();
1246
1247         err = set_system_power_state(APM_STATE_STANDBY);
1248         if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
1249                 apm_error("standby", err);
1250
1251         local_irq_disable();
1252         device_power_up();
1253         local_irq_enable();
1254 }
1255
1256 static apm_event_t get_event(void)
1257 {
1258         int             error;
1259         apm_event_t     event = APM_NO_EVENTS; /* silence gcc */
1260         apm_eventinfo_t info;
1261
1262         static int notified;
1263
1264         /* we don't use the eventinfo */
1265         error = apm_get_event(&event, &info);
1266         if (error == APM_SUCCESS)
1267                 return event;
1268
1269         if ((error != APM_NO_EVENTS) && (notified++ == 0))
1270                 apm_error("get_event", error);
1271
1272         return 0;
1273 }
1274
1275 static void check_events(void)
1276 {
1277         apm_event_t             event;
1278         static unsigned long    last_resume;
1279         static int              ignore_bounce;
1280
1281         while ((event = get_event()) != 0) {
1282                 if (debug) {
1283                         if (event <= NR_APM_EVENT_NAME)
1284                                 printk(KERN_DEBUG "apm: received %s notify\n",
1285                                        apm_event_name[event - 1]);
1286                         else
1287                                 printk(KERN_DEBUG "apm: received unknown "
1288                                        "event 0x%02x\n", event);
1289                 }
1290                 if (ignore_bounce
1291                     && ((jiffies - last_resume) > bounce_interval))
1292                         ignore_bounce = 0;
1293
1294                 switch (event) {
1295                 case APM_SYS_STANDBY:
1296                 case APM_USER_STANDBY:
1297                         queue_event(event, NULL);
1298                         if (standbys_pending <= 0)
1299                                 standby();
1300                         break;
1301
1302                 case APM_USER_SUSPEND:
1303 #ifdef CONFIG_APM_IGNORE_USER_SUSPEND
1304                         if (apm_info.connection_version > 0x100)
1305                                 set_system_power_state(APM_STATE_REJECT);
1306                         break;
1307 #endif
1308                 case APM_SYS_SUSPEND:
1309                         if (ignore_bounce) {
1310                                 if (apm_info.connection_version > 0x100)
1311                                         set_system_power_state(APM_STATE_REJECT);
1312                                 break;
1313                         }
1314                         /*
1315                          * If we are already processing a SUSPEND,
1316                          * then further SUSPEND events from the BIOS
1317                          * will be ignored.  We also return here to
1318                          * cope with the fact that the Thinkpads keep
1319                          * sending a SUSPEND event until something else
1320                          * happens!
1321                          */
1322                         if (ignore_sys_suspend)
1323                                 return;
1324                         ignore_sys_suspend = 1;
1325                         queue_event(event, NULL);
1326                         if (suspends_pending <= 0)
1327                                 (void) suspend(1);
1328                         break;
1329
1330                 case APM_NORMAL_RESUME:
1331                 case APM_CRITICAL_RESUME:
1332                 case APM_STANDBY_RESUME:
1333                         ignore_sys_suspend = 0;
1334                         last_resume = jiffies;
1335                         ignore_bounce = 1;
1336                         if ((event != APM_NORMAL_RESUME)
1337                             || (ignore_normal_resume == 0)) {
1338                                 device_resume();
1339                                 pm_send_all(PM_RESUME, (void *)0);
1340                                 queue_event(event, NULL);
1341                         }
1342                         ignore_normal_resume = 0;
1343                         break;
1344
1345                 case APM_CAPABILITY_CHANGE:
1346                 case APM_LOW_BATTERY:
1347                 case APM_POWER_STATUS_CHANGE:
1348                         queue_event(event, NULL);
1349                         /* If needed, notify drivers here */
1350                         break;
1351
1352                 case APM_UPDATE_TIME:
1353                         break;
1354
1355                 case APM_CRITICAL_SUSPEND:
1356                         /*
1357                          * We are not allowed to reject a critical suspend.
1358                          */
1359                         (void) suspend(0);
1360                         break;
1361                 }
1362         }
1363 }
1364
1365 static void apm_event_handler(void)
1366 {
1367         static int      pending_count = 4;
1368         int             err;
1369
1370         if ((standbys_pending > 0) || (suspends_pending > 0)) {
1371                 if ((apm_info.connection_version > 0x100) &&
1372                                 (pending_count-- <= 0)) {
1373                         pending_count = 4;
1374                         if (debug)
1375                                 printk(KERN_DEBUG "apm: setting state busy\n");
1376                         err = set_system_power_state(APM_STATE_BUSY);
1377                         if (err)
1378                                 apm_error("busy", err);
1379                 }
1380         } else
1381                 pending_count = 4;
1382         check_events();
1383 }
1384
1385 /*
1386  * This is the APM thread main loop.
1387  */
1388
1389 static void apm_mainloop(void)
1390 {
1391         DECLARE_WAITQUEUE(wait, current);
1392
1393         add_wait_queue(&apm_waitqueue, &wait);
1394         set_current_state(TASK_INTERRUPTIBLE);
1395         for (;;) {
1396                 schedule_timeout(APM_CHECK_TIMEOUT);
1397                 if (kthread_should_stop())
1398                         break;
1399                 /*
1400                  * Ok, check all events, check for idle (and mark us sleeping
1401                  * so as not to count towards the load average)..
1402                  */
1403                 set_current_state(TASK_INTERRUPTIBLE);
1404                 apm_event_handler();
1405         }
1406         remove_wait_queue(&apm_waitqueue, &wait);
1407 }
1408
1409 static int check_apm_user(struct apm_user *as, const char *func)
1410 {
1411         if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
1412                 printk(KERN_ERR "apm: %s passed bad filp\n", func);
1413                 return 1;
1414         }
1415         return 0;
1416 }
1417
1418 static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
1419 {
1420         struct apm_user *       as;
1421         int                     i;
1422         apm_event_t             event;
1423
1424         as = fp->private_data;
1425         if (check_apm_user(as, "read"))
1426                 return -EIO;
1427         if ((int)count < sizeof(apm_event_t))
1428                 return -EINVAL;
1429         if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK))
1430                 return -EAGAIN;
1431         wait_event_interruptible(apm_waitqueue, !queue_empty(as));
1432         i = count;
1433         while ((i >= sizeof(event)) && !queue_empty(as)) {
1434                 event = get_queued_event(as);
1435                 if (copy_to_user(buf, &event, sizeof(event))) {
1436                         if (i < count)
1437                                 break;
1438                         return -EFAULT;
1439                 }
1440                 switch (event) {
1441                 case APM_SYS_SUSPEND:
1442                 case APM_USER_SUSPEND:
1443                         as->suspends_read++;
1444                         break;
1445
1446                 case APM_SYS_STANDBY:
1447                 case APM_USER_STANDBY:
1448                         as->standbys_read++;
1449                         break;
1450                 }
1451                 buf += sizeof(event);
1452                 i -= sizeof(event);
1453         }
1454         if (i < count)
1455                 return count - i;
1456         if (signal_pending(current))
1457                 return -ERESTARTSYS;
1458         return 0;
1459 }
1460
1461 static unsigned int do_poll(struct file *fp, poll_table * wait)
1462 {
1463         struct apm_user * as;
1464
1465         as = fp->private_data;
1466         if (check_apm_user(as, "poll"))
1467                 return 0;
1468         poll_wait(fp, &apm_waitqueue, wait);
1469         if (!queue_empty(as))
1470                 return POLLIN | POLLRDNORM;
1471         return 0;
1472 }
1473
1474 static int do_ioctl(struct inode * inode, struct file *filp,
1475                     u_int cmd, u_long arg)
1476 {
1477         struct apm_user *       as;
1478
1479         as = filp->private_data;
1480         if (check_apm_user(as, "ioctl"))
1481                 return -EIO;
1482         if ((!as->suser) || (!as->writer))
1483                 return -EPERM;
1484         switch (cmd) {
1485         case APM_IOC_STANDBY:
1486                 if (as->standbys_read > 0) {
1487                         as->standbys_read--;
1488                         as->standbys_pending--;
1489                         standbys_pending--;
1490                 } else
1491                         queue_event(APM_USER_STANDBY, as);
1492                 if (standbys_pending <= 0)
1493                         standby();
1494                 break;
1495         case APM_IOC_SUSPEND:
1496                 if (as->suspends_read > 0) {
1497                         as->suspends_read--;
1498                         as->suspends_pending--;
1499                         suspends_pending--;
1500                 } else
1501                         queue_event(APM_USER_SUSPEND, as);
1502                 if (suspends_pending <= 0) {
1503                         return suspend(1);
1504                 } else {
1505                         as->suspend_wait = 1;
1506                         wait_event_interruptible(apm_suspend_waitqueue,
1507                                         as->suspend_wait == 0);
1508                         return as->suspend_result;
1509                 }
1510                 break;
1511         default:
1512                 return -EINVAL;
1513         }
1514         return 0;
1515 }
1516
1517 static int do_release(struct inode * inode, struct file * filp)
1518 {
1519         struct apm_user *       as;
1520
1521         as = filp->private_data;
1522         if (check_apm_user(as, "release"))
1523                 return 0;
1524         filp->private_data = NULL;
1525         if (as->standbys_pending > 0) {
1526                 standbys_pending -= as->standbys_pending;
1527                 if (standbys_pending <= 0)
1528                         standby();
1529         }
1530         if (as->suspends_pending > 0) {
1531                 suspends_pending -= as->suspends_pending;
1532                 if (suspends_pending <= 0)
1533                         (void) suspend(1);
1534         }
1535         spin_lock(&user_list_lock);
1536         if (user_list == as)
1537                 user_list = as->next;
1538         else {
1539                 struct apm_user *       as1;
1540
1541                 for (as1 = user_list;
1542                      (as1 != NULL) && (as1->next != as);
1543                      as1 = as1->next)
1544                         ;
1545                 if (as1 == NULL)
1546                         printk(KERN_ERR "apm: filp not in user list\n");
1547                 else
1548                         as1->next = as->next;
1549         }
1550         spin_unlock(&user_list_lock);
1551         kfree(as);
1552         return 0;
1553 }
1554
1555 static int do_open(struct inode * inode, struct file * filp)
1556 {
1557         struct apm_user *       as;
1558
1559         as = kmalloc(sizeof(*as), GFP_KERNEL);
1560         if (as == NULL) {
1561                 printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
1562                        sizeof(*as));
1563                 return -ENOMEM;
1564         }
1565         as->magic = APM_BIOS_MAGIC;
1566         as->event_tail = as->event_head = 0;
1567         as->suspends_pending = as->standbys_pending = 0;
1568         as->suspends_read = as->standbys_read = 0;
1569         /*
1570          * XXX - this is a tiny bit broken, when we consider BSD
1571          * process accounting. If the device is opened by root, we
1572          * instantly flag that we used superuser privs. Who knows,
1573          * we might close the device immediately without doing a
1574          * privileged operation -- cevans
1575          */
1576         as->suser = capable(CAP_SYS_ADMIN);
1577         as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
1578         as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
1579         spin_lock(&user_list_lock);
1580         as->next = user_list;
1581         user_list = as;
1582         spin_unlock(&user_list_lock);
1583         filp->private_data = as;
1584         return 0;
1585 }
1586
1587 static int proc_apm_show(struct seq_file *m, void *v)
1588 {
1589         unsigned short  bx;
1590         unsigned short  cx;
1591         unsigned short  dx;
1592         int             error;
1593         unsigned short  ac_line_status = 0xff;
1594         unsigned short  battery_status = 0xff;
1595         unsigned short  battery_flag   = 0xff;
1596         int             percentage     = -1;
1597         int             time_units     = -1;
1598         char            *units         = "?";
1599
1600         if ((num_online_cpus() == 1) &&
1601             !(error = apm_get_power_status(&bx, &cx, &dx))) {
1602                 ac_line_status = (bx >> 8) & 0xff;
1603                 battery_status = bx & 0xff;
1604                 if ((cx & 0xff) != 0xff)
1605                         percentage = cx & 0xff;
1606
1607                 if (apm_info.connection_version > 0x100) {
1608                         battery_flag = (cx >> 8) & 0xff;
1609                         if (dx != 0xffff) {
1610                                 units = (dx & 0x8000) ? "min" : "sec";
1611                                 time_units = dx & 0x7fff;
1612                         }
1613                 }
1614         }
1615         /* Arguments, with symbols from linux/apm_bios.h.  Information is
1616            from the Get Power Status (0x0a) call unless otherwise noted.
1617
1618            0) Linux driver version (this will change if format changes)
1619            1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
1620            2) APM flags from APM Installation Check (0x00):
1621               bit 0: APM_16_BIT_SUPPORT
1622               bit 1: APM_32_BIT_SUPPORT
1623               bit 2: APM_IDLE_SLOWS_CLOCK
1624               bit 3: APM_BIOS_DISABLED
1625               bit 4: APM_BIOS_DISENGAGED
1626            3) AC line status
1627               0x00: Off-line
1628               0x01: On-line
1629               0x02: On backup power (BIOS >= 1.1 only)
1630               0xff: Unknown
1631            4) Battery status
1632               0x00: High
1633               0x01: Low
1634               0x02: Critical
1635               0x03: Charging
1636               0x04: Selected battery not present (BIOS >= 1.2 only)
1637               0xff: Unknown
1638            5) Battery flag
1639               bit 0: High
1640               bit 1: Low
1641               bit 2: Critical
1642               bit 3: Charging
1643               bit 7: No system battery
1644               0xff: Unknown
1645            6) Remaining battery life (percentage of charge):
1646               0-100: valid
1647               -1: Unknown
1648            7) Remaining battery life (time units):
1649               Number of remaining minutes or seconds
1650               -1: Unknown
1651            8) min = minutes; sec = seconds */
1652
1653         seq_printf(m, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
1654                      driver_version,
1655                      (apm_info.bios.version >> 8) & 0xff,
1656                      apm_info.bios.version & 0xff,
1657                      apm_info.bios.flags,
1658                      ac_line_status,
1659                      battery_status,
1660                      battery_flag,
1661                      percentage,
1662                      time_units,
1663                      units);
1664         return 0;
1665 }
1666
1667 static int proc_apm_open(struct inode *inode, struct file *file)
1668 {
1669         return single_open(file, proc_apm_show, NULL);
1670 }
1671
1672 static const struct file_operations apm_file_ops = {
1673         .owner          = THIS_MODULE,
1674         .open           = proc_apm_open,
1675         .read           = seq_read,
1676         .llseek         = seq_lseek,
1677         .release        = single_release,
1678 };
1679
1680 static int apm(void *unused)
1681 {
1682         unsigned short  bx;
1683         unsigned short  cx;
1684         unsigned short  dx;
1685         int             error;
1686         char *          power_stat;
1687         char *          bat_stat;
1688
1689 #ifdef CONFIG_SMP
1690         /* 2002/08/01 - WT
1691          * This is to avoid random crashes at boot time during initialization
1692          * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D.
1693          * Some bioses don't like being called from CPU != 0.
1694          * Method suggested by Ingo Molnar.
1695          */
1696         set_cpus_allowed(current, cpumask_of_cpu(0));
1697         BUG_ON(smp_processor_id() != 0);
1698 #endif
1699
1700         if (apm_info.connection_version == 0) {
1701                 apm_info.connection_version = apm_info.bios.version;
1702                 if (apm_info.connection_version > 0x100) {
1703                         /*
1704                          * We only support BIOSs up to version 1.2
1705                          */
1706                         if (apm_info.connection_version > 0x0102)
1707                                 apm_info.connection_version = 0x0102;
1708                         error = apm_driver_version(&apm_info.connection_version);
1709                         if (error != APM_SUCCESS) {
1710                                 apm_error("driver version", error);
1711                                 /* Fall back to an APM 1.0 connection. */
1712                                 apm_info.connection_version = 0x100;
1713                         }
1714                 }
1715         }
1716
1717         if (debug)
1718                 printk(KERN_INFO "apm: Connection version %d.%d\n",
1719                         (apm_info.connection_version >> 8) & 0xff,
1720                         apm_info.connection_version & 0xff);
1721
1722 #ifdef CONFIG_APM_DO_ENABLE
1723         if (apm_info.bios.flags & APM_BIOS_DISABLED) {
1724                 /*
1725                  * This call causes my NEC UltraLite Versa 33/C to hang if it
1726                  * is booted with PM disabled but not in the docking station.
1727                  * Unfortunate ...
1728                  */
1729                 error = apm_enable_power_management(1);
1730                 if (error) {
1731                         apm_error("enable power management", error);
1732                         return -1;
1733                 }
1734         }
1735 #endif
1736
1737         if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
1738             && (apm_info.connection_version > 0x0100)) {
1739                 error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1740                 if (error) {
1741                         apm_error("engage power management", error);
1742                         return -1;
1743                 }
1744         }
1745
1746         if (debug && (num_online_cpus() == 1 || smp )) {
1747                 error = apm_get_power_status(&bx, &cx, &dx);
1748                 if (error)
1749                         printk(KERN_INFO "apm: power status not available\n");
1750                 else {
1751                         switch ((bx >> 8) & 0xff) {
1752                         case 0: power_stat = "off line"; break;
1753                         case 1: power_stat = "on line"; break;
1754                         case 2: power_stat = "on backup power"; break;
1755                         default: power_stat = "unknown"; break;
1756                         }
1757                         switch (bx & 0xff) {
1758                         case 0: bat_stat = "high"; break;
1759                         case 1: bat_stat = "low"; break;
1760                         case 2: bat_stat = "critical"; break;
1761                         case 3: bat_stat = "charging"; break;
1762                         default: bat_stat = "unknown"; break;
1763                         }
1764                         printk(KERN_INFO
1765                                "apm: AC %s, battery status %s, battery life ",
1766                                power_stat, bat_stat);
1767                         if ((cx & 0xff) == 0xff)
1768                                 printk("unknown\n");
1769                         else
1770                                 printk("%d%%\n", cx & 0xff);
1771                         if (apm_info.connection_version > 0x100) {
1772                                 printk(KERN_INFO
1773                                        "apm: battery flag 0x%02x, battery life ",
1774                                        (cx >> 8) & 0xff);
1775                                 if (dx == 0xffff)
1776                                         printk("unknown\n");
1777                                 else
1778                                         printk("%d %s\n", dx & 0x7fff,
1779                                                 (dx & 0x8000) ?
1780                                                 "minutes" : "seconds");
1781                         }
1782                 }
1783         }
1784
1785         /* Install our power off handler.. */
1786         if (power_off)
1787                 pm_power_off = apm_power_off;
1788
1789         if (num_online_cpus() == 1 || smp) {
1790 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1791                 console_blank_hook = apm_console_blank;
1792 #endif
1793                 apm_mainloop();
1794 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1795                 console_blank_hook = NULL;
1796 #endif
1797         }
1798
1799         return 0;
1800 }
1801
1802 #ifndef MODULE
1803 static int __init apm_setup(char *str)
1804 {
1805         int     invert;
1806
1807         while ((str != NULL) && (*str != '\0')) {
1808                 if (strncmp(str, "off", 3) == 0)
1809                         apm_disabled = 1;
1810                 if (strncmp(str, "on", 2) == 0)
1811                         apm_disabled = 0;
1812                 if ((strncmp(str, "bounce-interval=", 16) == 0) ||
1813                     (strncmp(str, "bounce_interval=", 16) == 0))
1814                         bounce_interval = simple_strtol(str + 16, NULL, 0);
1815                 if ((strncmp(str, "idle-threshold=", 15) == 0) ||
1816                     (strncmp(str, "idle_threshold=", 15) == 0))
1817                         idle_threshold = simple_strtol(str + 15, NULL, 0);
1818                 if ((strncmp(str, "idle-period=", 12) == 0) ||
1819                     (strncmp(str, "idle_period=", 12) == 0))
1820                         idle_period = simple_strtol(str + 12, NULL, 0);
1821                 invert = (strncmp(str, "no-", 3) == 0) ||
1822                         (strncmp(str, "no_", 3) == 0);
1823                 if (invert)
1824                         str += 3;
1825                 if (strncmp(str, "debug", 5) == 0)
1826                         debug = !invert;
1827                 if ((strncmp(str, "power-off", 9) == 0) ||
1828                     (strncmp(str, "power_off", 9) == 0))
1829                         power_off = !invert;
1830                 if (strncmp(str, "smp", 3) == 0)
1831                 {
1832                         smp = !invert;
1833                         idle_threshold = 100;
1834                 }
1835                 if ((strncmp(str, "allow-ints", 10) == 0) ||
1836                     (strncmp(str, "allow_ints", 10) == 0))
1837                         apm_info.allow_ints = !invert;
1838                 if ((strncmp(str, "broken-psr", 10) == 0) ||
1839                     (strncmp(str, "broken_psr", 10) == 0))
1840                         apm_info.get_power_status_broken = !invert;
1841                 if ((strncmp(str, "realmode-power-off", 18) == 0) ||
1842                     (strncmp(str, "realmode_power_off", 18) == 0))
1843                         apm_info.realmode_power_off = !invert;
1844                 str = strchr(str, ',');
1845                 if (str != NULL)
1846                         str += strspn(str, ", \t");
1847         }
1848         return 1;
1849 }
1850
1851 __setup("apm=", apm_setup);
1852 #endif
1853
1854 static const struct file_operations apm_bios_fops = {
1855         .owner          = THIS_MODULE,
1856         .read           = do_read,
1857         .poll           = do_poll,
1858         .ioctl          = do_ioctl,
1859         .open           = do_open,
1860         .release        = do_release,
1861 };
1862
1863 static struct miscdevice apm_device = {
1864         APM_MINOR_DEV,
1865         "apm_bios",
1866         &apm_bios_fops
1867 };
1868
1869
1870 /* Simple "print if true" callback */
1871 static int __init print_if_true(struct dmi_system_id *d)
1872 {
1873         printk("%s\n", d->ident);
1874         return 0;
1875 }
1876
1877 /*
1878  * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
1879  * disabled before the suspend. Linux used to get terribly confused by that.
1880  */
1881 static int __init broken_ps2_resume(struct dmi_system_id *d)
1882 {
1883         printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround hopefully not needed.\n", d->ident);
1884         return 0;
1885 }
1886
1887 /* Some bioses have a broken protected mode poweroff and need to use realmode */
1888 static int __init set_realmode_power_off(struct dmi_system_id *d)
1889 {
1890         if (apm_info.realmode_power_off == 0) {
1891                 apm_info.realmode_power_off = 1;
1892                 printk(KERN_INFO "%s bios detected. Using realmode poweroff only.\n", d->ident);
1893         }
1894         return 0;
1895 }
1896
1897 /* Some laptops require interrupts to be enabled during APM calls */
1898 static int __init set_apm_ints(struct dmi_system_id *d)
1899 {
1900         if (apm_info.allow_ints == 0) {
1901                 apm_info.allow_ints = 1;
1902                 printk(KERN_INFO "%s machine detected. Enabling interrupts during APM calls.\n", d->ident);
1903         }
1904         return 0;
1905 }
1906
1907 /* Some APM bioses corrupt memory or just plain do not work */
1908 static int __init apm_is_horked(struct dmi_system_id *d)
1909 {
1910         if (apm_info.disabled == 0) {
1911                 apm_info.disabled = 1;
1912                 printk(KERN_INFO "%s machine detected. Disabling APM.\n", d->ident);
1913         }
1914         return 0;
1915 }
1916
1917 static int __init apm_is_horked_d850md(struct dmi_system_id *d)
1918 {
1919         if (apm_info.disabled == 0) {
1920                 apm_info.disabled = 1;
1921                 printk(KERN_INFO "%s machine detected. Disabling APM.\n", d->ident);
1922                 printk(KERN_INFO "This bug is fixed in bios P15 which is available for \n");
1923                 printk(KERN_INFO "download from support.intel.com \n");
1924         }
1925         return 0;
1926 }
1927
1928 /* Some APM bioses hang on APM idle calls */
1929 static int __init apm_likes_to_melt(struct dmi_system_id *d)
1930 {
1931         if (apm_info.forbid_idle == 0) {
1932                 apm_info.forbid_idle = 1;
1933                 printk(KERN_INFO "%s machine detected. Disabling APM idle calls.\n", d->ident);
1934         }
1935         return 0;
1936 }
1937
1938 /*
1939  *  Check for clue free BIOS implementations who use
1940  *  the following QA technique
1941  *
1942  *      [ Write BIOS Code ]<------
1943  *               |                ^
1944  *      < Does it Compile >----N--
1945  *               |Y               ^
1946  *      < Does it Boot Win98 >-N--
1947  *               |Y
1948  *           [Ship It]
1949  *
1950  *      Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
1951  *      Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
1952  */
1953 static int __init broken_apm_power(struct dmi_system_id *d)
1954 {
1955         apm_info.get_power_status_broken = 1;
1956         printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
1957         return 0;
1958 }
1959
1960 /*
1961  * This bios swaps the APM minute reporting bytes over (Many sony laptops
1962  * have this problem).
1963  */
1964 static int __init swab_apm_power_in_minutes(struct dmi_system_id *d)
1965 {
1966         apm_info.get_power_status_swabinminutes = 1;
1967         printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n");
1968         return 0;
1969 }
1970
1971 static struct dmi_system_id __initdata apm_dmi_table[] = {
1972         {
1973                 print_if_true,
1974                 KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.",
1975                 {       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
1976                         DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), },
1977         },
1978         {       /* Handle problems with APM on the C600 */
1979                 broken_ps2_resume, "Dell Latitude C600",
1980                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
1981                         DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), },
1982         },
1983         {       /* Allow interrupts during suspend on Dell Latitude laptops*/
1984                 set_apm_ints, "Dell Latitude",
1985                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
1986                         DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), }
1987         },
1988         {       /* APM crashes */
1989                 apm_is_horked, "Dell Inspiron 2500",
1990                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
1991                         DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
1992                         DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
1993                         DMI_MATCH(DMI_BIOS_VERSION,"A11"), },
1994         },
1995         {       /* Allow interrupts during suspend on Dell Inspiron laptops*/
1996                 set_apm_ints, "Dell Inspiron", {
1997                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
1998                         DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), },
1999         },
2000         {       /* Handle problems with APM on Inspiron 5000e */
2001                 broken_apm_power, "Dell Inspiron 5000e",
2002                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2003                         DMI_MATCH(DMI_BIOS_VERSION, "A04"),
2004                         DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), },
2005         },
2006         {       /* Handle problems with APM on Inspiron 2500 */
2007                 broken_apm_power, "Dell Inspiron 2500",
2008                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2009                         DMI_MATCH(DMI_BIOS_VERSION, "A12"),
2010                         DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), },
2011         },
2012         {       /* APM crashes */
2013                 apm_is_horked, "Dell Dimension 4100",
2014                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2015                         DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
2016                         DMI_MATCH(DMI_BIOS_VENDOR,"Intel Corp."),
2017                         DMI_MATCH(DMI_BIOS_VERSION,"A11"), },
2018         },
2019         {       /* Allow interrupts during suspend on Compaq Laptops*/
2020                 set_apm_ints, "Compaq 12XL125",
2021                 {       DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
2022                         DMI_MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
2023                         DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2024                         DMI_MATCH(DMI_BIOS_VERSION,"4.06"), },
2025         },
2026         {       /* Allow interrupts during APM or the clock goes slow */
2027                 set_apm_ints, "ASUSTeK",
2028                 {       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
2029                         DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), },
2030         },
2031         {       /* APM blows on shutdown */
2032                 apm_is_horked, "ABIT KX7-333[R]",
2033                 {       DMI_MATCH(DMI_BOARD_VENDOR, "ABIT"),
2034                         DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), },
2035         },
2036         {       /* APM crashes */
2037                 apm_is_horked, "Trigem Delhi3",
2038                 {       DMI_MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
2039                         DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), },
2040         },
2041         {       /* APM crashes */
2042                 apm_is_horked, "Fujitsu-Siemens",
2043                 {       DMI_MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
2044                         DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), },
2045         },
2046         {       /* APM crashes */
2047                 apm_is_horked_d850md, "Intel D850MD",
2048                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2049                         DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), },
2050         },
2051         {       /* APM crashes */
2052                 apm_is_horked, "Intel D810EMO",
2053                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2054                         DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), },
2055         },
2056         {       /* APM crashes */
2057                 apm_is_horked, "Dell XPS-Z",
2058                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2059                         DMI_MATCH(DMI_BIOS_VERSION, "A11"),
2060                         DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), },
2061         },
2062         {       /* APM crashes */
2063                 apm_is_horked, "Sharp PC-PJ/AX",
2064                 {       DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
2065                         DMI_MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
2066                         DMI_MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
2067                         DMI_MATCH(DMI_BIOS_VERSION,"Version R2.08"), },
2068         },
2069         {       /* APM crashes */
2070                 apm_is_horked, "Dell Inspiron 2500",
2071                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2072                         DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2073                         DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
2074                         DMI_MATCH(DMI_BIOS_VERSION,"A11"), },
2075         },
2076         {       /* APM idle hangs */
2077                 apm_likes_to_melt, "Jabil AMD",
2078                 {       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2079                         DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), },
2080         },
2081         {       /* APM idle hangs */
2082                 apm_likes_to_melt, "AMI Bios",
2083                 {       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2084                         DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), },
2085         },
2086         {       /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
2087                 swab_apm_power_in_minutes, "Sony VAIO",
2088                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2089                         DMI_MATCH(DMI_BIOS_VERSION, "R0206H"),
2090                         DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), },
2091         },
2092         {       /* Handle problems with APM on Sony Vaio PCG-N505VX */
2093                 swab_apm_power_in_minutes, "Sony VAIO",
2094                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2095                         DMI_MATCH(DMI_BIOS_VERSION, "W2K06H0"),
2096                         DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), },
2097         },
2098         {       /* Handle problems with APM on Sony Vaio PCG-XG29 */
2099                 swab_apm_power_in_minutes, "Sony VAIO",
2100                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2101                         DMI_MATCH(DMI_BIOS_VERSION, "R0117A0"),
2102                         DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), },
2103         },
2104         {       /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2105                 swab_apm_power_in_minutes, "Sony VAIO",
2106                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2107                         DMI_MATCH(DMI_BIOS_VERSION, "R0121Z1"),
2108                         DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), },
2109         },
2110         {       /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2111                 swab_apm_power_in_minutes, "Sony VAIO",
2112                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2113                         DMI_MATCH(DMI_BIOS_VERSION, "WME01Z1"),
2114                         DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), },
2115         },
2116         {       /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
2117                 swab_apm_power_in_minutes, "Sony VAIO",
2118                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2119                         DMI_MATCH(DMI_BIOS_VERSION, "R0206Z3"),
2120                         DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), },
2121         },
2122         {       /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2123                 swab_apm_power_in_minutes, "Sony VAIO",
2124                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2125                         DMI_MATCH(DMI_BIOS_VERSION, "R0203D0"),
2126                         DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), },
2127         },
2128         {       /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2129                 swab_apm_power_in_minutes, "Sony VAIO",
2130                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2131                         DMI_MATCH(DMI_BIOS_VERSION, "R0203Z3"),
2132                         DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), },
2133         },
2134         {       /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
2135                 swab_apm_power_in_minutes, "Sony VAIO",
2136                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2137                         DMI_MATCH(DMI_BIOS_VERSION, "R0209Z3"),
2138                         DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), },
2139         },
2140         {       /* Handle problems with APM on Sony Vaio PCG-F104K */
2141                 swab_apm_power_in_minutes, "Sony VAIO",
2142                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2143                         DMI_MATCH(DMI_BIOS_VERSION, "R0204K2"),
2144                         DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), },
2145         },
2146
2147         {       /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
2148                 swab_apm_power_in_minutes, "Sony VAIO",
2149                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2150                         DMI_MATCH(DMI_BIOS_VERSION, "R0208P1"),
2151                         DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), },
2152         },
2153         {       /* Handle problems with APM on Sony Vaio PCG-C1VE */
2154                 swab_apm_power_in_minutes, "Sony VAIO",
2155                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2156                         DMI_MATCH(DMI_BIOS_VERSION, "R0204P1"),
2157                         DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), },
2158         },
2159         {       /* Handle problems with APM on Sony Vaio PCG-C1VE */
2160                 swab_apm_power_in_minutes, "Sony VAIO",
2161                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2162                         DMI_MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
2163                         DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), },
2164         },
2165         {       /* broken PM poweroff bios */
2166                 set_realmode_power_off, "Award Software v4.60 PGMA",
2167                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
2168                         DMI_MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
2169                         DMI_MATCH(DMI_BIOS_DATE, "134526184"), },
2170         },
2171
2172         /* Generic per vendor APM settings  */
2173
2174         {       /* Allow interrupts during suspend on IBM laptops */
2175                 set_apm_ints, "IBM",
2176                 {       DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
2177         },
2178
2179         { }
2180 };
2181
2182 /*
2183  * Just start the APM thread. We do NOT want to do APM BIOS
2184  * calls from anything but the APM thread, if for no other reason
2185  * than the fact that we don't trust the APM BIOS. This way,
2186  * most common APM BIOS problems that lead to protection errors
2187  * etc will have at least some level of being contained...
2188  *
2189  * In short, if something bad happens, at least we have a choice
2190  * of just killing the apm thread..
2191  */
2192 static int __init apm_init(void)
2193 {
2194         struct proc_dir_entry *apm_proc;
2195         struct desc_struct *gdt;
2196         int err;
2197
2198         dmi_check_system(apm_dmi_table);
2199
2200         if (apm_info.bios.version == 0 || paravirt_enabled()) {
2201                 printk(KERN_INFO "apm: BIOS not found.\n");
2202                 return -ENODEV;
2203         }
2204         printk(KERN_INFO
2205                 "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
2206                 ((apm_info.bios.version >> 8) & 0xff),
2207                 (apm_info.bios.version & 0xff),
2208                 apm_info.bios.flags,
2209                 driver_version);
2210         if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
2211                 printk(KERN_INFO "apm: no 32 bit BIOS support\n");
2212                 return -ENODEV;
2213         }
2214
2215         if (allow_ints)
2216                 apm_info.allow_ints = 1;
2217         if (broken_psr)
2218                 apm_info.get_power_status_broken = 1;
2219         if (realmode_power_off)
2220                 apm_info.realmode_power_off = 1;
2221         /* User can override, but default is to trust DMI */
2222         if (apm_disabled != -1)
2223                 apm_info.disabled = apm_disabled;
2224
2225         /*
2226          * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
2227          * but is reportedly a 1.0 BIOS.
2228          */
2229         if (apm_info.bios.version == 0x001)
2230                 apm_info.bios.version = 0x100;
2231
2232         /* BIOS < 1.2 doesn't set cseg_16_len */
2233         if (apm_info.bios.version < 0x102)
2234                 apm_info.bios.cseg_16_len = 0; /* 64k */
2235
2236         if (debug) {
2237                 printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x",
2238                         apm_info.bios.cseg, apm_info.bios.offset,
2239                         apm_info.bios.cseg_16, apm_info.bios.dseg);
2240                 if (apm_info.bios.version > 0x100)
2241                         printk(" cseg len %x, dseg len %x",
2242                                 apm_info.bios.cseg_len,
2243                                 apm_info.bios.dseg_len);
2244                 if (apm_info.bios.version > 0x101)
2245                         printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
2246                 printk("\n");
2247         }
2248
2249         if (apm_info.disabled) {
2250                 printk(KERN_NOTICE "apm: disabled on user request.\n");
2251                 return -ENODEV;
2252         }
2253         if ((num_online_cpus() > 1) && !power_off && !smp) {
2254                 printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
2255                 apm_info.disabled = 1;
2256                 return -ENODEV;
2257         }
2258         if (PM_IS_ACTIVE()) {
2259                 printk(KERN_NOTICE "apm: overridden by ACPI.\n");
2260                 apm_info.disabled = 1;
2261                 return -ENODEV;
2262         }
2263 #ifdef CONFIG_PM_LEGACY
2264         pm_active = 1;
2265 #endif
2266
2267         /*
2268          * Set up a segment that references the real mode segment 0x40
2269          * that extends up to the end of page zero (that we have reserved).
2270          * This is for buggy BIOS's that refer to (real mode) segment 0x40
2271          * even though they are called in protected mode.
2272          */
2273         set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
2274         _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
2275
2276         /*
2277          * Set up the long jump entry point to the APM BIOS, which is called
2278          * from inline assembly.
2279          */
2280         apm_bios_entry.offset = apm_info.bios.offset;
2281         apm_bios_entry.segment = APM_CS;
2282
2283         /*
2284          * The APM 1.1 BIOS is supposed to provide limit information that it
2285          * recognizes.  Many machines do this correctly, but many others do
2286          * not restrict themselves to their claimed limit.  When this happens,
2287          * they will cause a segmentation violation in the kernel at boot time.
2288          * Most BIOS's, however, will respect a 64k limit, so we use that.
2289          *
2290          * Note we only set APM segments on CPU zero, since we pin the APM
2291          * code to that CPU.
2292          */
2293         gdt = get_cpu_gdt_table(0);
2294         set_base(gdt[APM_CS >> 3],
2295                  __va((unsigned long)apm_info.bios.cseg << 4));
2296         set_base(gdt[APM_CS_16 >> 3],
2297                  __va((unsigned long)apm_info.bios.cseg_16 << 4));
2298         set_base(gdt[APM_DS >> 3],
2299                  __va((unsigned long)apm_info.bios.dseg << 4));
2300
2301         apm_proc = create_proc_entry("apm", 0, NULL);
2302         if (apm_proc)
2303                 apm_proc->proc_fops = &apm_file_ops;
2304
2305         kapmd_task = kthread_create(apm, NULL, "kapmd");
2306         if (IS_ERR(kapmd_task)) {
2307                 printk(KERN_ERR "apm: disabled - Unable to start kernel "
2308                                 "thread.\n");
2309                 err = PTR_ERR(kapmd_task);
2310                 kapmd_task = NULL;
2311                 remove_proc_entry("apm", NULL);
2312                 return err;
2313         }
2314         kapmd_task->flags |= PF_NOFREEZE;
2315         wake_up_process(kapmd_task);
2316
2317         if (num_online_cpus() > 1 && !smp ) {
2318                 printk(KERN_NOTICE
2319                    "apm: disabled - APM is not SMP safe (power off active).\n");
2320                 return 0;
2321         }
2322
2323         /*
2324          * Note we don't actually care if the misc_device cannot be registered.
2325          * this driver can do its job without it, even if userspace can't
2326          * control it.  just log the error
2327          */
2328         if (misc_register(&apm_device))
2329                 printk(KERN_WARNING "apm: Could not register misc device.\n");
2330
2331         if (HZ != 100)
2332                 idle_period = (idle_period * HZ) / 100;
2333         if (idle_threshold < 100) {
2334                 original_pm_idle = pm_idle;
2335                 pm_idle  = apm_cpu_idle;
2336                 set_pm_idle = 1;
2337         }
2338
2339         return 0;
2340 }
2341
2342 static void __exit apm_exit(void)
2343 {
2344         int     error;
2345
2346         if (set_pm_idle) {
2347                 pm_idle = original_pm_idle;
2348                 /*
2349                  * We are about to unload the current idle thread pm callback
2350                  * (pm_idle), Wait for all processors to update cached/local
2351                  * copies of pm_idle before proceeding.
2352                  */
2353                 cpu_idle_wait();
2354         }
2355         if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
2356             && (apm_info.connection_version > 0x0100)) {
2357                 error = apm_engage_power_management(APM_DEVICE_ALL, 0);
2358                 if (error)
2359                         apm_error("disengage power management", error);
2360         }
2361         misc_deregister(&apm_device);
2362         remove_proc_entry("apm", NULL);
2363         if (power_off)
2364                 pm_power_off = NULL;
2365         if (kapmd_task) {
2366                 kthread_stop(kapmd_task);
2367                 kapmd_task = NULL;
2368         }
2369 #ifdef CONFIG_PM_LEGACY
2370         pm_active = 0;
2371 #endif
2372 }
2373
2374 module_init(apm_init);
2375 module_exit(apm_exit);
2376
2377 MODULE_AUTHOR("Stephen Rothwell");
2378 MODULE_DESCRIPTION("Advanced Power Management");
2379 MODULE_LICENSE("GPL");
2380 module_param(debug, bool, 0644);
2381 MODULE_PARM_DESC(debug, "Enable debug mode");
2382 module_param(power_off, bool, 0444);
2383 MODULE_PARM_DESC(power_off, "Enable power off");
2384 module_param(bounce_interval, int, 0444);
2385 MODULE_PARM_DESC(bounce_interval,
2386                 "Set the number of ticks to ignore suspend bounces");
2387 module_param(allow_ints, bool, 0444);
2388 MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
2389 module_param(broken_psr, bool, 0444);
2390 MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
2391 module_param(realmode_power_off, bool, 0444);
2392 MODULE_PARM_DESC(realmode_power_off,
2393                 "Switch to real mode before powering off");
2394 module_param(idle_threshold, int, 0444);
2395 MODULE_PARM_DESC(idle_threshold,
2396         "System idle percentage above which to make APM BIOS idle calls");
2397 module_param(idle_period, int, 0444);
2398 MODULE_PARM_DESC(idle_period,
2399         "Period (in sec/100) over which to caculate the idle percentage");
2400 module_param(smp, bool, 0444);
2401 MODULE_PARM_DESC(smp,
2402         "Set this to enable APM use on an SMP platform. Use with caution on older systems");
2403 MODULE_ALIAS_MISCDEV(APM_MINOR_DEV);