2 * APM BIOS driver for Linux
3 * Copyright 1994-1998 Stephen Rothwell
4 * (Stephen.Rothwell@canb.auug.org.au)
5 * Development of this driver was funded by NEC Australia P/L
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
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.
18 * October 1995, Rik Faith (faith@cs.unc.edu):
19 * Minor enhancements and updates (to the patch set) for 1.3.x
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 (Stephen.Rothwell@canb.auug.org.au)
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
38 * 0.6b: first version in official kernel, Linux 1.3.46
39 * 0.7: changed /proc/apm format, Linux 1.3.58
40 * 0.8: fixed gcc 2.7.[12] compilation problems, Linux 1.3.59
41 * 0.9: only call bios if bios is present, Linux 1.3.72
42 * 1.0: use fixed device number, consolidate /proc/apm into this file,
44 * 1.1: support user-space standby and suspend, power off after system
45 * halted, Linux 1.3.98
46 * 1.2: When resetting RTC after resume, take care so that the time
47 * is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
48 * <jtoth@princeton.edu>); improve interaction between
49 * screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
50 * 1.2a:Simple change to stop mysterious bug reports with SMP also added
51 * levels to the printk calls. APM is not defined for SMP machines.
52 * The new replacment for it is, but Linux doesn't yet support this.
53 * Alan Cox Linux 2.1.55
54 * 1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
55 * 1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
56 * Dean Gaudet <dgaudet@arctic.org>.
57 * C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
58 * 1.5: Fix segment register reloading (in case of bad segments saved
61 * 1.6: Cope with complier/assembler differences.
62 * Only try to turn off the first display device.
63 * Fix OOPS at power off with no APM BIOS by Jan Echternach
64 * <echter@informatik.uni-rostock.de>
66 * 1.7: Modify driver's cached copy of the disabled/disengaged flags
67 * to reflect current state of APM BIOS.
68 * Chris Rankin <rankinc@bellsouth.net>
69 * Reset interrupt 0 timer to 100Hz after suspend
70 * Chad Miller <cmiller@surfsouth.com>
71 * Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE
72 * Richard Gooch <rgooch@atnf.csiro.au>
73 * Allow boot time disabling of APM
74 * Make boot messages far less verbose by default
77 * 1.8: Add CONFIG_APM_RTC_IS_GMT
78 * Richard Gooch <rgooch@atnf.csiro.au>
79 * change APM_NOINTS to CONFIG_APM_ALLOW_INTS
80 * remove dependency on CONFIG_PROC_FS
82 * 1.9: Fix small typo. <laslo@ilo.opole.pl>
83 * Try to cope with BIOS's that need to have all display
84 * devices blanked and not just the first one.
85 * Ross Paterson <ross@soi.city.ac.uk>
86 * Fix segment limit setting it has always been wrong as
87 * the segments needed to have byte granularity.
88 * Mark a few things __init.
89 * Add hack to allow power off of SMP systems by popular request.
90 * Use CONFIG_SMP instead of __SMP__
91 * Ignore BOUNCES for three seconds.
96 * Intel Corporation, Microsoft Corporation. Advanced Power Management
97 * (APM) BIOS Interface Specification, Revision 1.1, September 1993.
98 * Intel Order Number 241704-001. Microsoft Part Number 781-110-X01.
100 * [This document is available free from Intel by calling 800.628.8686 (fax
101 * 916.356.6100) or 800.548.4725; or via anonymous ftp from
102 * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc. It is also
103 * available from Microsoft by calling 206.882.8080.]
106 * Intel Corporation, Microsoft Corporation. Advanced Power Management
107 * (APM) BIOS Interface Specification, Revision 1.2, February 1996.
109 * [This document is available from Intel at:
110 * http://www.intel.com/IAL/powermgm
112 * http://www.microsoft.com/windows/thirdparty/hardware/pcfuture.htm
116 #include <linux/config.h>
117 #include <linux/module.h>
119 #include <linux/poll.h>
120 #include <linux/types.h>
121 #include <linux/stddef.h>
122 #include <linux/timer.h>
123 #include <linux/fcntl.h>
124 #include <linux/malloc.h>
125 #include <linux/linkage.h>
126 #include <linux/stat.h>
127 #include <linux/proc_fs.h>
128 #include <linux/miscdevice.h>
129 #include <linux/apm_bios.h>
130 #include <linux/init.h>
132 #include <asm/system.h>
133 #include <asm/uaccess.h>
134 #include <asm/desc.h>
136 EXPORT_SYMBOL(apm_register_callback
);
137 EXPORT_SYMBOL(apm_unregister_callback
);
139 extern unsigned long get_cmos_time(void);
142 * The apm_bios device is one of the misc char devices.
143 * This is its minor number.
145 #define APM_MINOR_DEV 134
147 /* Configurable options:
149 * CONFIG_APM_IGNORE_USER_SUSPEND: define to ignore USER SUSPEND requests.
150 * This is necessary on the NEC Versa M series, which generates these when
151 * resuming from SYSTEM SUSPEND. However, enabling this on other laptops
152 * will cause the laptop to generate a CRITICAL SUSPEND when an appropriate
153 * USER SUSPEND is ignored -- this may prevent the APM driver from updating
154 * the system time on a RESUME.
156 * CONFIG_APM_DO_ENABLE: enable APM features at boot time. From page 36 of
157 * the specification: "When disabled, the APM BIOS does not automatically
158 * power manage devices, enter the Standby State, enter the Suspend State,
159 * or take power saving steps in response to CPU Idle calls." This driver
160 * will make CPU Idle calls when Linux is idle (unless this feature is
161 * turned off -- see below). This should always save battery power, but
162 * more complicated APM features will be dependent on your BIOS
163 * implementation. You may need to turn this option off if your computer
164 * hangs at boot time when using APM support, or if it beeps continuously
165 * instead of suspending. Turn this off if you have a NEC UltraLite Versa
166 * 33/C or a Toshiba T400CDT. This is off by default since most machines
167 * do fine without this feature.
169 * CONFIG_APM_CPU_IDLE: enable calls to APM CPU Idle/CPU Busy inside the
170 * idle loop. On some machines, this can activate improved power savings,
171 * such as a slowed CPU clock rate, when the machine is idle. These idle
172 * call is made after the idle loop has run for some length of time (e.g.,
173 * 333 mS). On some machines, this will cause a hang at boot time or
174 * whenever the CPU becomes idle.
176 * CONFIG_APM_DISPLAY_BLANK: enable console blanking using the APM. Some
177 * laptops can use this to turn of the LCD backlight when the VC screen
178 * blanker blanks the screen. Note that this is only used by the VC screen
179 * blanker, and probably won't turn off the backlight when using X11. Some
180 * problems have been reported when using this option with gpm (if you'd
181 * like to debug this, please do so).
183 * CONFIG_APM_IGNORE_MULTIPLE_SUSPEND: The IBM TP560 bios seems to insist
184 * on returning multiple suspend/standby events whenever one occurs. We
185 * really only need one at a time, so just ignore any beyond the first.
186 * This is probably safe on most laptops.
188 * If you are debugging the APM support for your laptop, note that code for
189 * all of these options is contained in this file, so you can #define or
190 * #undef these on the next line to avoid recompiling the whole kernel.
194 /* KNOWN PROBLEM MACHINES:
196 * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
197 * [Confirmed by TI representative]
198 * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
199 * [Confirmed by BIOS disassembly]
200 * [This may work now ...]
201 * P: Toshiba 1950S: battery life information only gets updated after resume
202 * P: Midwest Micro Soundbook Elite DX2/66 monochrome: screen blanking
203 * broken in BIOS [Reported by Garst R. Reese <reese@isn.net>]
205 * Legend: U = unusable with APM patches
206 * P = partially usable with APM patches
210 * Define to have debug messages.
215 * Define to always call the APM BIOS busy routine even if the clock was
216 * not slowed by the idle routine.
218 #define ALWAYS_CALL_BUSY
221 * Define to make the APM BIOS calls zero all data segment registers (so
222 * that an incorrect BIOS implementation will cause a kernel panic if it
223 * tries to write to arbitrary memory).
225 #define APM_ZERO_SEGS
228 * Define to make all _set_limit calls use 64k limits. The APM 1.1 BIOS is
229 * supposed to provide limit information that it recognizes. Many machines
230 * do this correctly, but many others do not restrict themselves to their
231 * claimed limit. When this happens, they will cause a segmentation
232 * violation in the kernel at boot time. Most BIOS's, however, will
233 * respect a 64k limit, so we use that. If you want to be pedantic and
234 * hold your BIOS to its claims, then undefine this.
236 #define APM_RELAX_SEGMENTS
239 * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
240 * This patched by Chad Miller <cmiller@surfsouth.com>, orig code by David
241 * Chen <chen@ctpa04.mit.edu>
243 #undef INIT_TIMER_AFTER_SUSPEND
245 #ifdef INIT_TIMER_AFTER_SUSPEND
246 #include <linux/timex.h>
248 #include <linux/delay.h>
252 * Need to poll the APM BIOS every second
254 #define APM_CHECK_TIMEOUT (HZ)
257 * If CONFIG_APM_IGNORE_SUSPEND_BOUNCE is defined then
258 * ignore suspend events for this amount of time
260 #define BOUNCE_INTERVAL (3 * HZ)
263 * Save a segment register away
265 #define savesegment(seg, where) \
266 __asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where))
269 * Forward declarations
271 static void suspend(void);
272 static void standby(void);
273 static void set_time(void);
275 static void check_events(void);
277 static int do_open(struct inode
*, struct file
*);
278 static int do_release(struct inode
*, struct file
*);
279 static ssize_t
do_read(struct file
*, char *, size_t , loff_t
*);
280 static unsigned int do_poll(struct file
*, poll_table
*);
281 static int do_ioctl(struct inode
*, struct file
*, u_int
, u_long
);
283 static int apm_get_info(char *, char **, off_t
, int, int);
285 extern int apm_register_callback(int (*)(apm_event_t
));
286 extern void apm_unregister_callback(int (*)(apm_event_t
));
292 unsigned long offset
;
293 unsigned short segment
;
295 static int apm_enabled
= 0;
296 static int smp_hack
= 0;
297 #ifdef CONFIG_APM_CPU_IDLE
298 static int clock_slowed
= 0;
300 static int suspends_pending
= 0;
301 static int standbys_pending
= 0;
302 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
303 static int waiting_for_resume
= 0;
306 #ifdef CONFIG_APM_RTC_IS_GMT
307 # define clock_cmos_diff 0
308 # define got_clock_diff 1
310 static long clock_cmos_diff
;
311 static int got_clock_diff
= 0;
313 static int debug
= 0;
314 static int apm_disabled
= 0;
316 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue
);
317 static struct apm_bios_struct
* user_list
= NULL
;
319 static char driver_version
[] = "1.9"; /* no spaces */
322 static char * apm_event_name
[] = {
328 "power status change",
333 "system standby resume",
334 "capabilities change"
336 #define NR_APM_EVENT_NAME \
337 (sizeof(apm_event_name) / sizeof(apm_event_name[0]))
340 static struct file_operations apm_bios_fops
= {
355 static struct miscdevice apm_device
= {
361 typedef struct callback_list_t
{
362 int (* callback
)(apm_event_t
);
363 struct callback_list_t
* next
;
366 static callback_list_t
* callback_list
= NULL
;
368 typedef struct lookup_t
{
373 static const lookup_t error_table
[] = {
374 /* N/A { APM_SUCCESS, "Operation succeeded" }, */
375 { APM_DISABLED
, "Power management disabled" },
376 { APM_CONNECTED
, "Real mode interface already connected" },
377 { APM_NOT_CONNECTED
, "Interface not connected" },
378 { APM_16_CONNECTED
, "16 bit interface already connected" },
379 /* N/A { APM_16_UNSUPPORTED, "16 bit interface not supported" }, */
380 { APM_32_CONNECTED
, "32 bit interface already connected" },
381 { APM_32_UNSUPPORTED
, "32 bit interface not supported" },
382 { APM_BAD_DEVICE
, "Unrecognized device ID" },
383 { APM_BAD_PARAM
, "Parameter out of range" },
384 { APM_NOT_ENGAGED
, "Interface not engaged" },
385 { APM_BAD_FUNCTION
, "Function not supported" },
386 { APM_RESUME_DISABLED
, "Resume timer disabled" },
387 { APM_BAD_STATE
, "Unable to enter requested state" },
388 /* N/A { APM_NO_EVENTS, "No events pending" }, */
389 { APM_NOT_PRESENT
, "No APM present" }
391 #define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t))
394 * These are the actual BIOS calls. Depending on APM_ZERO_SEGS and
395 * CONFIG_APM_ALLOW_INTS, we are being really paranoid here! Not only
396 * are interrupts disabled, but all the segment registers (except SS)
397 * are saved and zeroed this means that if the BIOS tries to reference
398 * any data without explicitly loading the segment registers, the kernel
399 * will fault immediately rather than have some unforeseen circumstances
400 * for the rest of the kernel. And it will be very obvious! :-) Doing
401 * this depends on CS referring to the same physical memory as DS so that
402 * DS can be zeroed before the call. Unfortunately, we can't do anything
403 * about the stack segment/pointer. Also, we tell the compiler that
404 * everything could change.
406 * Also, we KNOW that for the non error case of apm_bios_call, there
407 * is no useful data returned in the low order 8 bits of eax.
409 #ifndef CONFIG_APM_ALLOW_INTS
410 # define APM_DO_CLI __cli()
415 # define APM_DO_SAVE_SEGS \
416 savesegment(fs, saved_fs); \
417 savesegment(gs, saved_gs)
418 # define APM_DO_ZERO_SEGS \
421 "xorl %%edx, %%edx\n\t" \
422 "mov %%dx, %%ds\n\t" \
423 "mov %%dx, %%es\n\t" \
424 "mov %%dx, %%fs\n\t" \
426 # define APM_DO_POP_SEGS \
429 # define APM_DO_RESTORE_SEGS \
430 loadsegment(fs, saved_fs); \
431 loadsegment(gs, saved_gs)
433 # define APM_DO_SAVE_SEGS
434 # define APM_DO_ZERO_SEGS
435 # define APM_DO_POP_SEGS
436 # define APM_DO_RESTORE_SEGS
439 static u8
apm_bios_call(u32 eax_in
, u32 ebx_in
, u32 ecx_in
,
440 u32
*eax
, u32
*ebx
, u32
*ecx
, u32
*edx
, u32
*esi
)
442 unsigned int saved_fs
;
443 unsigned int saved_gs
;
449 __asm__
__volatile__(APM_DO_ZERO_SEGS
452 "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry
) "\n\t"
457 : "=a" (*eax
), "=b" (*ebx
), "=c" (*ecx
), "=d" (*edx
),
459 : "a" (eax_in
), "b" (ebx_in
), "c" (ecx_in
)
462 __restore_flags(flags
);
467 * This version only returns one value (usually an error code)
470 static u8
apm_bios_call_simple(u32 eax_in
, u32 ebx_in
, u32 ecx_in
,
474 unsigned int saved_fs
;
475 unsigned int saved_gs
;
484 __asm__
__volatile__(APM_DO_ZERO_SEGS
487 "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry
) "\n\t"
492 : "=a" (*eax
), "=b" (error
), "=c" (cx
), "=d" (dx
),
494 : "a" (eax_in
), "b" (ebx_in
), "c" (ecx_in
)
498 __restore_flags(flags
);
502 static int apm_driver_version(u_short
*val
)
506 if (apm_bios_call_simple(0x530e, 0, *val
, &eax
))
507 return (eax
>> 8) & 0xff;
512 static int apm_get_event(apm_event_t
*event
, apm_eventinfo_t
*info
)
519 if (apm_bios_call(0x530b, 0, 0, &eax
, &ebx
, &ecx
, &dummy
, &dummy
))
520 return (eax
>> 8) & 0xff;
522 if (apm_bios_info
.version
< 0x0102)
523 *info
= ~0; /* indicate info not valid */
529 static int set_power_state(u_short what
, u_short state
)
533 if (apm_bios_call_simple(0x5307, what
, state
, &eax
))
534 return (eax
>> 8) & 0xff;
538 static int apm_set_power_state(u_short state
)
540 return set_power_state(0x0001, state
);
544 * If no process has been interested in this
545 * CPU for some time, we want to wake up the
546 * power management thread - we probably want
549 #define HARD_IDLE_TIMEOUT (HZ/3)
551 /* This should wake up kapmd and ask it to slow the CPU */
552 #define powermanagement_idle() do { } while (0)
554 extern int hlt_counter
;
557 * This is the idle thing.
559 void apm_cpu_idle(void)
561 unsigned int start_idle
;
563 start_idle
= jiffies
;
565 if (!current
->need_resched
) {
566 if (jiffies
- start_idle
< HARD_IDLE_TIMEOUT
) {
567 if (!current_cpu_data
.hlt_works_ok
)
571 asm volatile("sti ; hlt" : : : "memory");
576 * Ok, do some power management - we've been idle for too long
578 powermanagement_idle();
583 start_idle
= jiffies
;
587 void apm_power_off(void)
590 * smp_hack == 2 means that we would have enabled APM support
591 * except there is more than one processor and so most of
592 * the APM stuff is unsafe. We will still try power down
593 * because is is useful to some people and they know what
594 * they are doing because they booted with the smp-power-off
597 if (apm_enabled
|| (smp_hack
== 2))
598 (void) apm_set_power_state(APM_STATE_OFF
);
601 #ifdef CONFIG_APM_DISPLAY_BLANK
602 /* Called by apm_display_blank and apm_display_unblank when apm_enabled. */
603 static int apm_set_display_power_state(u_short state
)
607 /* Blank the first display device */
608 error
= set_power_state(0x0100, state
);
609 if (error
== APM_BAD_DEVICE
)
610 /* try to blank them all instead */
611 error
= set_power_state(0x01ff, state
);
616 #ifdef CONFIG_APM_DO_ENABLE
617 static int __init
apm_enable_power_management(void)
621 if (apm_bios_call_simple(0x5308,
622 (apm_bios_info
.version
> 0x100) ? 0x0001 : 0xffff,
624 return (eax
>> 8) & 0xff;
625 apm_bios_info
.flags
&= ~APM_BIOS_DISABLED
;
630 static int apm_get_power_status(u_short
*status
, u_short
*bat
, u_short
*life
)
638 if (apm_bios_call(0x530a, 1, 0, &eax
, &ebx
, &ecx
, &edx
, &dummy
))
639 return (eax
>> 8) & 0xff;
646 static int apm_get_battery_status(u_short which
, u_short
*status
,
647 u_short
*bat
, u_short
*life
, u_short
*nbat
)
655 if (apm_bios_info
.version
< 0x0102) {
656 /* pretend we only have one battery. */
658 return APM_BAD_DEVICE
;
660 return apm_get_power_status(status
, bat
, life
);
663 if (apm_bios_call(0x530a, (0x8000 | (which
)), 0, &eax
,
664 &ebx
, &ecx
, &edx
, &esi
))
665 return (eax
>> 8) & 0xff;
673 static int __init
apm_engage_power_management(u_short device
)
677 if (apm_bios_call_simple(0x530f, device
, 1, &eax
))
678 return (eax
>> 8) & 0xff;
682 static void apm_error(char *str
, int err
)
686 for (i
= 0; i
< ERROR_COUNT
; i
++)
687 if (error_table
[i
].key
== err
) break;
689 printk(KERN_NOTICE
"apm: %s: %s\n", str
, error_table
[i
].msg
);
691 printk(KERN_NOTICE
"apm: %s: unknown error code %#2.2x\n",
695 /* Called from console driver -- must make sure apm_enabled. */
696 int apm_display_blank(void)
698 #ifdef CONFIG_APM_DISPLAY_BLANK
703 error
= apm_set_display_power_state(APM_STATE_STANDBY
);
704 if (error
== APM_SUCCESS
)
706 apm_error("set display standby", error
);
711 /* Called from console driver -- must make sure apm_enabled. */
712 int apm_display_unblank(void)
714 #ifdef CONFIG_APM_DISPLAY_BLANK
719 error
= apm_set_display_power_state(APM_STATE_READY
);
720 if (error
== APM_SUCCESS
)
722 apm_error("set display ready", error
);
727 int apm_register_callback(int (*callback
)(apm_event_t
))
729 callback_list_t
* new;
731 new = kmalloc(sizeof(callback_list_t
), GFP_KERNEL
);
734 new->callback
= callback
;
735 new->next
= callback_list
;
740 void apm_unregister_callback(int (*callback
)(apm_event_t
))
742 callback_list_t
** ptr
;
743 callback_list_t
* old
;
745 for (ptr
= &callback_list
; *ptr
!= NULL
; ptr
= &(*ptr
)->next
)
746 if ((*ptr
)->callback
== callback
)
750 kfree_s(old
, sizeof(callback_list_t
));
753 static int queue_empty(struct apm_bios_struct
* as
)
755 return as
->event_head
== as
->event_tail
;
758 static apm_event_t
get_queued_event(struct apm_bios_struct
* as
)
760 as
->event_tail
= (as
->event_tail
+ 1) % APM_MAX_EVENTS
;
761 return as
->events
[as
->event_tail
];
764 static int queue_event(apm_event_t event
, struct apm_bios_struct
*sender
)
766 struct apm_bios_struct
* as
;
768 if (user_list
== NULL
)
770 for (as
= user_list
; as
!= NULL
; as
= as
->next
) {
773 as
->event_head
= (as
->event_head
+ 1) % APM_MAX_EVENTS
;
774 if (as
->event_head
== as
->event_tail
) {
778 printk(KERN_ERR
"apm: an event queue overflowed\n");
781 as
->event_tail
= (as
->event_tail
+ 1) % APM_MAX_EVENTS
;
783 as
->events
[as
->event_head
] = event
;
787 case APM_SYS_SUSPEND
:
788 case APM_USER_SUSPEND
:
789 as
->suspends_pending
++;
793 case APM_SYS_STANDBY
:
794 case APM_USER_STANDBY
:
795 as
->standbys_pending
++;
800 wake_up_interruptible(&apm_waitqueue
);
804 static void set_time(void)
808 if (!got_clock_diff
) /* Don't know time zone, can't set clock */
813 CURRENT_TIME
= get_cmos_time() + clock_cmos_diff
;
814 restore_flags(flags
);
817 static void suspend(void)
822 #ifndef CONFIG_APM_RTC_IS_GMT
824 * Estimate time zone so that set_time can update the clock
827 clock_cmos_diff
= -get_cmos_time();
829 clock_cmos_diff
+= CURRENT_TIME
;
831 restore_flags(flags
);
834 err
= apm_set_power_state(APM_STATE_SUSPEND
);
836 apm_error("suspend", err
);
837 #ifdef INIT_TIMER_AFTER_SUSPEND
840 /* set the clock to 100 Hz */
841 outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
843 outb_p(LATCH
& 0xff , 0x40); /* LSB */
845 outb(LATCH
>> 8 , 0x40); /* MSB */
847 restore_flags(flags
);
852 static void standby(void)
856 err
= apm_set_power_state(APM_STATE_STANDBY
);
858 apm_error("standby", err
);
861 static apm_event_t
get_event(void)
865 apm_eventinfo_t info
;
867 static int notified
= 0;
869 /* we don't use the eventinfo */
870 error
= apm_get_event(&event
, &info
);
871 if (error
== APM_SUCCESS
)
874 if ((error
!= APM_NO_EVENTS
) && (notified
++ == 0))
875 apm_error("get_event", error
);
880 static void send_event(apm_event_t event
, apm_event_t undo
,
881 struct apm_bios_struct
*sender
)
883 callback_list_t
* call
;
884 callback_list_t
* fix
;
886 for (call
= callback_list
; call
!= NULL
; call
= call
->next
) {
887 if (call
->callback(event
) && undo
) {
888 for (fix
= callback_list
; fix
!= call
; fix
= fix
->next
)
890 if (apm_bios_info
.version
> 0x100)
891 apm_set_power_state(APM_STATE_REJECT
);
896 queue_event(event
, sender
);
899 static void check_events(void)
902 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
903 static unsigned long last_resume
= 0;
904 static int ignore_bounce
= 0;
907 while ((event
= get_event()) != 0) {
909 if (event
<= NR_APM_EVENT_NAME
)
910 printk(KERN_DEBUG
"apm: received %s notify\n",
911 apm_event_name
[event
- 1]);
913 printk(KERN_DEBUG
"apm: received unknown "
914 "event 0x%02x\n", event
);
916 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
918 && ((jiffies
- last_resume
) > BOUNCE_INTERVAL
))
922 case APM_SYS_STANDBY
:
923 case APM_USER_STANDBY
:
924 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
925 if (waiting_for_resume
)
927 waiting_for_resume
= 1;
929 send_event(event
, APM_STANDBY_RESUME
, NULL
);
930 if (standbys_pending
<= 0)
934 case APM_USER_SUSPEND
:
935 #ifdef CONFIG_APM_IGNORE_USER_SUSPEND
936 if (apm_bios_info
.version
> 0x100)
937 apm_set_power_state(APM_STATE_REJECT
);
940 case APM_SYS_SUSPEND
:
941 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
945 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
946 if (waiting_for_resume
)
948 waiting_for_resume
= 1;
950 send_event(event
, APM_NORMAL_RESUME
, NULL
);
951 if (suspends_pending
<= 0)
955 case APM_NORMAL_RESUME
:
956 case APM_CRITICAL_RESUME
:
957 case APM_STANDBY_RESUME
:
958 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
959 waiting_for_resume
= 0;
961 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
962 last_resume
= jiffies
;
966 send_event(event
, 0, NULL
);
969 case APM_LOW_BATTERY
:
970 case APM_POWER_STATUS_CHANGE
:
971 case APM_CAPABILITY_CHANGE
:
972 send_event(event
, 0, NULL
);
975 case APM_UPDATE_TIME
:
979 case APM_CRITICAL_SUSPEND
:
986 static void apm_event_handler(void)
988 static int pending_count
= 0;
990 if (((standbys_pending
> 0) || (suspends_pending
> 0))
991 && (apm_bios_info
.version
> 0x100)
992 && (pending_count
-- <= 0)) {
996 err
= apm_set_power_state(APM_STATE_BUSY
);
998 apm_error("busy", err
);
1001 if (!(((standbys_pending
> 0) || (suspends_pending
> 0))
1002 && (apm_bios_info
.version
== 0x100)))
1006 static int apm_do_idle(void)
1008 #ifdef CONFIG_APM_CPU_IDLE
1014 if (apm_bios_call_simple(0x5305, 0, 0, &dummy
))
1017 #ifdef ALWAYS_CALL_BUSY
1020 clock_slowed
= (apm_bios_info
.flags
& APM_IDLE_SLOWS_CLOCK
) != 0;
1028 static void apm_do_busy(void)
1030 #ifdef CONFIG_APM_CPU_IDLE
1034 (void) apm_bios_call_simple(0x5306, 0, 0, &dummy
);
1041 * This is the APM thread main loop.
1043 * Check whether we're the only running process to
1044 * decide if we should just power down.
1046 * Do this by checking the runqueue: if we're the
1047 * only one, then the current process run_list will
1048 * have both prev and next pointing to the same
1049 * entry (the true idle process)
1051 #define system_idle() (current->run_list.next == current->run_list.prev)
1053 static void apm_mainloop(void)
1055 DECLARE_WAITQUEUE(wait
, current
);
1058 add_wait_queue(&apm_waitqueue
, &wait
);
1059 current
->state
= TASK_INTERRUPTIBLE
;
1061 /* Nothing to do, just sleep for the timeout */
1062 schedule_timeout(APM_CHECK_TIMEOUT
);
1065 * Ok, check all events, check for idle (and mark us sleeping
1066 * so as not to count towards the load average)..
1068 current
->state
= TASK_INTERRUPTIBLE
;
1069 apm_event_handler();
1072 if (apm_do_idle()) {
1073 unsigned long start
= jiffies
;
1076 if (jiffies
- start
> APM_CHECK_TIMEOUT
)
1078 } while (system_idle());
1080 apm_event_handler();
1085 static int check_apm_bios_struct(struct apm_bios_struct
*as
, const char *func
)
1087 if ((as
== NULL
) || (as
->magic
!= APM_BIOS_MAGIC
)) {
1088 printk(KERN_ERR
"apm: %s passed bad filp", func
);
1094 static ssize_t
do_read(struct file
*fp
, char *buf
, size_t count
, loff_t
*ppos
)
1096 struct apm_bios_struct
* as
;
1099 DECLARE_WAITQUEUE(wait
, current
);
1101 as
= fp
->private_data
;
1102 if (check_apm_bios_struct(as
, "read"))
1104 if (count
< sizeof(apm_event_t
))
1106 if (queue_empty(as
)) {
1107 if (fp
->f_flags
& O_NONBLOCK
)
1109 add_wait_queue(&apm_waitqueue
, &wait
);
1111 set_current_state(TASK_INTERRUPTIBLE
);
1112 if (queue_empty(as
) && !signal_pending(current
)) {
1116 current
->state
= TASK_RUNNING
;
1117 remove_wait_queue(&apm_waitqueue
, &wait
);
1120 while ((i
>= sizeof(event
)) && !queue_empty(as
)) {
1121 event
= get_queued_event(as
);
1122 copy_to_user(buf
, &event
, sizeof(event
));
1124 case APM_SYS_SUSPEND
:
1125 case APM_USER_SUSPEND
:
1126 as
->suspends_read
++;
1129 case APM_SYS_STANDBY
:
1130 case APM_USER_STANDBY
:
1131 as
->standbys_read
++;
1134 buf
+= sizeof(event
);
1139 if (signal_pending(current
))
1140 return -ERESTARTSYS
;
1144 static unsigned int do_poll(struct file
*fp
, poll_table
* wait
)
1146 struct apm_bios_struct
* as
;
1148 as
= fp
->private_data
;
1149 if (check_apm_bios_struct(as
, "select"))
1151 poll_wait(fp
, &apm_waitqueue
, wait
);
1152 if (!queue_empty(as
))
1153 return POLLIN
| POLLRDNORM
;
1157 static int do_ioctl(struct inode
* inode
, struct file
*filp
,
1158 u_int cmd
, u_long arg
)
1160 struct apm_bios_struct
* as
;
1162 as
= filp
->private_data
;
1163 if (check_apm_bios_struct(as
, "ioctl"))
1168 case APM_IOC_STANDBY
:
1169 if (as
->standbys_read
> 0) {
1170 as
->standbys_read
--;
1171 as
->standbys_pending
--;
1175 send_event(APM_USER_STANDBY
, APM_STANDBY_RESUME
, as
);
1176 if (standbys_pending
<= 0)
1179 case APM_IOC_SUSPEND
:
1180 if (as
->suspends_read
> 0) {
1181 as
->suspends_read
--;
1182 as
->suspends_pending
--;
1186 send_event(APM_USER_SUSPEND
, APM_NORMAL_RESUME
, as
);
1187 if (suspends_pending
<= 0)
1196 static int do_release(struct inode
* inode
, struct file
* filp
)
1198 struct apm_bios_struct
* as
;
1200 as
= filp
->private_data
;
1201 filp
->private_data
= NULL
;
1202 if (check_apm_bios_struct(as
, "release"))
1204 if (as
->standbys_pending
> 0) {
1205 standbys_pending
-= as
->standbys_pending
;
1206 if (standbys_pending
<= 0)
1209 if (as
->suspends_pending
> 0) {
1210 suspends_pending
-= as
->suspends_pending
;
1211 if (suspends_pending
<= 0)
1214 if (user_list
== as
)
1215 user_list
= as
->next
;
1217 struct apm_bios_struct
* as1
;
1219 for (as1
= user_list
;
1220 (as1
!= NULL
) && (as1
->next
!= as
);
1224 printk(KERN_ERR
"apm: filp not in user list");
1226 as1
->next
= as
->next
;
1228 kfree_s(as
, sizeof(*as
));
1232 static int do_open(struct inode
* inode
, struct file
* filp
)
1234 struct apm_bios_struct
* as
;
1236 as
= (struct apm_bios_struct
*)kmalloc(sizeof(*as
), GFP_KERNEL
);
1238 printk(KERN_ERR
"apm: cannot allocate struct of size %d bytes",
1242 as
->magic
= APM_BIOS_MAGIC
;
1243 as
->event_tail
= as
->event_head
= 0;
1244 as
->suspends_pending
= as
->standbys_pending
= 0;
1245 as
->suspends_read
= as
->standbys_read
= 0;
1247 * XXX - this is a tiny bit broken, when we consider BSD
1248 * process accounting. If the device is opened by root, we
1249 * instantly flag that we used superuser privs. Who knows,
1250 * we might close the device immediately without doing a
1251 * privileged operation -- cevans
1253 as
->suser
= capable(CAP_SYS_ADMIN
);
1254 as
->next
= user_list
;
1256 filp
->private_data
= as
;
1260 int apm_get_info(char *buf
, char **start
, off_t fpos
, int length
, int dummy
)
1266 unsigned short nbat
;
1267 unsigned short error
;
1268 unsigned short ac_line_status
= 0xff;
1269 unsigned short battery_status
= 0xff;
1270 unsigned short battery_flag
= 0xff;
1271 int percentage
= -1;
1272 int time_units
= -1;
1279 if (!(error
= apm_get_power_status(&bx
, &cx
, &dx
))) {
1280 ac_line_status
= (bx
>> 8) & 0xff;
1281 battery_status
= bx
& 0xff;
1282 if ((cx
& 0xff) != 0xff)
1283 percentage
= cx
& 0xff;
1285 if (apm_bios_info
.version
> 0x100) {
1286 battery_flag
= (cx
>> 8) & 0xff;
1288 units
= (dx
& 0x8000) ? "min" : "sec";
1289 time_units
= dx
& 0x7fff;
1293 /* Arguments, with symbols from linux/apm_bios.h. Information is
1294 from the Get Power Status (0x0a) call unless otherwise noted.
1296 0) Linux driver version (this will change if format changes)
1297 1) APM BIOS Version. Usually 1.0 or 1.1.
1298 2) APM flags from APM Installation Check (0x00):
1299 bit 0: APM_16_BIT_SUPPORT
1300 bit 1: APM_32_BIT_SUPPORT
1301 bit 2: APM_IDLE_SLOWS_CLOCK
1302 bit 3: APM_BIOS_DISABLED
1303 bit 4: APM_BIOS_DISENGAGED
1307 0x02: On backup power (APM BIOS 1.1 only)
1320 bit 7: No system battery
1322 6) Remaining battery life (percentage of charge):
1325 7) Remaining battery life (time units):
1326 Number of remaining minutes or seconds
1328 8) min = minutes; sec = seconds */
1330 p
+= sprintf(p
, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
1332 (apm_bios_info
.version
>> 8) & 0xff,
1333 apm_bios_info
.version
& 0xff,
1334 apm_bios_info
.flags
,
1345 static int apm(void *unused
)
1350 unsigned short error
;
1354 strcpy(current
->comm
, "kapmd");
1355 sigfillset(¤t
->blocked
);
1357 if (apm_bios_info
.version
> 0x100) {
1359 * We only support BIOSs up to version 1.2
1361 if (apm_bios_info
.version
> 0x0102)
1362 apm_bios_info
.version
= 0x0102;
1363 if (apm_driver_version(&apm_bios_info
.version
) != APM_SUCCESS
) {
1364 /* Fall back to an APM 1.0 connection. */
1365 apm_bios_info
.version
= 0x100;
1369 printk(KERN_INFO
"apm: Connection version %d.%d\n",
1370 (apm_bios_info
.version
>> 8) & 0xff,
1371 apm_bios_info
.version
& 0xff );
1373 error
= apm_get_power_status(&bx
, &cx
, &dx
);
1375 printk(KERN_INFO
"apm: power status not available\n");
1377 switch ((bx
>> 8) & 0xff) {
1378 case 0: power_stat
= "off line"; break;
1379 case 1: power_stat
= "on line"; break;
1380 case 2: power_stat
= "on backup power"; break;
1381 default: power_stat
= "unknown"; break;
1383 switch (bx
& 0xff) {
1384 case 0: bat_stat
= "high"; break;
1385 case 1: bat_stat
= "low"; break;
1386 case 2: bat_stat
= "critical"; break;
1387 case 3: bat_stat
= "charging"; break;
1388 default: bat_stat
= "unknown"; break;
1391 "apm: AC %s, battery status %s, battery life ",
1392 power_stat
, bat_stat
);
1393 if ((cx
& 0xff) == 0xff)
1394 printk("unknown\n");
1396 printk("%d%%\n", cx
& 0xff);
1397 if (apm_bios_info
.version
> 0x100) {
1399 "apm: battery flag 0x%02x, battery life ",
1402 printk("unknown\n");
1404 printk("%d %s\n", dx
& 0x7fff,
1406 "minutes" : "seconds");
1411 #ifdef CONFIG_APM_DO_ENABLE
1412 if (apm_bios_info
.flags
& APM_BIOS_DISABLED
) {
1414 * This call causes my NEC UltraLite Versa 33/C to hang if it
1415 * is booted with PM disabled but not in the docking station.
1418 error
= apm_enable_power_management();
1420 apm_error("enable power management", error
);
1425 if (((apm_bios_info
.flags
& APM_BIOS_DISENGAGED
) == 0)
1426 && (apm_bios_info
.version
> 0x0100)) {
1427 if (apm_engage_power_management(0x0001) == APM_SUCCESS
)
1428 apm_bios_info
.flags
&= ~APM_BIOS_DISENGAGED
;
1435 static int __init
apm_setup(char *str
)
1439 while ((str
!= NULL
) && (*str
!= '\0')) {
1440 if (strncmp(str
, "off", 3) == 0)
1442 if (strncmp(str
, "on", 2) == 0)
1444 invert
= (strncmp(str
, "no-", 3) == 0);
1447 if (strncmp(str
, "debug", 5) == 0)
1449 if (strncmp(str
, "smp-power-off", 13) == 0)
1451 str
= strchr(str
, ',');
1453 str
+= strspn(str
, ", \t");
1458 __setup("apm=", apm_setup
);
1461 * Just start the APM thread. We do NOT want to do APM BIOS
1462 * calls from anything but the APM thread, if for no other reason
1463 * than the fact that we don't trust the APM BIOS. This way,
1464 * most common APM BIOS problems that lead to protection errors
1465 * etc will have at least some level of being contained...
1467 * In short, if something bad happens, at least we have a choice
1468 * of just killing the apm thread..
1470 static int __init
apm_init(void)
1472 static struct proc_dir_entry
*ent
;
1474 if (apm_bios_info
.version
== 0) {
1475 printk(KERN_INFO
"apm: BIOS not found.\n");
1479 "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
1480 ((apm_bios_info
.version
>> 8) & 0xff),
1481 (apm_bios_info
.version
& 0xff),
1482 apm_bios_info
.flags
,
1484 if ((apm_bios_info
.flags
& APM_32_BIT_SUPPORT
) == 0) {
1485 printk(KERN_INFO
"apm: no 32 bit BIOS support\n");
1490 * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
1491 * but is reportedly a 1.0 BIOS.
1493 if (apm_bios_info
.version
== 0x001)
1494 apm_bios_info
.version
= 0x100;
1496 /* BIOS < 1.2 doesn't set cseg_16_len */
1497 if (apm_bios_info
.version
< 0x102)
1498 apm_bios_info
.cseg_16_len
= 0; /* 64k */
1501 printk(KERN_INFO
"apm: entry %x:%lx cseg16 %x dseg %x",
1502 apm_bios_info
.cseg
, apm_bios_info
.offset
,
1503 apm_bios_info
.cseg_16
, apm_bios_info
.dseg
);
1504 if (apm_bios_info
.version
> 0x100)
1505 printk(" cseg len %x, dseg len %x",
1506 apm_bios_info
.cseg_len
,
1507 apm_bios_info
.dseg_len
);
1508 if (apm_bios_info
.version
> 0x101)
1509 printk(" cseg16 len %x", apm_bios_info
.cseg_16_len
);
1514 printk(KERN_NOTICE
"apm: disabled on user request.\n");
1519 if (smp_num_cpus
> 1) {
1520 printk(KERN_NOTICE
"apm: disabled - APM is not SMP safe.\n");
1528 * Set up a segment that references the real mode segment 0x40
1529 * that extends up to the end of page zero (that we have reserved).
1530 * This is for buggy BIOS's that refer to (real mode) segment 0x40
1531 * even though they are called in protected mode.
1533 set_base(gdt
[APM_40
>> 3],
1534 __va((unsigned long)0x40 << 4));
1535 _set_limit((char *)&gdt
[APM_40
>> 3], 4095 - (0x40 << 4));
1537 apm_bios_entry
.offset
= apm_bios_info
.offset
;
1538 apm_bios_entry
.segment
= APM_CS
;
1539 set_base(gdt
[APM_CS
>> 3],
1540 __va((unsigned long)apm_bios_info
.cseg
<< 4));
1541 set_base(gdt
[APM_CS_16
>> 3],
1542 __va((unsigned long)apm_bios_info
.cseg_16
<< 4));
1543 set_base(gdt
[APM_DS
>> 3],
1544 __va((unsigned long)apm_bios_info
.dseg
<< 4));
1545 #ifndef APM_RELAX_SEGMENTS
1546 if (apm_bios_info
.version
== 0x100)
1549 /* For ASUS motherboard, Award BIOS rev 110 (and others?) */
1550 _set_limit((char *)&gdt
[APM_CS
>> 3], 64 * 1024 - 1);
1551 /* For some unknown machine. */
1552 _set_limit((char *)&gdt
[APM_CS_16
>> 3], 64 * 1024 - 1);
1553 /* For the DEC Hinote Ultra CT475 (and others?) */
1554 _set_limit((char *)&gdt
[APM_DS
>> 3], 64 * 1024 - 1);
1556 #ifndef APM_RELAX_SEGMENTS
1558 _set_limit((char *)&gdt
[APM_CS
>> 3],
1559 (apm_bios_info
.cseg_len
- 1) & 0xffff);
1560 _set_limit((char *)&gdt
[APM_CS_16
>> 3],
1561 (apm_bios_info
.cseg_16_len
- 1) & 0xffff);
1562 _set_limit((char *)&gdt
[APM_DS
>> 3],
1563 (apm_bios_info
.dseg_len
- 1) & 0xffff);
1567 ent
= create_proc_entry("apm", 0, 0);
1569 ent
->get_info
= apm_get_info
;
1571 misc_register(&apm_device
);
1573 kernel_thread(apm
, NULL
, CLONE_FS
| CLONE_FILES
| CLONE_SIGHAND
| SIGCHLD
);
1576 module_init(apm_init
)