Pull add-mmio-to-proc-iomem into release branch
[pandora-kernel.git] / 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/hwdev/busbios/amp_12.htm]
202  */
203
204 #include <linux/config.h>
205 #include <linux/module.h>
206
207 #include <linux/poll.h>
208 #include <linux/types.h>
209 #include <linux/stddef.h>
210 #include <linux/timer.h>
211 #include <linux/fcntl.h>
212 #include <linux/slab.h>
213 #include <linux/stat.h>
214 #include <linux/proc_fs.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/device.h>
222 #include <linux/kernel.h>
223 #include <linux/smp.h>
224 #include <linux/smp_lock.h>
225 #include <linux/dmi.h>
226 #include <linux/suspend.h>
227
228 #include <asm/system.h>
229 #include <asm/uaccess.h>
230 #include <asm/desc.h>
231 #include <asm/i8253.h>
232
233 #include "io_ports.h"
234
235 extern unsigned long get_cmos_time(void);
236 extern void machine_real_restart(unsigned char *, int);
237
238 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
239 extern int (*console_blank_hook)(int);
240 #endif
241
242 /*
243  * The apm_bios device is one of the misc char devices.
244  * This is its minor number.
245  */
246 #define APM_MINOR_DEV   134
247
248 /*
249  * See Documentation/Config.help for the configuration options.
250  *
251  * Various options can be changed at boot time as follows:
252  * (We allow underscores for compatibility with the modules code)
253  *      apm=on/off                      enable/disable APM
254  *          [no-]allow[-_]ints          allow interrupts during BIOS calls
255  *          [no-]broken[-_]psr          BIOS has a broken GetPowerStatus call
256  *          [no-]realmode[-_]power[-_]off       switch to real mode before
257  *                                              powering off
258  *          [no-]debug                  log some debugging messages
259  *          [no-]power[-_]off           power off on shutdown
260  *          [no-]smp                    Use apm even on an SMP box
261  *          bounce[-_]interval=<n>      number of ticks to ignore suspend
262  *                                      bounces
263  *          idle[-_]threshold=<n>       System idle percentage above which to
264  *                                      make APM BIOS idle calls. Set it to
265  *                                      100 to disable.
266  *          idle[-_]period=<n>          Period (in 1/100s of a second) over
267  *                                      which the idle percentage is
268  *                                      calculated.
269  */
270
271 /* KNOWN PROBLEM MACHINES:
272  *
273  * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
274  *                         [Confirmed by TI representative]
275  * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
276  *                    [Confirmed by BIOS disassembly]
277  *                    [This may work now ...]
278  * P: Toshiba 1950S: battery life information only gets updated after resume
279  * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
280  *      broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
281  * ?: AcerNote-950: oops on reading /proc/apm - workaround is a WIP
282  *      Neale Banks <neale@lowendale.com.au> December 2000
283  *
284  * Legend: U = unusable with APM patches
285  *         P = partially usable with APM patches
286  */
287
288 /*
289  * Define as 1 to make the driver always call the APM BIOS busy
290  * routine even if the clock was not reported as slowed by the
291  * idle routine.  Otherwise, define as 0.
292  */
293 #define ALWAYS_CALL_BUSY   1
294
295 /*
296  * Define to make the APM BIOS calls zero all data segment registers (so
297  * that an incorrect BIOS implementation will cause a kernel panic if it
298  * tries to write to arbitrary memory).
299  */
300 #define APM_ZERO_SEGS
301
302 #include "apm.h"
303
304 /*
305  * Define to make all _set_limit calls use 64k limits.  The APM 1.1 BIOS is
306  * supposed to provide limit information that it recognizes.  Many machines
307  * do this correctly, but many others do not restrict themselves to their
308  * claimed limit.  When this happens, they will cause a segmentation
309  * violation in the kernel at boot time.  Most BIOS's, however, will
310  * respect a 64k limit, so we use that.  If you want to be pedantic and
311  * hold your BIOS to its claims, then undefine this.
312  */
313 #define APM_RELAX_SEGMENTS
314
315 /*
316  * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
317  * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
318  * David Chen <chen@ctpa04.mit.edu>
319  */
320 #undef INIT_TIMER_AFTER_SUSPEND
321
322 #ifdef INIT_TIMER_AFTER_SUSPEND
323 #include <linux/timex.h>
324 #include <asm/io.h>
325 #include <linux/delay.h>
326 #endif
327
328 /*
329  * Need to poll the APM BIOS every second
330  */
331 #define APM_CHECK_TIMEOUT       (HZ)
332
333 /*
334  * Ignore suspend events for this amount of time after a resume
335  */
336 #define DEFAULT_BOUNCE_INTERVAL         (3 * HZ)
337
338 /*
339  * Maximum number of events stored
340  */
341 #define APM_MAX_EVENTS          20
342
343 /*
344  * The per-file APM data
345  */
346 struct apm_user {
347         int             magic;
348         struct apm_user *       next;
349         unsigned int    suser: 1;
350         unsigned int    writer: 1;
351         unsigned int    reader: 1;
352         unsigned int    suspend_wait: 1;
353         int             suspend_result;
354         int             suspends_pending;
355         int             standbys_pending;
356         int             suspends_read;
357         int             standbys_read;
358         int             event_head;
359         int             event_tail;
360         apm_event_t     events[APM_MAX_EVENTS];
361 };
362
363 /*
364  * The magic number in apm_user
365  */
366 #define APM_BIOS_MAGIC          0x4101
367
368 /*
369  * idle percentage above which bios idle calls are done
370  */
371 #ifdef CONFIG_APM_CPU_IDLE
372 #define DEFAULT_IDLE_THRESHOLD  95
373 #else
374 #define DEFAULT_IDLE_THRESHOLD  100
375 #endif
376 #define DEFAULT_IDLE_PERIOD     (100 / 3)
377
378 /*
379  * Local variables
380  */
381 static struct {
382         unsigned long   offset;
383         unsigned short  segment;
384 }                               apm_bios_entry;
385 static int                      clock_slowed;
386 static int                      idle_threshold = DEFAULT_IDLE_THRESHOLD;
387 static int                      idle_period = DEFAULT_IDLE_PERIOD;
388 static int                      set_pm_idle;
389 static int                      suspends_pending;
390 static int                      standbys_pending;
391 static int                      ignore_sys_suspend;
392 static int                      ignore_normal_resume;
393 static int                      bounce_interval = DEFAULT_BOUNCE_INTERVAL;
394
395 #ifdef CONFIG_APM_RTC_IS_GMT
396 #       define  clock_cmos_diff 0
397 #       define  got_clock_diff  1
398 #else
399 static long                     clock_cmos_diff;
400 static int                      got_clock_diff;
401 #endif
402 static int                      debug;
403 static int                      smp;
404 static int                      apm_disabled = -1;
405 #ifdef CONFIG_SMP
406 static int                      power_off;
407 #else
408 static int                      power_off = 1;
409 #endif
410 #ifdef CONFIG_APM_REAL_MODE_POWER_OFF
411 static int                      realmode_power_off = 1;
412 #else
413 static int                      realmode_power_off;
414 #endif
415 static int                      exit_kapmd;
416 static int                      kapmd_running;
417 #ifdef CONFIG_APM_ALLOW_INTS
418 static int                      allow_ints = 1;
419 #else
420 static int                      allow_ints;
421 #endif
422 static int                      broken_psr;
423
424 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
425 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
426 static struct apm_user *        user_list;
427 static DEFINE_SPINLOCK(user_list_lock);
428 static struct desc_struct       bad_bios_desc = { 0, 0x00409200 };
429
430 static char                     driver_version[] = "1.16ac";    /* no spaces */
431
432 /*
433  *      APM event names taken from the APM 1.2 specification. These are
434  *      the message codes that the BIOS uses to tell us about events
435  */
436 static char *   apm_event_name[] = {
437         "system standby",
438         "system suspend",
439         "normal resume",
440         "critical resume",
441         "low battery",
442         "power status change",
443         "update time",
444         "critical suspend",
445         "user standby",
446         "user suspend",
447         "system standby resume",
448         "capabilities change"
449 };
450 #define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
451
452 typedef struct lookup_t {
453         int     key;
454         char *  msg;
455 } lookup_t;
456
457 /*
458  *      The BIOS returns a set of standard error codes in AX when the
459  *      carry flag is set.
460  */
461  
462 static const lookup_t error_table[] = {
463 /* N/A  { APM_SUCCESS,          "Operation succeeded" }, */
464         { APM_DISABLED,         "Power management disabled" },
465         { APM_CONNECTED,        "Real mode interface already connected" },
466         { APM_NOT_CONNECTED,    "Interface not connected" },
467         { APM_16_CONNECTED,     "16 bit interface already connected" },
468 /* N/A  { APM_16_UNSUPPORTED,   "16 bit interface not supported" }, */
469         { APM_32_CONNECTED,     "32 bit interface already connected" },
470         { APM_32_UNSUPPORTED,   "32 bit interface not supported" },
471         { APM_BAD_DEVICE,       "Unrecognized device ID" },
472         { APM_BAD_PARAM,        "Parameter out of range" },
473         { APM_NOT_ENGAGED,      "Interface not engaged" },
474         { APM_BAD_FUNCTION,     "Function not supported" },
475         { APM_RESUME_DISABLED,  "Resume timer disabled" },
476         { APM_BAD_STATE,        "Unable to enter requested state" },
477 /* N/A  { APM_NO_EVENTS,        "No events pending" }, */
478         { APM_NO_ERROR,         "BIOS did not set a return code" },
479         { APM_NOT_PRESENT,      "No APM present" }
480 };
481 #define ERROR_COUNT     ARRAY_SIZE(error_table)
482
483 /**
484  *      apm_error       -       display an APM error
485  *      @str: information string
486  *      @err: APM BIOS return code
487  *
488  *      Write a meaningful log entry to the kernel log in the event of
489  *      an APM error.
490  */
491  
492 static void apm_error(char *str, int err)
493 {
494         int     i;
495
496         for (i = 0; i < ERROR_COUNT; i++)
497                 if (error_table[i].key == err) break;
498         if (i < ERROR_COUNT)
499                 printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg);
500         else
501                 printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n",
502                         str, err);
503 }
504
505 /*
506  * Lock APM functionality to physical CPU 0
507  */
508  
509 #ifdef CONFIG_SMP
510
511 static cpumask_t apm_save_cpus(void)
512 {
513         cpumask_t x = current->cpus_allowed;
514         /* Some bioses don't like being called from CPU != 0 */
515         set_cpus_allowed(current, cpumask_of_cpu(0));
516         BUG_ON(smp_processor_id() != 0);
517         return x;
518 }
519
520 static inline void apm_restore_cpus(cpumask_t mask)
521 {
522         set_cpus_allowed(current, mask);
523 }
524
525 #else
526
527 /*
528  *      No CPU lockdown needed on a uniprocessor
529  */
530  
531 #define apm_save_cpus()         (current->cpus_allowed)
532 #define apm_restore_cpus(x)     (void)(x)
533
534 #endif
535
536 /*
537  * These are the actual BIOS calls.  Depending on APM_ZERO_SEGS and
538  * apm_info.allow_ints, we are being really paranoid here!  Not only
539  * are interrupts disabled, but all the segment registers (except SS)
540  * are saved and zeroed this means that if the BIOS tries to reference
541  * any data without explicitly loading the segment registers, the kernel
542  * will fault immediately rather than have some unforeseen circumstances
543  * for the rest of the kernel.  And it will be very obvious!  :-) Doing
544  * this depends on CS referring to the same physical memory as DS so that
545  * DS can be zeroed before the call. Unfortunately, we can't do anything
546  * about the stack segment/pointer.  Also, we tell the compiler that
547  * everything could change.
548  *
549  * Also, we KNOW that for the non error case of apm_bios_call, there
550  * is no useful data returned in the low order 8 bits of eax.
551  */
552 #define APM_DO_CLI      \
553         if (apm_info.allow_ints) \
554                 local_irq_enable(); \
555         else \
556                 local_irq_disable();
557
558 #ifdef APM_ZERO_SEGS
559 #       define APM_DECL_SEGS \
560                 unsigned int saved_fs; unsigned int saved_gs;
561 #       define APM_DO_SAVE_SEGS \
562                 savesegment(fs, saved_fs); savesegment(gs, saved_gs)
563 #       define APM_DO_RESTORE_SEGS \
564                 loadsegment(fs, saved_fs); loadsegment(gs, saved_gs)
565 #else
566 #       define APM_DECL_SEGS
567 #       define APM_DO_SAVE_SEGS
568 #       define APM_DO_RESTORE_SEGS
569 #endif
570
571 /**
572  *      apm_bios_call   -       Make an APM BIOS 32bit call
573  *      @func: APM function to execute
574  *      @ebx_in: EBX register for call entry
575  *      @ecx_in: ECX register for call entry
576  *      @eax: EAX register return
577  *      @ebx: EBX register return
578  *      @ecx: ECX register return
579  *      @edx: EDX register return
580  *      @esi: ESI register return
581  *
582  *      Make an APM call using the 32bit protected mode interface. The
583  *      caller is responsible for knowing if APM BIOS is configured and
584  *      enabled. This call can disable interrupts for a long period of
585  *      time on some laptops.  The return value is in AH and the carry
586  *      flag is loaded into AL.  If there is an error, then the error
587  *      code is returned in AH (bits 8-15 of eax) and this function
588  *      returns non-zero.
589  */
590  
591 static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
592         u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
593 {
594         APM_DECL_SEGS
595         unsigned long           flags;
596         cpumask_t               cpus;
597         int                     cpu;
598         struct desc_struct      save_desc_40;
599         struct desc_struct      *gdt;
600
601         cpus = apm_save_cpus();
602         
603         cpu = get_cpu();
604         gdt = get_cpu_gdt_table(cpu);
605         save_desc_40 = gdt[0x40 / 8];
606         gdt[0x40 / 8] = bad_bios_desc;
607
608         local_save_flags(flags);
609         APM_DO_CLI;
610         APM_DO_SAVE_SEGS;
611         apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi);
612         APM_DO_RESTORE_SEGS;
613         local_irq_restore(flags);
614         gdt[0x40 / 8] = save_desc_40;
615         put_cpu();
616         apm_restore_cpus(cpus);
617         
618         return *eax & 0xff;
619 }
620
621 /**
622  *      apm_bios_call_simple    -       make a simple APM BIOS 32bit call
623  *      @func: APM function to invoke
624  *      @ebx_in: EBX register value for BIOS call
625  *      @ecx_in: ECX register value for BIOS call
626  *      @eax: EAX register on return from the BIOS call
627  *
628  *      Make a BIOS call that does only returns one value, or just status.
629  *      If there is an error, then the error code is returned in AH
630  *      (bits 8-15 of eax) and this function returns non-zero. This is
631  *      used for simpler BIOS operations. This call may hold interrupts
632  *      off for a long time on some laptops.
633  */
634
635 static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
636 {
637         u8                      error;
638         APM_DECL_SEGS
639         unsigned long           flags;
640         cpumask_t               cpus;
641         int                     cpu;
642         struct desc_struct      save_desc_40;
643         struct desc_struct      *gdt;
644
645         cpus = apm_save_cpus();
646         
647         cpu = get_cpu();
648         gdt = get_cpu_gdt_table(cpu);
649         save_desc_40 = gdt[0x40 / 8];
650         gdt[0x40 / 8] = bad_bios_desc;
651
652         local_save_flags(flags);
653         APM_DO_CLI;
654         APM_DO_SAVE_SEGS;
655         error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax);
656         APM_DO_RESTORE_SEGS;
657         local_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 = test_thread_flag(TIF_POLLING_NRFLAG);
777         if (polling) {
778                 clear_thread_flag(TIF_POLLING_NRFLAG);
779                 smp_mb__after_clear_bit();
780         }
781         if (!need_resched()) {
782                 idled = 1;
783                 ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax);
784         }
785         if (polling)
786                 set_thread_flag(TIF_POLLING_NRFLAG);
787
788         if (!idled)
789                 return 0;
790
791         if (ret) {
792                 static unsigned long t;
793
794                 /* This always fails on some SMP boards running UP kernels.
795                  * Only report the failure the first 5 times.
796                  */
797                 if (++t < 5)
798                 {
799                         printk(KERN_DEBUG "apm_do_idle failed (%d)\n",
800                                         (eax >> 8) & 0xff);
801                         t = jiffies;
802                 }
803                 return -1;
804         }
805         clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
806         return clock_slowed;
807 }
808
809 /**
810  *      apm_do_busy     -       inform the BIOS the CPU is busy
811  *
812  *      Request that the BIOS brings the CPU back to full performance. 
813  */
814  
815 static void apm_do_busy(void)
816 {
817         u32     dummy;
818
819         if (clock_slowed || ALWAYS_CALL_BUSY) {
820                 (void) apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy);
821                 clock_slowed = 0;
822         }
823 }
824
825 /*
826  * If no process has really been interested in
827  * the CPU for some time, we want to call BIOS
828  * power management - we probably want
829  * to conserve power.
830  */
831 #define IDLE_CALC_LIMIT   (HZ * 100)
832 #define IDLE_LEAKY_MAX    16
833
834 static void (*original_pm_idle)(void);
835
836 extern void default_idle(void);
837
838 /**
839  * apm_cpu_idle         -       cpu idling for APM capable Linux
840  *
841  * This is the idling function the kernel executes when APM is available. It 
842  * tries to do BIOS powermanagement based on the average system idle time.
843  * Furthermore it calls the system default idle routine.
844  */
845
846 static void apm_cpu_idle(void)
847 {
848         static int use_apm_idle; /* = 0 */
849         static unsigned int last_jiffies; /* = 0 */
850         static unsigned int last_stime; /* = 0 */
851
852         int apm_idle_done = 0;
853         unsigned int jiffies_since_last_check = jiffies - last_jiffies;
854         unsigned int bucket;
855
856 recalc:
857         if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
858                 use_apm_idle = 0;
859                 last_jiffies = jiffies;
860                 last_stime = current->stime;
861         } else if (jiffies_since_last_check > idle_period) {
862                 unsigned int idle_percentage;
863
864                 idle_percentage = current->stime - last_stime;
865                 idle_percentage *= 100;
866                 idle_percentage /= jiffies_since_last_check;
867                 use_apm_idle = (idle_percentage > idle_threshold);
868                 if (apm_info.forbid_idle)
869                         use_apm_idle = 0;
870                 last_jiffies = jiffies;
871                 last_stime = current->stime;
872         }
873
874         bucket = IDLE_LEAKY_MAX;
875
876         while (!need_resched()) {
877                 if (use_apm_idle) {
878                         unsigned int t;
879
880                         t = jiffies;
881                         switch (apm_do_idle()) {
882                         case 0: apm_idle_done = 1;
883                                 if (t != jiffies) {
884                                         if (bucket) {
885                                                 bucket = IDLE_LEAKY_MAX;
886                                                 continue;
887                                         }
888                                 } else if (bucket) {
889                                         bucket--;
890                                         continue;
891                                 }
892                                 break;
893                         case 1: apm_idle_done = 1;
894                                 break;
895                         default: /* BIOS refused */
896                                 break;
897                         }
898                 }
899                 if (original_pm_idle)
900                         original_pm_idle();
901                 else
902                         default_idle();
903                 jiffies_since_last_check = jiffies - last_jiffies;
904                 if (jiffies_since_last_check > idle_period)
905                         goto recalc;
906         }
907
908         if (apm_idle_done)
909                 apm_do_busy();
910 }
911
912 /**
913  *      apm_power_off   -       ask the BIOS to power off
914  *
915  *      Handle the power off sequence. This is the one piece of code we
916  *      will execute even on SMP machines. In order to deal with BIOS
917  *      bugs we support real mode APM BIOS power off calls. We also make
918  *      the SMP call on CPU0 as some systems will only honour this call
919  *      on their first cpu.
920  */
921  
922 static void apm_power_off(void)
923 {
924         unsigned char   po_bios_call[] = {
925                 0xb8, 0x00, 0x10,       /* movw  $0x1000,ax  */
926                 0x8e, 0xd0,             /* movw  ax,ss       */
927                 0xbc, 0x00, 0xf0,       /* movw  $0xf000,sp  */
928                 0xb8, 0x07, 0x53,       /* movw  $0x5307,ax  */
929                 0xbb, 0x01, 0x00,       /* movw  $0x0001,bx  */
930                 0xb9, 0x03, 0x00,       /* movw  $0x0003,cx  */
931                 0xcd, 0x15              /* int   $0x15       */
932         };
933
934         /* Some bioses don't like being called from CPU != 0 */
935         if (apm_info.realmode_power_off)
936         {
937                 (void)apm_save_cpus();
938                 machine_real_restart(po_bios_call, sizeof(po_bios_call));
939         }
940         else
941                 (void) set_system_power_state(APM_STATE_OFF);
942 }
943
944 #ifdef CONFIG_APM_DO_ENABLE
945
946 /**
947  *      apm_enable_power_management - enable BIOS APM power management
948  *      @enable: enable yes/no
949  *
950  *      Enable or disable the APM BIOS power services. 
951  */
952  
953 static int apm_enable_power_management(int enable)
954 {
955         u32     eax;
956
957         if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
958                 return APM_NOT_ENGAGED;
959         if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
960                         enable, &eax))
961                 return (eax >> 8) & 0xff;
962         if (enable)
963                 apm_info.bios.flags &= ~APM_BIOS_DISABLED;
964         else
965                 apm_info.bios.flags |= APM_BIOS_DISABLED;
966         return APM_SUCCESS;
967 }
968 #endif
969
970 /**
971  *      apm_get_power_status    -       get current power state
972  *      @status: returned status
973  *      @bat: battery info
974  *      @life: estimated life
975  *
976  *      Obtain the current power status from the APM BIOS. We return a
977  *      status which gives the rough battery status, and current power
978  *      source. The bat value returned give an estimate as a percentage
979  *      of life and a status value for the battery. The estimated life
980  *      if reported is a lifetime in secodnds/minutes at current powwer
981  *      consumption.
982  */
983  
984 static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
985 {
986         u32     eax;
987         u32     ebx;
988         u32     ecx;
989         u32     edx;
990         u32     dummy;
991
992         if (apm_info.get_power_status_broken)
993                 return APM_32_UNSUPPORTED;
994         if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0,
995                         &eax, &ebx, &ecx, &edx, &dummy))
996                 return (eax >> 8) & 0xff;
997         *status = ebx;
998         *bat = ecx;
999         if (apm_info.get_power_status_swabinminutes) {
1000                 *life = swab16((u16)edx);
1001                 *life |= 0x8000;
1002         } else
1003                 *life = edx;
1004         return APM_SUCCESS;
1005 }
1006
1007 #if 0
1008 static int apm_get_battery_status(u_short which, u_short *status,
1009                                   u_short *bat, u_short *life, u_short *nbat)
1010 {
1011         u32     eax;
1012         u32     ebx;
1013         u32     ecx;
1014         u32     edx;
1015         u32     esi;
1016
1017         if (apm_info.connection_version < 0x0102) {
1018                 /* pretend we only have one battery. */
1019                 if (which != 1)
1020                         return APM_BAD_DEVICE;
1021                 *nbat = 1;
1022                 return apm_get_power_status(status, bat, life);
1023         }
1024
1025         if (apm_bios_call(APM_FUNC_GET_STATUS, (0x8000 | (which)), 0, &eax,
1026                         &ebx, &ecx, &edx, &esi))
1027                 return (eax >> 8) & 0xff;
1028         *status = ebx;
1029         *bat = ecx;
1030         *life = edx;
1031         *nbat = esi;
1032         return APM_SUCCESS;
1033 }
1034 #endif
1035
1036 /**
1037  *      apm_engage_power_management     -       enable PM on a device
1038  *      @device: identity of device
1039  *      @enable: on/off
1040  *
1041  *      Activate or deactive power management on either a specific device
1042  *      or the entire system (%APM_DEVICE_ALL).
1043  */
1044  
1045 static int apm_engage_power_management(u_short device, int enable)
1046 {
1047         u32     eax;
1048
1049         if ((enable == 0) && (device == APM_DEVICE_ALL)
1050             && (apm_info.bios.flags & APM_BIOS_DISABLED))
1051                 return APM_DISABLED;
1052         if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
1053                 return (eax >> 8) & 0xff;
1054         if (device == APM_DEVICE_ALL) {
1055                 if (enable)
1056                         apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
1057                 else
1058                         apm_info.bios.flags |= APM_BIOS_DISENGAGED;
1059         }
1060         return APM_SUCCESS;
1061 }
1062
1063 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1064
1065 /**
1066  *      apm_console_blank       -       blank the display
1067  *      @blank: on/off
1068  *
1069  *      Attempt to blank the console, firstly by blanking just video device
1070  *      zero, and if that fails (some BIOSes don't support it) then it blanks
1071  *      all video devices. Typically the BIOS will do laptop backlight and
1072  *      monitor powerdown for us.
1073  */
1074  
1075 static int apm_console_blank(int blank)
1076 {
1077         int     error;
1078         u_short state;
1079
1080         state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
1081         /* Blank the first display device */
1082         error = set_power_state(0x100, state);
1083         if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) {
1084                 /* try to blank them all instead */
1085                 error = set_power_state(0x1ff, state);
1086                 if ((error != APM_SUCCESS) && (error != APM_NO_ERROR))
1087                         /* try to blank device one instead */
1088                         error = set_power_state(0x101, state);
1089         }
1090         if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
1091                 return 1;
1092         if (error == APM_NOT_ENGAGED) {
1093                 static int tried;
1094                 int eng_error;
1095                 if (tried++ == 0) {
1096                         eng_error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1097                         if (eng_error) {
1098                                 apm_error("set display", error);
1099                                 apm_error("engage interface", eng_error);
1100                                 return 0;
1101                         } else
1102                                 return apm_console_blank(blank);
1103                 }
1104         }
1105         apm_error("set display", error);
1106         return 0;
1107 }
1108 #endif
1109
1110 static int queue_empty(struct apm_user *as)
1111 {
1112         return as->event_head == as->event_tail;
1113 }
1114
1115 static apm_event_t get_queued_event(struct apm_user *as)
1116 {
1117         as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
1118         return as->events[as->event_tail];
1119 }
1120
1121 static void queue_event(apm_event_t event, struct apm_user *sender)
1122 {
1123         struct apm_user *       as;
1124
1125         spin_lock(&user_list_lock);
1126         if (user_list == NULL)
1127                 goto out;
1128         for (as = user_list; as != NULL; as = as->next) {
1129                 if ((as == sender) || (!as->reader))
1130                         continue;
1131                 as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
1132                 if (as->event_head == as->event_tail) {
1133                         static int notified;
1134
1135                         if (notified++ == 0)
1136                             printk(KERN_ERR "apm: an event queue overflowed\n");
1137                         as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
1138                 }
1139                 as->events[as->event_head] = event;
1140                 if ((!as->suser) || (!as->writer))
1141                         continue;
1142                 switch (event) {
1143                 case APM_SYS_SUSPEND:
1144                 case APM_USER_SUSPEND:
1145                         as->suspends_pending++;
1146                         suspends_pending++;
1147                         break;
1148
1149                 case APM_SYS_STANDBY:
1150                 case APM_USER_STANDBY:
1151                         as->standbys_pending++;
1152                         standbys_pending++;
1153                         break;
1154                 }
1155         }
1156         wake_up_interruptible(&apm_waitqueue);
1157 out:
1158         spin_unlock(&user_list_lock);
1159 }
1160
1161 static void set_time(void)
1162 {
1163         if (got_clock_diff) {   /* Must know time zone in order to set clock */
1164                 xtime.tv_sec = get_cmos_time() + clock_cmos_diff;
1165                 xtime.tv_nsec = 0; 
1166         } 
1167 }
1168
1169 static void get_time_diff(void)
1170 {
1171 #ifndef CONFIG_APM_RTC_IS_GMT
1172         /*
1173          * Estimate time zone so that set_time can update the clock
1174          */
1175         clock_cmos_diff = -get_cmos_time();
1176         clock_cmos_diff += get_seconds();
1177         got_clock_diff = 1;
1178 #endif
1179 }
1180
1181 static void reinit_timer(void)
1182 {
1183 #ifdef INIT_TIMER_AFTER_SUSPEND
1184         unsigned long flags;
1185
1186         spin_lock_irqsave(&i8253_lock, flags);
1187         /* set the clock to 100 Hz */
1188         outb_p(0x34, PIT_MODE);         /* binary, mode 2, LSB/MSB, ch 0 */
1189         udelay(10);
1190         outb_p(LATCH & 0xff, PIT_CH0);  /* LSB */
1191         udelay(10);
1192         outb(LATCH >> 8, PIT_CH0);      /* MSB */
1193         udelay(10);
1194         spin_unlock_irqrestore(&i8253_lock, flags);
1195 #endif
1196 }
1197
1198 static int suspend(int vetoable)
1199 {
1200         int             err;
1201         struct apm_user *as;
1202
1203         if (pm_send_all(PM_SUSPEND, (void *)3)) {
1204                 /* Vetoed */
1205                 if (vetoable) {
1206                         if (apm_info.connection_version > 0x100)
1207                                 set_system_power_state(APM_STATE_REJECT);
1208                         err = -EBUSY;
1209                         ignore_sys_suspend = 0;
1210                         printk(KERN_WARNING "apm: suspend was vetoed.\n");
1211                         goto out;
1212                 }
1213                 printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
1214         }
1215
1216         device_suspend(PMSG_SUSPEND);
1217         local_irq_disable();
1218         device_power_down(PMSG_SUSPEND);
1219
1220         /* serialize with the timer interrupt */
1221         write_seqlock(&xtime_lock);
1222
1223         /* protect against access to timer chip registers */
1224         spin_lock(&i8253_lock);
1225
1226         get_time_diff();
1227         /*
1228          * Irq spinlock must be dropped around set_system_power_state.
1229          * We'll undo any timer changes due to interrupts below.
1230          */
1231         spin_unlock(&i8253_lock);
1232         write_sequnlock(&xtime_lock);
1233         local_irq_enable();
1234
1235         save_processor_state();
1236         err = set_system_power_state(APM_STATE_SUSPEND);
1237         ignore_normal_resume = 1;
1238         restore_processor_state();
1239
1240         local_irq_disable();
1241         write_seqlock(&xtime_lock);
1242         spin_lock(&i8253_lock);
1243         reinit_timer();
1244         set_time();
1245
1246         spin_unlock(&i8253_lock);
1247         write_sequnlock(&xtime_lock);
1248
1249         if (err == APM_NO_ERROR)
1250                 err = APM_SUCCESS;
1251         if (err != APM_SUCCESS)
1252                 apm_error("suspend", err);
1253         err = (err == APM_SUCCESS) ? 0 : -EIO;
1254         device_power_up();
1255         local_irq_enable();
1256         device_resume();
1257         pm_send_all(PM_RESUME, (void *)0);
1258         queue_event(APM_NORMAL_RESUME, NULL);
1259  out:
1260         spin_lock(&user_list_lock);
1261         for (as = user_list; as != NULL; as = as->next) {
1262                 as->suspend_wait = 0;
1263                 as->suspend_result = err;
1264         }
1265         spin_unlock(&user_list_lock);
1266         wake_up_interruptible(&apm_suspend_waitqueue);
1267         return err;
1268 }
1269
1270 static void standby(void)
1271 {
1272         int     err;
1273
1274         local_irq_disable();
1275         device_power_down(PMSG_SUSPEND);
1276         /* serialize with the timer interrupt */
1277         write_seqlock(&xtime_lock);
1278         /* If needed, notify drivers here */
1279         get_time_diff();
1280         write_sequnlock(&xtime_lock);
1281         local_irq_enable();
1282
1283         err = set_system_power_state(APM_STATE_STANDBY);
1284         if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
1285                 apm_error("standby", err);
1286
1287         local_irq_disable();
1288         device_power_up();
1289         local_irq_enable();
1290 }
1291
1292 static apm_event_t get_event(void)
1293 {
1294         int             error;
1295         apm_event_t     event;
1296         apm_eventinfo_t info;
1297
1298         static int notified;
1299
1300         /* we don't use the eventinfo */
1301         error = apm_get_event(&event, &info);
1302         if (error == APM_SUCCESS)
1303                 return event;
1304
1305         if ((error != APM_NO_EVENTS) && (notified++ == 0))
1306                 apm_error("get_event", error);
1307
1308         return 0;
1309 }
1310
1311 static void check_events(void)
1312 {
1313         apm_event_t             event;
1314         static unsigned long    last_resume;
1315         static int              ignore_bounce;
1316
1317         while ((event = get_event()) != 0) {
1318                 if (debug) {
1319                         if (event <= NR_APM_EVENT_NAME)
1320                                 printk(KERN_DEBUG "apm: received %s notify\n",
1321                                        apm_event_name[event - 1]);
1322                         else
1323                                 printk(KERN_DEBUG "apm: received unknown "
1324                                        "event 0x%02x\n", event);
1325                 }
1326                 if (ignore_bounce
1327                     && ((jiffies - last_resume) > bounce_interval))
1328                         ignore_bounce = 0;
1329
1330                 switch (event) {
1331                 case APM_SYS_STANDBY:
1332                 case APM_USER_STANDBY:
1333                         queue_event(event, NULL);
1334                         if (standbys_pending <= 0)
1335                                 standby();
1336                         break;
1337
1338                 case APM_USER_SUSPEND:
1339 #ifdef CONFIG_APM_IGNORE_USER_SUSPEND
1340                         if (apm_info.connection_version > 0x100)
1341                                 set_system_power_state(APM_STATE_REJECT);
1342                         break;
1343 #endif
1344                 case APM_SYS_SUSPEND:
1345                         if (ignore_bounce) {
1346                                 if (apm_info.connection_version > 0x100)
1347                                         set_system_power_state(APM_STATE_REJECT);
1348                                 break;
1349                         }
1350                         /*
1351                          * If we are already processing a SUSPEND,
1352                          * then further SUSPEND events from the BIOS
1353                          * will be ignored.  We also return here to
1354                          * cope with the fact that the Thinkpads keep
1355                          * sending a SUSPEND event until something else
1356                          * happens!
1357                          */
1358                         if (ignore_sys_suspend)
1359                                 return;
1360                         ignore_sys_suspend = 1;
1361                         queue_event(event, NULL);
1362                         if (suspends_pending <= 0)
1363                                 (void) suspend(1);
1364                         break;
1365
1366                 case APM_NORMAL_RESUME:
1367                 case APM_CRITICAL_RESUME:
1368                 case APM_STANDBY_RESUME:
1369                         ignore_sys_suspend = 0;
1370                         last_resume = jiffies;
1371                         ignore_bounce = 1;
1372                         if ((event != APM_NORMAL_RESUME)
1373                             || (ignore_normal_resume == 0)) {
1374                                 write_seqlock_irq(&xtime_lock);
1375                                 set_time();
1376                                 write_sequnlock_irq(&xtime_lock);
1377                                 device_resume();
1378                                 pm_send_all(PM_RESUME, (void *)0);
1379                                 queue_event(event, NULL);
1380                         }
1381                         ignore_normal_resume = 0;
1382                         break;
1383
1384                 case APM_CAPABILITY_CHANGE:
1385                 case APM_LOW_BATTERY:
1386                 case APM_POWER_STATUS_CHANGE:
1387                         queue_event(event, NULL);
1388                         /* If needed, notify drivers here */
1389                         break;
1390
1391                 case APM_UPDATE_TIME:
1392                         write_seqlock_irq(&xtime_lock);
1393                         set_time();
1394                         write_sequnlock_irq(&xtime_lock);
1395                         break;
1396
1397                 case APM_CRITICAL_SUSPEND:
1398                         /*
1399                          * We are not allowed to reject a critical suspend.
1400                          */
1401                         (void) suspend(0);
1402                         break;
1403                 }
1404         }
1405 }
1406
1407 static void apm_event_handler(void)
1408 {
1409         static int      pending_count = 4;
1410         int             err;
1411
1412         if ((standbys_pending > 0) || (suspends_pending > 0)) {
1413                 if ((apm_info.connection_version > 0x100) &&
1414                                 (pending_count-- <= 0)) {
1415                         pending_count = 4;
1416                         if (debug)
1417                                 printk(KERN_DEBUG "apm: setting state busy\n");
1418                         err = set_system_power_state(APM_STATE_BUSY);
1419                         if (err)
1420                                 apm_error("busy", err);
1421                 }
1422         } else
1423                 pending_count = 4;
1424         check_events();
1425 }
1426
1427 /*
1428  * This is the APM thread main loop.
1429  */
1430
1431 static void apm_mainloop(void)
1432 {
1433         DECLARE_WAITQUEUE(wait, current);
1434
1435         add_wait_queue(&apm_waitqueue, &wait);
1436         set_current_state(TASK_INTERRUPTIBLE);
1437         for (;;) {
1438                 schedule_timeout(APM_CHECK_TIMEOUT);
1439                 if (exit_kapmd)
1440                         break;
1441                 /*
1442                  * Ok, check all events, check for idle (and mark us sleeping
1443                  * so as not to count towards the load average)..
1444                  */
1445                 set_current_state(TASK_INTERRUPTIBLE);
1446                 apm_event_handler();
1447         }
1448         remove_wait_queue(&apm_waitqueue, &wait);
1449 }
1450
1451 static int check_apm_user(struct apm_user *as, const char *func)
1452 {
1453         if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
1454                 printk(KERN_ERR "apm: %s passed bad filp\n", func);
1455                 return 1;
1456         }
1457         return 0;
1458 }
1459
1460 static ssize_t do_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
1461 {
1462         struct apm_user *       as;
1463         int                     i;
1464         apm_event_t             event;
1465
1466         as = fp->private_data;
1467         if (check_apm_user(as, "read"))
1468                 return -EIO;
1469         if ((int)count < sizeof(apm_event_t))
1470                 return -EINVAL;
1471         if ((queue_empty(as)) && (fp->f_flags & O_NONBLOCK))
1472                 return -EAGAIN;
1473         wait_event_interruptible(apm_waitqueue, !queue_empty(as));
1474         i = count;
1475         while ((i >= sizeof(event)) && !queue_empty(as)) {
1476                 event = get_queued_event(as);
1477                 if (copy_to_user(buf, &event, sizeof(event))) {
1478                         if (i < count)
1479                                 break;
1480                         return -EFAULT;
1481                 }
1482                 switch (event) {
1483                 case APM_SYS_SUSPEND:
1484                 case APM_USER_SUSPEND:
1485                         as->suspends_read++;
1486                         break;
1487
1488                 case APM_SYS_STANDBY:
1489                 case APM_USER_STANDBY:
1490                         as->standbys_read++;
1491                         break;
1492                 }
1493                 buf += sizeof(event);
1494                 i -= sizeof(event);
1495         }
1496         if (i < count)
1497                 return count - i;
1498         if (signal_pending(current))
1499                 return -ERESTARTSYS;
1500         return 0;
1501 }
1502
1503 static unsigned int do_poll(struct file *fp, poll_table * wait)
1504 {
1505         struct apm_user * as;
1506
1507         as = fp->private_data;
1508         if (check_apm_user(as, "poll"))
1509                 return 0;
1510         poll_wait(fp, &apm_waitqueue, wait);
1511         if (!queue_empty(as))
1512                 return POLLIN | POLLRDNORM;
1513         return 0;
1514 }
1515
1516 static int do_ioctl(struct inode * inode, struct file *filp,
1517                     u_int cmd, u_long arg)
1518 {
1519         struct apm_user *       as;
1520
1521         as = filp->private_data;
1522         if (check_apm_user(as, "ioctl"))
1523                 return -EIO;
1524         if ((!as->suser) || (!as->writer))
1525                 return -EPERM;
1526         switch (cmd) {
1527         case APM_IOC_STANDBY:
1528                 if (as->standbys_read > 0) {
1529                         as->standbys_read--;
1530                         as->standbys_pending--;
1531                         standbys_pending--;
1532                 } else
1533                         queue_event(APM_USER_STANDBY, as);
1534                 if (standbys_pending <= 0)
1535                         standby();
1536                 break;
1537         case APM_IOC_SUSPEND:
1538                 if (as->suspends_read > 0) {
1539                         as->suspends_read--;
1540                         as->suspends_pending--;
1541                         suspends_pending--;
1542                 } else
1543                         queue_event(APM_USER_SUSPEND, as);
1544                 if (suspends_pending <= 0) {
1545                         return suspend(1);
1546                 } else {
1547                         as->suspend_wait = 1;
1548                         wait_event_interruptible(apm_suspend_waitqueue,
1549                                         as->suspend_wait == 0);
1550                         return as->suspend_result;
1551                 }
1552                 break;
1553         default:
1554                 return -EINVAL;
1555         }
1556         return 0;
1557 }
1558
1559 static int do_release(struct inode * inode, struct file * filp)
1560 {
1561         struct apm_user *       as;
1562
1563         as = filp->private_data;
1564         if (check_apm_user(as, "release"))
1565                 return 0;
1566         filp->private_data = NULL;
1567         if (as->standbys_pending > 0) {
1568                 standbys_pending -= as->standbys_pending;
1569                 if (standbys_pending <= 0)
1570                         standby();
1571         }
1572         if (as->suspends_pending > 0) {
1573                 suspends_pending -= as->suspends_pending;
1574                 if (suspends_pending <= 0)
1575                         (void) suspend(1);
1576         }
1577         spin_lock(&user_list_lock);
1578         if (user_list == as)
1579                 user_list = as->next;
1580         else {
1581                 struct apm_user *       as1;
1582
1583                 for (as1 = user_list;
1584                      (as1 != NULL) && (as1->next != as);
1585                      as1 = as1->next)
1586                         ;
1587                 if (as1 == NULL)
1588                         printk(KERN_ERR "apm: filp not in user list\n");
1589                 else
1590                         as1->next = as->next;
1591         }
1592         spin_unlock(&user_list_lock);
1593         kfree(as);
1594         return 0;
1595 }
1596
1597 static int do_open(struct inode * inode, struct file * filp)
1598 {
1599         struct apm_user *       as;
1600
1601         as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
1602         if (as == NULL) {
1603                 printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
1604                        sizeof(*as));
1605                 return -ENOMEM;
1606         }
1607         as->magic = APM_BIOS_MAGIC;
1608         as->event_tail = as->event_head = 0;
1609         as->suspends_pending = as->standbys_pending = 0;
1610         as->suspends_read = as->standbys_read = 0;
1611         /*
1612          * XXX - this is a tiny bit broken, when we consider BSD
1613          * process accounting. If the device is opened by root, we
1614          * instantly flag that we used superuser privs. Who knows,
1615          * we might close the device immediately without doing a
1616          * privileged operation -- cevans
1617          */
1618         as->suser = capable(CAP_SYS_ADMIN);
1619         as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
1620         as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
1621         spin_lock(&user_list_lock);
1622         as->next = user_list;
1623         user_list = as;
1624         spin_unlock(&user_list_lock);
1625         filp->private_data = as;
1626         return 0;
1627 }
1628
1629 static int apm_get_info(char *buf, char **start, off_t fpos, int length)
1630 {
1631         char *          p;
1632         unsigned short  bx;
1633         unsigned short  cx;
1634         unsigned short  dx;
1635         int             error;
1636         unsigned short  ac_line_status = 0xff;
1637         unsigned short  battery_status = 0xff;
1638         unsigned short  battery_flag   = 0xff;
1639         int             percentage     = -1;
1640         int             time_units     = -1;
1641         char            *units         = "?";
1642
1643         p = buf;
1644
1645         if ((num_online_cpus() == 1) &&
1646             !(error = apm_get_power_status(&bx, &cx, &dx))) {
1647                 ac_line_status = (bx >> 8) & 0xff;
1648                 battery_status = bx & 0xff;
1649                 if ((cx & 0xff) != 0xff)
1650                         percentage = cx & 0xff;
1651
1652                 if (apm_info.connection_version > 0x100) {
1653                         battery_flag = (cx >> 8) & 0xff;
1654                         if (dx != 0xffff) {
1655                                 units = (dx & 0x8000) ? "min" : "sec";
1656                                 time_units = dx & 0x7fff;
1657                         }
1658                 }
1659         }
1660         /* Arguments, with symbols from linux/apm_bios.h.  Information is
1661            from the Get Power Status (0x0a) call unless otherwise noted.
1662
1663            0) Linux driver version (this will change if format changes)
1664            1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
1665            2) APM flags from APM Installation Check (0x00):
1666               bit 0: APM_16_BIT_SUPPORT
1667               bit 1: APM_32_BIT_SUPPORT
1668               bit 2: APM_IDLE_SLOWS_CLOCK
1669               bit 3: APM_BIOS_DISABLED
1670               bit 4: APM_BIOS_DISENGAGED
1671            3) AC line status
1672               0x00: Off-line
1673               0x01: On-line
1674               0x02: On backup power (BIOS >= 1.1 only)
1675               0xff: Unknown
1676            4) Battery status
1677               0x00: High
1678               0x01: Low
1679               0x02: Critical
1680               0x03: Charging
1681               0x04: Selected battery not present (BIOS >= 1.2 only)
1682               0xff: Unknown
1683            5) Battery flag
1684               bit 0: High
1685               bit 1: Low
1686               bit 2: Critical
1687               bit 3: Charging
1688               bit 7: No system battery
1689               0xff: Unknown
1690            6) Remaining battery life (percentage of charge):
1691               0-100: valid
1692               -1: Unknown
1693            7) Remaining battery life (time units):
1694               Number of remaining minutes or seconds
1695               -1: Unknown
1696            8) min = minutes; sec = seconds */
1697
1698         p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
1699                      driver_version,
1700                      (apm_info.bios.version >> 8) & 0xff,
1701                      apm_info.bios.version & 0xff,
1702                      apm_info.bios.flags,
1703                      ac_line_status,
1704                      battery_status,
1705                      battery_flag,
1706                      percentage,
1707                      time_units,
1708                      units);
1709
1710         return p - buf;
1711 }
1712
1713 static int apm(void *unused)
1714 {
1715         unsigned short  bx;
1716         unsigned short  cx;
1717         unsigned short  dx;
1718         int             error;
1719         char *          power_stat;
1720         char *          bat_stat;
1721
1722         kapmd_running = 1;
1723
1724         daemonize("kapmd");
1725
1726         current->flags |= PF_NOFREEZE;
1727
1728 #ifdef CONFIG_SMP
1729         /* 2002/08/01 - WT
1730          * This is to avoid random crashes at boot time during initialization
1731          * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D.
1732          * Some bioses don't like being called from CPU != 0.
1733          * Method suggested by Ingo Molnar.
1734          */
1735         set_cpus_allowed(current, cpumask_of_cpu(0));
1736         BUG_ON(smp_processor_id() != 0);
1737 #endif
1738
1739         if (apm_info.connection_version == 0) {
1740                 apm_info.connection_version = apm_info.bios.version;
1741                 if (apm_info.connection_version > 0x100) {
1742                         /*
1743                          * We only support BIOSs up to version 1.2
1744                          */
1745                         if (apm_info.connection_version > 0x0102)
1746                                 apm_info.connection_version = 0x0102;
1747                         error = apm_driver_version(&apm_info.connection_version);
1748                         if (error != APM_SUCCESS) {
1749                                 apm_error("driver version", error);
1750                                 /* Fall back to an APM 1.0 connection. */
1751                                 apm_info.connection_version = 0x100;
1752                         }
1753                 }
1754         }
1755
1756         if (debug)
1757                 printk(KERN_INFO "apm: Connection version %d.%d\n",
1758                         (apm_info.connection_version >> 8) & 0xff,
1759                         apm_info.connection_version & 0xff);
1760
1761 #ifdef CONFIG_APM_DO_ENABLE
1762         if (apm_info.bios.flags & APM_BIOS_DISABLED) {
1763                 /*
1764                  * This call causes my NEC UltraLite Versa 33/C to hang if it
1765                  * is booted with PM disabled but not in the docking station.
1766                  * Unfortunate ...
1767                  */
1768                 error = apm_enable_power_management(1);
1769                 if (error) {
1770                         apm_error("enable power management", error);
1771                         return -1;
1772                 }
1773         }
1774 #endif
1775
1776         if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
1777             && (apm_info.connection_version > 0x0100)) {
1778                 error = apm_engage_power_management(APM_DEVICE_ALL, 1);
1779                 if (error) {
1780                         apm_error("engage power management", error);
1781                         return -1;
1782                 }
1783         }
1784
1785         if (debug && (num_online_cpus() == 1 || smp )) {
1786                 error = apm_get_power_status(&bx, &cx, &dx);
1787                 if (error)
1788                         printk(KERN_INFO "apm: power status not available\n");
1789                 else {
1790                         switch ((bx >> 8) & 0xff) {
1791                         case 0: power_stat = "off line"; break;
1792                         case 1: power_stat = "on line"; break;
1793                         case 2: power_stat = "on backup power"; break;
1794                         default: power_stat = "unknown"; break;
1795                         }
1796                         switch (bx & 0xff) {
1797                         case 0: bat_stat = "high"; break;
1798                         case 1: bat_stat = "low"; break;
1799                         case 2: bat_stat = "critical"; break;
1800                         case 3: bat_stat = "charging"; break;
1801                         default: bat_stat = "unknown"; break;
1802                         }
1803                         printk(KERN_INFO
1804                                "apm: AC %s, battery status %s, battery life ",
1805                                power_stat, bat_stat);
1806                         if ((cx & 0xff) == 0xff)
1807                                 printk("unknown\n");
1808                         else
1809                                 printk("%d%%\n", cx & 0xff);
1810                         if (apm_info.connection_version > 0x100) {
1811                                 printk(KERN_INFO
1812                                        "apm: battery flag 0x%02x, battery life ",
1813                                        (cx >> 8) & 0xff);
1814                                 if (dx == 0xffff)
1815                                         printk("unknown\n");
1816                                 else
1817                                         printk("%d %s\n", dx & 0x7fff,
1818                                                 (dx & 0x8000) ?
1819                                                 "minutes" : "seconds");
1820                         }
1821                 }
1822         }
1823
1824         /* Install our power off handler.. */
1825         if (power_off)
1826                 pm_power_off = apm_power_off;
1827
1828         if (num_online_cpus() == 1 || smp) {
1829 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1830                 console_blank_hook = apm_console_blank;
1831 #endif
1832                 apm_mainloop();
1833 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
1834                 console_blank_hook = NULL;
1835 #endif
1836         }
1837         kapmd_running = 0;
1838
1839         return 0;
1840 }
1841
1842 #ifndef MODULE
1843 static int __init apm_setup(char *str)
1844 {
1845         int     invert;
1846
1847         while ((str != NULL) && (*str != '\0')) {
1848                 if (strncmp(str, "off", 3) == 0)
1849                         apm_disabled = 1;
1850                 if (strncmp(str, "on", 2) == 0)
1851                         apm_disabled = 0;
1852                 if ((strncmp(str, "bounce-interval=", 16) == 0) ||
1853                     (strncmp(str, "bounce_interval=", 16) == 0))
1854                         bounce_interval = simple_strtol(str + 16, NULL, 0);
1855                 if ((strncmp(str, "idle-threshold=", 15) == 0) ||
1856                     (strncmp(str, "idle_threshold=", 15) == 0))
1857                         idle_threshold = simple_strtol(str + 15, NULL, 0);
1858                 if ((strncmp(str, "idle-period=", 12) == 0) ||
1859                     (strncmp(str, "idle_period=", 12) == 0))
1860                         idle_period = simple_strtol(str + 12, NULL, 0);
1861                 invert = (strncmp(str, "no-", 3) == 0) ||
1862                         (strncmp(str, "no_", 3) == 0);
1863                 if (invert)
1864                         str += 3;
1865                 if (strncmp(str, "debug", 5) == 0)
1866                         debug = !invert;
1867                 if ((strncmp(str, "power-off", 9) == 0) ||
1868                     (strncmp(str, "power_off", 9) == 0))
1869                         power_off = !invert;
1870                 if (strncmp(str, "smp", 3) == 0)
1871                 {
1872                         smp = !invert;
1873                         idle_threshold = 100;
1874                 }
1875                 if ((strncmp(str, "allow-ints", 10) == 0) ||
1876                     (strncmp(str, "allow_ints", 10) == 0))
1877                         apm_info.allow_ints = !invert;
1878                 if ((strncmp(str, "broken-psr", 10) == 0) ||
1879                     (strncmp(str, "broken_psr", 10) == 0))
1880                         apm_info.get_power_status_broken = !invert;
1881                 if ((strncmp(str, "realmode-power-off", 18) == 0) ||
1882                     (strncmp(str, "realmode_power_off", 18) == 0))
1883                         apm_info.realmode_power_off = !invert;
1884                 str = strchr(str, ',');
1885                 if (str != NULL)
1886                         str += strspn(str, ", \t");
1887         }
1888         return 1;
1889 }
1890
1891 __setup("apm=", apm_setup);
1892 #endif
1893
1894 static struct file_operations apm_bios_fops = {
1895         .owner          = THIS_MODULE,
1896         .read           = do_read,
1897         .poll           = do_poll,
1898         .ioctl          = do_ioctl,
1899         .open           = do_open,
1900         .release        = do_release,
1901 };
1902
1903 static struct miscdevice apm_device = {
1904         APM_MINOR_DEV,
1905         "apm_bios",
1906         &apm_bios_fops
1907 };
1908
1909
1910 /* Simple "print if true" callback */
1911 static int __init print_if_true(struct dmi_system_id *d)
1912 {
1913         printk("%s\n", d->ident);
1914         return 0;
1915 }
1916
1917 /*
1918  * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
1919  * disabled before the suspend. Linux used to get terribly confused by that.
1920  */
1921 static int __init broken_ps2_resume(struct dmi_system_id *d)
1922 {
1923         printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround hopefully not needed.\n", d->ident);
1924         return 0;
1925 }
1926
1927 /* Some bioses have a broken protected mode poweroff and need to use realmode */
1928 static int __init set_realmode_power_off(struct dmi_system_id *d)
1929 {
1930         if (apm_info.realmode_power_off == 0) {
1931                 apm_info.realmode_power_off = 1;
1932                 printk(KERN_INFO "%s bios detected. Using realmode poweroff only.\n", d->ident);
1933         }
1934         return 0;
1935 }
1936
1937 /* Some laptops require interrupts to be enabled during APM calls */
1938 static int __init set_apm_ints(struct dmi_system_id *d)
1939 {
1940         if (apm_info.allow_ints == 0) {
1941                 apm_info.allow_ints = 1;
1942                 printk(KERN_INFO "%s machine detected. Enabling interrupts during APM calls.\n", d->ident);
1943         }
1944         return 0;
1945 }
1946
1947 /* Some APM bioses corrupt memory or just plain do not work */
1948 static int __init apm_is_horked(struct dmi_system_id *d)
1949 {
1950         if (apm_info.disabled == 0) {
1951                 apm_info.disabled = 1;
1952                 printk(KERN_INFO "%s machine detected. Disabling APM.\n", d->ident);
1953         }
1954         return 0;
1955 }
1956
1957 static int __init apm_is_horked_d850md(struct dmi_system_id *d)
1958 {
1959         if (apm_info.disabled == 0) {
1960                 apm_info.disabled = 1;
1961                 printk(KERN_INFO "%s machine detected. Disabling APM.\n", d->ident);
1962                 printk(KERN_INFO "This bug is fixed in bios P15 which is available for \n");
1963                 printk(KERN_INFO "download from support.intel.com \n");
1964         }
1965         return 0;
1966 }
1967
1968 /* Some APM bioses hang on APM idle calls */
1969 static int __init apm_likes_to_melt(struct dmi_system_id *d)
1970 {
1971         if (apm_info.forbid_idle == 0) {
1972                 apm_info.forbid_idle = 1;
1973                 printk(KERN_INFO "%s machine detected. Disabling APM idle calls.\n", d->ident);
1974         }
1975         return 0;
1976 }
1977
1978 /*
1979  *  Check for clue free BIOS implementations who use
1980  *  the following QA technique
1981  *
1982  *      [ Write BIOS Code ]<------
1983  *               |                ^
1984  *      < Does it Compile >----N--
1985  *               |Y               ^
1986  *      < Does it Boot Win98 >-N--
1987  *               |Y
1988  *           [Ship It]
1989  *
1990  *      Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
1991  *      Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
1992  */
1993 static int __init broken_apm_power(struct dmi_system_id *d)
1994 {
1995         apm_info.get_power_status_broken = 1;
1996         printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
1997         return 0;
1998 }
1999
2000 /*
2001  * This bios swaps the APM minute reporting bytes over (Many sony laptops
2002  * have this problem).
2003  */
2004 static int __init swab_apm_power_in_minutes(struct dmi_system_id *d)
2005 {
2006         apm_info.get_power_status_swabinminutes = 1;
2007         printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n");
2008         return 0;
2009 }
2010
2011 static struct dmi_system_id __initdata apm_dmi_table[] = {
2012         {
2013                 print_if_true,
2014                 KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.",
2015                 {       DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
2016                         DMI_MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"), },
2017         },
2018         {       /* Handle problems with APM on the C600 */
2019                 broken_ps2_resume, "Dell Latitude C600",
2020                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
2021                         DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C600"), },
2022         },
2023         {       /* Allow interrupts during suspend on Dell Latitude laptops*/
2024                 set_apm_ints, "Dell Latitude",
2025                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2026                         DMI_MATCH(DMI_PRODUCT_NAME, "Latitude C510"), }
2027         },
2028         {       /* APM crashes */
2029                 apm_is_horked, "Dell Inspiron 2500",
2030                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2031                         DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2032                         DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
2033                         DMI_MATCH(DMI_BIOS_VERSION,"A11"), },
2034         },
2035         {       /* Allow interrupts during suspend on Dell Inspiron laptops*/
2036                 set_apm_ints, "Dell Inspiron", {
2037                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2038                         DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"), },
2039         },
2040         {       /* Handle problems with APM on Inspiron 5000e */
2041                 broken_apm_power, "Dell Inspiron 5000e",
2042                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2043                         DMI_MATCH(DMI_BIOS_VERSION, "A04"),
2044                         DMI_MATCH(DMI_BIOS_DATE, "08/24/2000"), },
2045         },
2046         {       /* Handle problems with APM on Inspiron 2500 */
2047                 broken_apm_power, "Dell Inspiron 2500",
2048                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2049                         DMI_MATCH(DMI_BIOS_VERSION, "A12"),
2050                         DMI_MATCH(DMI_BIOS_DATE, "02/04/2002"), },
2051         },
2052         {       /* APM crashes */
2053                 apm_is_horked, "Dell Dimension 4100",
2054                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2055                         DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
2056                         DMI_MATCH(DMI_BIOS_VENDOR,"Intel Corp."),
2057                         DMI_MATCH(DMI_BIOS_VERSION,"A11"), },
2058         },
2059         {       /* Allow interrupts during suspend on Compaq Laptops*/
2060                 set_apm_ints, "Compaq 12XL125",
2061                 {       DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
2062                         DMI_MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
2063                         DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2064                         DMI_MATCH(DMI_BIOS_VERSION,"4.06"), },
2065         },
2066         {       /* Allow interrupts during APM or the clock goes slow */
2067                 set_apm_ints, "ASUSTeK",
2068                 {       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
2069                         DMI_MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"), },
2070         },
2071         {       /* APM blows on shutdown */
2072                 apm_is_horked, "ABIT KX7-333[R]",
2073                 {       DMI_MATCH(DMI_BOARD_VENDOR, "ABIT"),
2074                         DMI_MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"), },
2075         },
2076         {       /* APM crashes */
2077                 apm_is_horked, "Trigem Delhi3",
2078                 {       DMI_MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
2079                         DMI_MATCH(DMI_PRODUCT_NAME, "Delhi3"), },
2080         },
2081         {       /* APM crashes */
2082                 apm_is_horked, "Fujitsu-Siemens",
2083                 {       DMI_MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
2084                         DMI_MATCH(DMI_BIOS_VERSION, "Version1.01"), },
2085         },
2086         {       /* APM crashes */
2087                 apm_is_horked_d850md, "Intel D850MD",
2088                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2089                         DMI_MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"), },
2090         },
2091         {       /* APM crashes */
2092                 apm_is_horked, "Intel D810EMO",
2093                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2094                         DMI_MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"), },
2095         },
2096         {       /* APM crashes */
2097                 apm_is_horked, "Dell XPS-Z",
2098                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
2099                         DMI_MATCH(DMI_BIOS_VERSION, "A11"),
2100                         DMI_MATCH(DMI_PRODUCT_NAME, "XPS-Z"), },
2101         },
2102         {       /* APM crashes */
2103                 apm_is_horked, "Sharp PC-PJ/AX",
2104                 {       DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
2105                         DMI_MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
2106                         DMI_MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
2107                         DMI_MATCH(DMI_BIOS_VERSION,"Version R2.08"), },
2108         },
2109         {       /* APM crashes */
2110                 apm_is_horked, "Dell Inspiron 2500",
2111                 {       DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
2112                         DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
2113                         DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
2114                         DMI_MATCH(DMI_BIOS_VERSION,"A11"), },
2115         },
2116         {       /* APM idle hangs */
2117                 apm_likes_to_melt, "Jabil AMD",
2118                 {       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2119                         DMI_MATCH(DMI_BIOS_VERSION, "0AASNP06"), },
2120         },
2121         {       /* APM idle hangs */
2122                 apm_likes_to_melt, "AMI Bios",
2123                 {       DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
2124                         DMI_MATCH(DMI_BIOS_VERSION, "0AASNP05"), },
2125         },
2126         {       /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
2127                 swab_apm_power_in_minutes, "Sony VAIO",
2128                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2129                         DMI_MATCH(DMI_BIOS_VERSION, "R0206H"),
2130                         DMI_MATCH(DMI_BIOS_DATE, "08/23/99"), },
2131         },
2132         {       /* Handle problems with APM on Sony Vaio PCG-N505VX */
2133                 swab_apm_power_in_minutes, "Sony VAIO",
2134                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2135                         DMI_MATCH(DMI_BIOS_VERSION, "W2K06H0"),
2136                         DMI_MATCH(DMI_BIOS_DATE, "02/03/00"), },
2137         },
2138         {       /* Handle problems with APM on Sony Vaio PCG-XG29 */
2139                 swab_apm_power_in_minutes, "Sony VAIO",
2140                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2141                         DMI_MATCH(DMI_BIOS_VERSION, "R0117A0"),
2142                         DMI_MATCH(DMI_BIOS_DATE, "04/25/00"), },
2143         },
2144         {       /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2145                 swab_apm_power_in_minutes, "Sony VAIO",
2146                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2147                         DMI_MATCH(DMI_BIOS_VERSION, "R0121Z1"),
2148                         DMI_MATCH(DMI_BIOS_DATE, "05/11/00"), },
2149         },
2150         {       /* Handle problems with APM on Sony Vaio PCG-Z600NE */
2151                 swab_apm_power_in_minutes, "Sony VAIO",
2152                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2153                         DMI_MATCH(DMI_BIOS_VERSION, "WME01Z1"),
2154                         DMI_MATCH(DMI_BIOS_DATE, "08/11/00"), },
2155         },
2156         {       /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
2157                 swab_apm_power_in_minutes, "Sony VAIO",
2158                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2159                         DMI_MATCH(DMI_BIOS_VERSION, "R0206Z3"),
2160                         DMI_MATCH(DMI_BIOS_DATE, "12/25/00"), },
2161         },
2162         {       /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2163                 swab_apm_power_in_minutes, "Sony VAIO",
2164                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2165                         DMI_MATCH(DMI_BIOS_VERSION, "R0203D0"),
2166                         DMI_MATCH(DMI_BIOS_DATE, "05/12/00"), },
2167         },
2168         {       /* Handle problems with APM on Sony Vaio PCG-Z505LS */
2169                 swab_apm_power_in_minutes, "Sony VAIO",
2170                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2171                         DMI_MATCH(DMI_BIOS_VERSION, "R0203Z3"),
2172                         DMI_MATCH(DMI_BIOS_DATE, "08/25/00"), },
2173         },
2174         {       /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
2175                 swab_apm_power_in_minutes, "Sony VAIO",
2176                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2177                         DMI_MATCH(DMI_BIOS_VERSION, "R0209Z3"),
2178                         DMI_MATCH(DMI_BIOS_DATE, "05/12/01"), },
2179         },
2180         {       /* Handle problems with APM on Sony Vaio PCG-F104K */
2181                 swab_apm_power_in_minutes, "Sony VAIO",
2182                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2183                         DMI_MATCH(DMI_BIOS_VERSION, "R0204K2"),
2184                         DMI_MATCH(DMI_BIOS_DATE, "08/28/00"), },
2185         },
2186
2187         {       /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
2188                 swab_apm_power_in_minutes, "Sony VAIO",
2189                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2190                         DMI_MATCH(DMI_BIOS_VERSION, "R0208P1"),
2191                         DMI_MATCH(DMI_BIOS_DATE, "11/09/00"), },
2192         },
2193         {       /* Handle problems with APM on Sony Vaio PCG-C1VE */
2194                 swab_apm_power_in_minutes, "Sony VAIO",
2195                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2196                         DMI_MATCH(DMI_BIOS_VERSION, "R0204P1"),
2197                         DMI_MATCH(DMI_BIOS_DATE, "09/12/00"), },
2198         },
2199         {       /* Handle problems with APM on Sony Vaio PCG-C1VE */
2200                 swab_apm_power_in_minutes, "Sony VAIO",
2201                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
2202                         DMI_MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
2203                         DMI_MATCH(DMI_BIOS_DATE, "10/26/01"), },
2204         },
2205         {       /* broken PM poweroff bios */
2206                 set_realmode_power_off, "Award Software v4.60 PGMA",
2207                 {       DMI_MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
2208                         DMI_MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
2209                         DMI_MATCH(DMI_BIOS_DATE, "134526184"), },
2210         },
2211
2212         /* Generic per vendor APM settings  */
2213
2214         {       /* Allow interrupts during suspend on IBM laptops */
2215                 set_apm_ints, "IBM",
2216                 {       DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
2217         },
2218
2219         { }
2220 };
2221
2222 /*
2223  * Just start the APM thread. We do NOT want to do APM BIOS
2224  * calls from anything but the APM thread, if for no other reason
2225  * than the fact that we don't trust the APM BIOS. This way,
2226  * most common APM BIOS problems that lead to protection errors
2227  * etc will have at least some level of being contained...
2228  *
2229  * In short, if something bad happens, at least we have a choice
2230  * of just killing the apm thread..
2231  */
2232 static int __init apm_init(void)
2233 {
2234         struct proc_dir_entry *apm_proc;
2235         int ret;
2236         int i;
2237
2238         dmi_check_system(apm_dmi_table);
2239
2240         if (apm_info.bios.version == 0) {
2241                 printk(KERN_INFO "apm: BIOS not found.\n");
2242                 return -ENODEV;
2243         }
2244         printk(KERN_INFO
2245                 "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
2246                 ((apm_info.bios.version >> 8) & 0xff),
2247                 (apm_info.bios.version & 0xff),
2248                 apm_info.bios.flags,
2249                 driver_version);
2250         if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
2251                 printk(KERN_INFO "apm: no 32 bit BIOS support\n");
2252                 return -ENODEV;
2253         }
2254
2255         if (allow_ints)
2256                 apm_info.allow_ints = 1;
2257         if (broken_psr)
2258                 apm_info.get_power_status_broken = 1;
2259         if (realmode_power_off)
2260                 apm_info.realmode_power_off = 1;
2261         /* User can override, but default is to trust DMI */
2262         if (apm_disabled != -1)
2263                 apm_info.disabled = apm_disabled;
2264
2265         /*
2266          * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
2267          * but is reportedly a 1.0 BIOS.
2268          */
2269         if (apm_info.bios.version == 0x001)
2270                 apm_info.bios.version = 0x100;
2271
2272         /* BIOS < 1.2 doesn't set cseg_16_len */
2273         if (apm_info.bios.version < 0x102)
2274                 apm_info.bios.cseg_16_len = 0; /* 64k */
2275
2276         if (debug) {
2277                 printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x",
2278                         apm_info.bios.cseg, apm_info.bios.offset,
2279                         apm_info.bios.cseg_16, apm_info.bios.dseg);
2280                 if (apm_info.bios.version > 0x100)
2281                         printk(" cseg len %x, dseg len %x",
2282                                 apm_info.bios.cseg_len,
2283                                 apm_info.bios.dseg_len);
2284                 if (apm_info.bios.version > 0x101)
2285                         printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
2286                 printk("\n");
2287         }
2288
2289         if (apm_info.disabled) {
2290                 printk(KERN_NOTICE "apm: disabled on user request.\n");
2291                 return -ENODEV;
2292         }
2293         if ((num_online_cpus() > 1) && !power_off && !smp) {
2294                 printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
2295                 apm_info.disabled = 1;
2296                 return -ENODEV;
2297         }
2298         if (PM_IS_ACTIVE()) {
2299                 printk(KERN_NOTICE "apm: overridden by ACPI.\n");
2300                 apm_info.disabled = 1;
2301                 return -ENODEV;
2302         }
2303         pm_active = 1;
2304
2305         /*
2306          * Set up a segment that references the real mode segment 0x40
2307          * that extends up to the end of page zero (that we have reserved).
2308          * This is for buggy BIOS's that refer to (real mode) segment 0x40
2309          * even though they are called in protected mode.
2310          */
2311         set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
2312         _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
2313
2314         apm_bios_entry.offset = apm_info.bios.offset;
2315         apm_bios_entry.segment = APM_CS;
2316
2317         for (i = 0; i < NR_CPUS; i++) {
2318                 struct desc_struct *gdt = get_cpu_gdt_table(i);
2319                 set_base(gdt[APM_CS >> 3],
2320                          __va((unsigned long)apm_info.bios.cseg << 4));
2321                 set_base(gdt[APM_CS_16 >> 3],
2322                          __va((unsigned long)apm_info.bios.cseg_16 << 4));
2323                 set_base(gdt[APM_DS >> 3],
2324                          __va((unsigned long)apm_info.bios.dseg << 4));
2325 #ifndef APM_RELAX_SEGMENTS
2326                 if (apm_info.bios.version == 0x100) {
2327 #endif
2328                         /* For ASUS motherboard, Award BIOS rev 110 (and others?) */
2329                         _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
2330                         /* For some unknown machine. */
2331                         _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
2332                         /* For the DEC Hinote Ultra CT475 (and others?) */
2333                         _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
2334 #ifndef APM_RELAX_SEGMENTS
2335                 } else {
2336                         _set_limit((char *)&gdt[APM_CS >> 3],
2337                                 (apm_info.bios.cseg_len - 1) & 0xffff);
2338                         _set_limit((char *)&gdt[APM_CS_16 >> 3],
2339                                 (apm_info.bios.cseg_16_len - 1) & 0xffff);
2340                         _set_limit((char *)&gdt[APM_DS >> 3],
2341                                 (apm_info.bios.dseg_len - 1) & 0xffff);
2342                       /* workaround for broken BIOSes */
2343                         if (apm_info.bios.cseg_len <= apm_info.bios.offset)
2344                                 _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1);
2345                        if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
2346                                 /* for the BIOS that assumes granularity = 1 */
2347                                 gdt[APM_DS >> 3].b |= 0x800000;
2348                                 printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
2349                         }
2350                 }
2351 #endif
2352         }
2353
2354         apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
2355         if (apm_proc)
2356                 apm_proc->owner = THIS_MODULE;
2357
2358         ret = kernel_thread(apm, NULL, CLONE_KERNEL | SIGCHLD);
2359         if (ret < 0) {
2360                 printk(KERN_ERR "apm: disabled - Unable to start kernel thread.\n");
2361                 return -ENOMEM;
2362         }
2363
2364         if (num_online_cpus() > 1 && !smp ) {
2365                 printk(KERN_NOTICE
2366                    "apm: disabled - APM is not SMP safe (power off active).\n");
2367                 return 0;
2368         }
2369
2370         misc_register(&apm_device);
2371
2372         if (HZ != 100)
2373                 idle_period = (idle_period * HZ) / 100;
2374         if (idle_threshold < 100) {
2375                 original_pm_idle = pm_idle;
2376                 pm_idle  = apm_cpu_idle;
2377                 set_pm_idle = 1;
2378         }
2379
2380         return 0;
2381 }
2382
2383 static void __exit apm_exit(void)
2384 {
2385         int     error;
2386
2387         if (set_pm_idle) {
2388                 pm_idle = original_pm_idle;
2389                 /*
2390                  * We are about to unload the current idle thread pm callback
2391                  * (pm_idle), Wait for all processors to update cached/local
2392                  * copies of pm_idle before proceeding.
2393                  */
2394                 cpu_idle_wait();
2395         }
2396         if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
2397             && (apm_info.connection_version > 0x0100)) {
2398                 error = apm_engage_power_management(APM_DEVICE_ALL, 0);
2399                 if (error)
2400                         apm_error("disengage power management", error);
2401         }
2402         misc_deregister(&apm_device);
2403         remove_proc_entry("apm", NULL);
2404         if (power_off)
2405                 pm_power_off = NULL;
2406         exit_kapmd = 1;
2407         while (kapmd_running)
2408                 schedule();
2409         pm_active = 0;
2410 }
2411
2412 module_init(apm_init);
2413 module_exit(apm_exit);
2414
2415 MODULE_AUTHOR("Stephen Rothwell");
2416 MODULE_DESCRIPTION("Advanced Power Management");
2417 MODULE_LICENSE("GPL");
2418 module_param(debug, bool, 0644);
2419 MODULE_PARM_DESC(debug, "Enable debug mode");
2420 module_param(power_off, bool, 0444);
2421 MODULE_PARM_DESC(power_off, "Enable power off");
2422 module_param(bounce_interval, int, 0444);
2423 MODULE_PARM_DESC(bounce_interval,
2424                 "Set the number of ticks to ignore suspend bounces");
2425 module_param(allow_ints, bool, 0444);
2426 MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
2427 module_param(broken_psr, bool, 0444);
2428 MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
2429 module_param(realmode_power_off, bool, 0444);
2430 MODULE_PARM_DESC(realmode_power_off,
2431                 "Switch to real mode before powering off");
2432 module_param(idle_threshold, int, 0444);
2433 MODULE_PARM_DESC(idle_threshold,
2434         "System idle percentage above which to make APM BIOS idle calls");
2435 module_param(idle_period, int, 0444);
2436 MODULE_PARM_DESC(idle_period,
2437         "Period (in sec/100) over which to caculate the idle percentage");
2438 module_param(smp, bool, 0444);
2439 MODULE_PARM_DESC(smp,
2440         "Set this to enable APM use on an SMP platform. Use with caution on older systems");
2441 MODULE_ALIAS_MISCDEV(APM_MINOR_DEV);