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
));
291 static asmlinkage
struct {
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
);
543 void apm_power_off(void)
546 * smp_hack == 2 means that we would have enabled APM support
547 * except there is more than one processor and so most of
548 * the APM stuff is unsafe. We will still try power down
549 * because is is useful to some people and they know what
550 * they are doing because they booted with the smp-power-off
553 if (apm_enabled
|| (smp_hack
== 2))
554 (void) apm_set_power_state(APM_STATE_OFF
);
557 #ifdef CONFIG_APM_DISPLAY_BLANK
558 /* Called by apm_display_blank and apm_display_unblank when apm_enabled. */
559 static int apm_set_display_power_state(u_short state
)
563 /* Blank the first display device */
564 error
= set_power_state(0x0100, state
);
565 if (error
== APM_BAD_DEVICE
)
566 /* try to blank them all instead */
567 error
= set_power_state(0x01ff, state
);
572 #ifdef CONFIG_APM_DO_ENABLE
573 static int __init
apm_enable_power_management(void)
577 if (apm_bios_call_simple(0x5308,
578 (apm_bios_info
.version
> 0x100) ? 0x0001 : 0xffff,
580 return (eax
>> 8) & 0xff;
581 apm_bios_info
.flags
&= ~APM_BIOS_DISABLED
;
586 static int apm_get_power_status(u_short
*status
, u_short
*bat
, u_short
*life
)
594 if (apm_bios_call(0x530a, 1, 0, &eax
, &ebx
, &ecx
, &edx
, &dummy
))
595 return (eax
>> 8) & 0xff;
602 static int apm_get_battery_status(u_short which
, u_short
*status
,
603 u_short
*bat
, u_short
*life
, u_short
*nbat
)
611 if (apm_bios_info
.version
< 0x0102) {
612 /* pretend we only have one battery. */
614 return APM_BAD_DEVICE
;
616 return apm_get_power_status(status
, bat
, life
);
619 if (apm_bios_call(0x530a, (0x8000 | (which
)), 0, &eax
,
620 &ebx
, &ecx
, &edx
, &esi
))
621 return (eax
>> 8) & 0xff;
629 static int __init
apm_engage_power_management(u_short device
)
633 if (apm_bios_call_simple(0x530f, device
, 1, &eax
))
634 return (eax
>> 8) & 0xff;
638 static void apm_error(char *str
, int err
)
642 for (i
= 0; i
< ERROR_COUNT
; i
++)
643 if (error_table
[i
].key
== err
) break;
645 printk(KERN_NOTICE
"apm: %s: %s\n", str
, error_table
[i
].msg
);
647 printk(KERN_NOTICE
"apm: %s: unknown error code %#2.2x\n",
651 /* Called from console driver -- must make sure apm_enabled. */
652 int apm_display_blank(void)
654 #ifdef CONFIG_APM_DISPLAY_BLANK
659 error
= apm_set_display_power_state(APM_STATE_STANDBY
);
660 if (error
== APM_SUCCESS
)
662 apm_error("set display standby", error
);
667 /* Called from console driver -- must make sure apm_enabled. */
668 int apm_display_unblank(void)
670 #ifdef CONFIG_APM_DISPLAY_BLANK
675 error
= apm_set_display_power_state(APM_STATE_READY
);
676 if (error
== APM_SUCCESS
)
678 apm_error("set display ready", error
);
683 int apm_register_callback(int (*callback
)(apm_event_t
))
685 callback_list_t
* new;
687 new = kmalloc(sizeof(callback_list_t
), GFP_KERNEL
);
690 new->callback
= callback
;
691 new->next
= callback_list
;
696 void apm_unregister_callback(int (*callback
)(apm_event_t
))
698 callback_list_t
** ptr
;
699 callback_list_t
* old
;
701 for (ptr
= &callback_list
; *ptr
!= NULL
; ptr
= &(*ptr
)->next
)
702 if ((*ptr
)->callback
== callback
)
706 kfree_s(old
, sizeof(callback_list_t
));
709 static int queue_empty(struct apm_bios_struct
* as
)
711 return as
->event_head
== as
->event_tail
;
714 static apm_event_t
get_queued_event(struct apm_bios_struct
* as
)
716 as
->event_tail
= (as
->event_tail
+ 1) % APM_MAX_EVENTS
;
717 return as
->events
[as
->event_tail
];
720 static int queue_event(apm_event_t event
, struct apm_bios_struct
*sender
)
722 struct apm_bios_struct
* as
;
724 if (user_list
== NULL
)
726 for (as
= user_list
; as
!= NULL
; as
= as
->next
) {
729 as
->event_head
= (as
->event_head
+ 1) % APM_MAX_EVENTS
;
730 if (as
->event_head
== as
->event_tail
) {
734 printk(KERN_ERR
"apm: an event queue overflowed\n");
737 as
->event_tail
= (as
->event_tail
+ 1) % APM_MAX_EVENTS
;
739 as
->events
[as
->event_head
] = event
;
743 case APM_SYS_SUSPEND
:
744 case APM_USER_SUSPEND
:
745 as
->suspends_pending
++;
749 case APM_SYS_STANDBY
:
750 case APM_USER_STANDBY
:
751 as
->standbys_pending
++;
756 wake_up_interruptible(&apm_waitqueue
);
760 static void set_time(void)
764 if (!got_clock_diff
) /* Don't know time zone, can't set clock */
769 CURRENT_TIME
= get_cmos_time() + clock_cmos_diff
;
770 restore_flags(flags
);
773 static void suspend(void)
778 #ifndef CONFIG_APM_RTC_IS_GMT
780 * Estimate time zone so that set_time can update the clock
783 clock_cmos_diff
= -get_cmos_time();
785 clock_cmos_diff
+= CURRENT_TIME
;
787 restore_flags(flags
);
790 err
= apm_set_power_state(APM_STATE_SUSPEND
);
792 apm_error("suspend", err
);
793 #ifdef INIT_TIMER_AFTER_SUSPEND
796 /* set the clock to 100 Hz */
797 outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
799 outb_p(LATCH
& 0xff , 0x40); /* LSB */
801 outb(LATCH
>> 8 , 0x40); /* MSB */
803 restore_flags(flags
);
808 static void standby(void)
812 err
= apm_set_power_state(APM_STATE_STANDBY
);
814 apm_error("standby", err
);
817 static apm_event_t
get_event(void)
821 apm_eventinfo_t info
;
823 static int notified
= 0;
825 /* we don't use the eventinfo */
826 error
= apm_get_event(&event
, &info
);
827 if (error
== APM_SUCCESS
)
830 if ((error
!= APM_NO_EVENTS
) && (notified
++ == 0))
831 apm_error("get_event", error
);
836 static void send_event(apm_event_t event
, apm_event_t undo
,
837 struct apm_bios_struct
*sender
)
839 callback_list_t
* call
;
840 callback_list_t
* fix
;
842 for (call
= callback_list
; call
!= NULL
; call
= call
->next
) {
843 if (call
->callback(event
) && undo
) {
844 for (fix
= callback_list
; fix
!= call
; fix
= fix
->next
)
846 if (apm_bios_info
.version
> 0x100)
847 apm_set_power_state(APM_STATE_REJECT
);
852 queue_event(event
, sender
);
855 static void check_events(void)
858 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
859 static unsigned long last_resume
= 0;
860 static int ignore_bounce
= 0;
863 while ((event
= get_event()) != 0) {
865 if (event
<= NR_APM_EVENT_NAME
)
866 printk(KERN_DEBUG
"apm: received %s notify\n",
867 apm_event_name
[event
- 1]);
869 printk(KERN_DEBUG
"apm: received unknown "
870 "event 0x%02x\n", event
);
872 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
874 && ((jiffies
- last_resume
) > BOUNCE_INTERVAL
))
878 case APM_SYS_STANDBY
:
879 case APM_USER_STANDBY
:
880 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
881 if (waiting_for_resume
)
883 waiting_for_resume
= 1;
885 send_event(event
, APM_STANDBY_RESUME
, NULL
);
886 if (standbys_pending
<= 0)
890 case APM_USER_SUSPEND
:
891 #ifdef CONFIG_APM_IGNORE_USER_SUSPEND
892 if (apm_bios_info
.version
> 0x100)
893 apm_set_power_state(APM_STATE_REJECT
);
896 case APM_SYS_SUSPEND
:
897 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
901 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
902 if (waiting_for_resume
)
904 waiting_for_resume
= 1;
906 send_event(event
, APM_NORMAL_RESUME
, NULL
);
907 if (suspends_pending
<= 0)
911 case APM_NORMAL_RESUME
:
912 case APM_CRITICAL_RESUME
:
913 case APM_STANDBY_RESUME
:
914 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
915 waiting_for_resume
= 0;
917 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
918 last_resume
= jiffies
;
922 send_event(event
, 0, NULL
);
925 case APM_LOW_BATTERY
:
926 case APM_POWER_STATUS_CHANGE
:
927 case APM_CAPABILITY_CHANGE
:
928 send_event(event
, 0, NULL
);
931 case APM_UPDATE_TIME
:
935 case APM_CRITICAL_SUSPEND
:
943 * This is the APM thread main loop.
945 static void apm_mainloop(void)
947 DECLARE_WAITQUEUE(wait
, current
);
950 add_wait_queue(&apm_waitqueue
, &wait
);
952 static int pending_count
= 0;
955 current
->state
= TASK_INTERRUPTIBLE
;
956 schedule_timeout(APM_CHECK_TIMEOUT
);
958 if (((standbys_pending
> 0) || (suspends_pending
> 0))
959 && (apm_bios_info
.version
> 0x100)
960 && (pending_count
-- <= 0)) {
963 err
= apm_set_power_state(APM_STATE_BUSY
);
965 apm_error("busy", err
);
968 if (!(((standbys_pending
> 0) || (suspends_pending
> 0))
969 && (apm_bios_info
.version
== 0x100)))
974 /* Called from cpu_idle, must make sure apm_enabled. */
975 int apm_do_idle(void)
977 #ifdef CONFIG_APM_CPU_IDLE
983 if (apm_bios_call_simple(0x5305, 0, 0, &dummy
))
986 clock_slowed
= (apm_bios_info
.flags
& APM_IDLE_SLOWS_CLOCK
) != 0;
993 /* Called from cpu_idle, must make sure apm_enabled. */
994 void apm_do_busy(void)
996 #ifdef CONFIG_APM_CPU_IDLE
1000 #ifndef ALWAYS_CALL_BUSY
1004 (void) apm_bios_call_simple(0x5306, 0, 0, &dummy
);
1010 static int check_apm_bios_struct(struct apm_bios_struct
*as
, const char *func
)
1012 if ((as
== NULL
) || (as
->magic
!= APM_BIOS_MAGIC
)) {
1013 printk(KERN_ERR
"apm: %s passed bad filp", func
);
1019 static ssize_t
do_read(struct file
*fp
, char *buf
, size_t count
, loff_t
*ppos
)
1021 struct apm_bios_struct
* as
;
1024 DECLARE_WAITQUEUE(wait
, current
);
1026 as
= fp
->private_data
;
1027 if (check_apm_bios_struct(as
, "read"))
1029 if (count
< sizeof(apm_event_t
))
1031 if (queue_empty(as
)) {
1032 if (fp
->f_flags
& O_NONBLOCK
)
1034 add_wait_queue(&apm_waitqueue
, &wait
);
1036 current
->state
= TASK_INTERRUPTIBLE
;
1037 if (queue_empty(as
) && !signal_pending(current
)) {
1041 current
->state
= TASK_RUNNING
;
1042 remove_wait_queue(&apm_waitqueue
, &wait
);
1045 while ((i
>= sizeof(event
)) && !queue_empty(as
)) {
1046 event
= get_queued_event(as
);
1047 copy_to_user(buf
, &event
, sizeof(event
));
1049 case APM_SYS_SUSPEND
:
1050 case APM_USER_SUSPEND
:
1051 as
->suspends_read
++;
1054 case APM_SYS_STANDBY
:
1055 case APM_USER_STANDBY
:
1056 as
->standbys_read
++;
1059 buf
+= sizeof(event
);
1064 if (signal_pending(current
))
1065 return -ERESTARTSYS
;
1069 static unsigned int do_poll(struct file
*fp
, poll_table
* wait
)
1071 struct apm_bios_struct
* as
;
1073 as
= fp
->private_data
;
1074 if (check_apm_bios_struct(as
, "select"))
1076 poll_wait(fp
, &apm_waitqueue
, wait
);
1077 if (!queue_empty(as
))
1078 return POLLIN
| POLLRDNORM
;
1082 static int do_ioctl(struct inode
* inode
, struct file
*filp
,
1083 u_int cmd
, u_long arg
)
1085 struct apm_bios_struct
* as
;
1087 as
= filp
->private_data
;
1088 if (check_apm_bios_struct(as
, "ioctl"))
1093 case APM_IOC_STANDBY
:
1094 if (as
->standbys_read
> 0) {
1095 as
->standbys_read
--;
1096 as
->standbys_pending
--;
1100 send_event(APM_USER_STANDBY
, APM_STANDBY_RESUME
, as
);
1101 if (standbys_pending
<= 0)
1104 case APM_IOC_SUSPEND
:
1105 if (as
->suspends_read
> 0) {
1106 as
->suspends_read
--;
1107 as
->suspends_pending
--;
1111 send_event(APM_USER_SUSPEND
, APM_NORMAL_RESUME
, as
);
1112 if (suspends_pending
<= 0)
1121 static int do_release(struct inode
* inode
, struct file
* filp
)
1123 struct apm_bios_struct
* as
;
1125 as
= filp
->private_data
;
1126 filp
->private_data
= NULL
;
1127 if (check_apm_bios_struct(as
, "release"))
1129 if (as
->standbys_pending
> 0) {
1130 standbys_pending
-= as
->standbys_pending
;
1131 if (standbys_pending
<= 0)
1134 if (as
->suspends_pending
> 0) {
1135 suspends_pending
-= as
->suspends_pending
;
1136 if (suspends_pending
<= 0)
1139 if (user_list
== as
)
1140 user_list
= as
->next
;
1142 struct apm_bios_struct
* as1
;
1144 for (as1
= user_list
;
1145 (as1
!= NULL
) && (as1
->next
!= as
);
1149 printk(KERN_ERR
"apm: filp not in user list");
1151 as1
->next
= as
->next
;
1153 kfree_s(as
, sizeof(*as
));
1157 static int do_open(struct inode
* inode
, struct file
* filp
)
1159 struct apm_bios_struct
* as
;
1161 as
= (struct apm_bios_struct
*)kmalloc(sizeof(*as
), GFP_KERNEL
);
1163 printk(KERN_ERR
"apm: cannot allocate struct of size %d bytes",
1167 as
->magic
= APM_BIOS_MAGIC
;
1168 as
->event_tail
= as
->event_head
= 0;
1169 as
->suspends_pending
= as
->standbys_pending
= 0;
1170 as
->suspends_read
= as
->standbys_read
= 0;
1172 * XXX - this is a tiny bit broken, when we consider BSD
1173 * process accounting. If the device is opened by root, we
1174 * instantly flag that we used superuser privs. Who knows,
1175 * we might close the device immediately without doing a
1176 * privileged operation -- cevans
1178 as
->suser
= capable(CAP_SYS_ADMIN
);
1179 as
->next
= user_list
;
1181 filp
->private_data
= as
;
1185 int apm_get_info(char *buf
, char **start
, off_t fpos
, int length
, int dummy
)
1191 unsigned short nbat
;
1192 unsigned short error
;
1193 unsigned short ac_line_status
= 0xff;
1194 unsigned short battery_status
= 0xff;
1195 unsigned short battery_flag
= 0xff;
1196 int percentage
= -1;
1197 int time_units
= -1;
1204 if (!(error
= apm_get_power_status(&bx
, &cx
, &dx
))) {
1205 ac_line_status
= (bx
>> 8) & 0xff;
1206 battery_status
= bx
& 0xff;
1207 if ((cx
& 0xff) != 0xff)
1208 percentage
= cx
& 0xff;
1210 if (apm_bios_info
.version
> 0x100) {
1211 battery_flag
= (cx
>> 8) & 0xff;
1213 units
= (dx
& 0x8000) ? "min" : "sec";
1214 time_units
= dx
& 0x7fff;
1218 /* Arguments, with symbols from linux/apm_bios.h. Information is
1219 from the Get Power Status (0x0a) call unless otherwise noted.
1221 0) Linux driver version (this will change if format changes)
1222 1) APM BIOS Version. Usually 1.0 or 1.1.
1223 2) APM flags from APM Installation Check (0x00):
1224 bit 0: APM_16_BIT_SUPPORT
1225 bit 1: APM_32_BIT_SUPPORT
1226 bit 2: APM_IDLE_SLOWS_CLOCK
1227 bit 3: APM_BIOS_DISABLED
1228 bit 4: APM_BIOS_DISENGAGED
1232 0x02: On backup power (APM BIOS 1.1 only)
1245 bit 7: No system battery
1247 6) Remaining battery life (percentage of charge):
1250 7) Remaining battery life (time units):
1251 Number of remaining minutes or seconds
1253 8) min = minutes; sec = seconds */
1255 p
+= sprintf(p
, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
1257 (apm_bios_info
.version
>> 8) & 0xff,
1258 apm_bios_info
.version
& 0xff,
1259 apm_bios_info
.flags
,
1270 void __init
apm_setup(char *str
, int *dummy
)
1274 while ((str
!= NULL
) && (*str
!= '\0')) {
1275 if (strncmp(str
, "off", 3) == 0)
1277 if (strncmp(str
, "on", 2) == 0)
1279 invert
= (strncmp(str
, "no-", 3) == 0);
1282 if (strncmp(str
, "debug", 5) == 0)
1284 if (strncmp(str
, "smp-power-off", 13) == 0)
1286 str
= strchr(str
, ',');
1288 str
+= strspn(str
, ", \t");
1292 static int apm(void *unused
)
1297 unsigned short error
;
1301 strcpy(current
->comm
, "kapmd");
1302 sigfillset(¤t
->blocked
);
1304 if (apm_bios_info
.version
> 0x100) {
1306 * We only support BIOSs up to version 1.2
1308 if (apm_bios_info
.version
> 0x0102)
1309 apm_bios_info
.version
= 0x0102;
1310 if (apm_driver_version(&apm_bios_info
.version
) != APM_SUCCESS
) {
1311 /* Fall back to an APM 1.0 connection. */
1312 apm_bios_info
.version
= 0x100;
1316 printk(KERN_INFO
"apm: Connection version %d.%d\n",
1317 (apm_bios_info
.version
>> 8) & 0xff,
1318 apm_bios_info
.version
& 0xff );
1320 error
= apm_get_power_status(&bx
, &cx
, &dx
);
1322 printk(KERN_INFO
"apm: power status not available\n");
1324 switch ((bx
>> 8) & 0xff) {
1325 case 0: power_stat
= "off line"; break;
1326 case 1: power_stat
= "on line"; break;
1327 case 2: power_stat
= "on backup power"; break;
1328 default: power_stat
= "unknown"; break;
1330 switch (bx
& 0xff) {
1331 case 0: bat_stat
= "high"; break;
1332 case 1: bat_stat
= "low"; break;
1333 case 2: bat_stat
= "critical"; break;
1334 case 3: bat_stat
= "charging"; break;
1335 default: bat_stat
= "unknown"; break;
1338 "apm: AC %s, battery status %s, battery life ",
1339 power_stat
, bat_stat
);
1340 if ((cx
& 0xff) == 0xff)
1341 printk("unknown\n");
1343 printk("%d%%\n", cx
& 0xff);
1344 if (apm_bios_info
.version
> 0x100) {
1346 "apm: battery flag 0x%02x, battery life ",
1349 printk("unknown\n");
1351 printk("%d %s\n", dx
& 0x7fff,
1353 "minutes" : "seconds");
1358 #ifdef CONFIG_APM_DO_ENABLE
1359 if (apm_bios_info
.flags
& APM_BIOS_DISABLED
) {
1361 * This call causes my NEC UltraLite Versa 33/C to hang if it
1362 * is booted with PM disabled but not in the docking station.
1365 error
= apm_enable_power_management();
1367 apm_error("enable power management", error
);
1372 if (((apm_bios_info
.flags
& APM_BIOS_DISABLED
) == 0)
1373 && (apm_bios_info
.version
> 0x0100)) {
1374 if (apm_engage_power_management(0x0001) == APM_SUCCESS
)
1375 apm_bios_info
.flags
&= ~APM_BIOS_DISENGAGED
;
1383 * Just start the APM thread. We do NOT want to do APM BIOS
1384 * calls from anything but the APM thread, if for no other reason
1385 * than the fact that we don't trust the APM BIOS. This way,
1386 * most common APM BIOS problems that lead to protection errors
1387 * etc will have at least some level of being contained...
1389 * In short, if something bad happens, at least we have a choice
1390 * of just killing the apm thread..
1392 void __init
apm_init(void)
1394 static struct proc_dir_entry
*ent
;
1396 if (apm_bios_info
.version
== 0) {
1397 printk(KERN_INFO
"apm: BIOS not found.\n");
1401 "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
1402 ((apm_bios_info
.version
>> 8) & 0xff),
1403 (apm_bios_info
.version
& 0xff),
1404 apm_bios_info
.flags
,
1406 if ((apm_bios_info
.flags
& APM_32_BIT_SUPPORT
) == 0) {
1407 printk(KERN_INFO
"apm: no 32 bit BIOS support\n");
1412 * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
1413 * but is reportedly a 1.0 BIOS.
1415 if (apm_bios_info
.version
== 0x001)
1416 apm_bios_info
.version
= 0x100;
1418 /* BIOS < 1.2 doesn't set cseg_16_len */
1419 if (apm_bios_info
.version
< 0x102)
1420 apm_bios_info
.cseg_16_len
= 0; /* 64k */
1423 printk(KERN_INFO
"apm: entry %x:%lx cseg16 %x dseg %x",
1424 apm_bios_info
.cseg
, apm_bios_info
.offset
,
1425 apm_bios_info
.cseg_16
, apm_bios_info
.dseg
);
1426 if (apm_bios_info
.version
> 0x100)
1427 printk(" cseg len %x, dseg len %x",
1428 apm_bios_info
.cseg_len
,
1429 apm_bios_info
.dseg_len
);
1430 if (apm_bios_info
.version
> 0x101)
1431 printk(" cseg16 len %x", apm_bios_info
.cseg_16_len
);
1436 printk(KERN_NOTICE
"apm: disabled on user request.\n");
1441 if (smp_num_cpus
> 1) {
1442 printk(KERN_NOTICE
"apm: disabled - APM is not SMP safe.\n");
1450 * Set up a segment that references the real mode segment 0x40
1451 * that extends up to the end of page zero (that we have reserved).
1452 * This is for buggy BIOS's that refer to (real mode) segment 0x40
1453 * even though they are called in protected mode.
1455 set_base(gdt
[APM_40
>> 3],
1456 __va((unsigned long)0x40 << 4));
1457 _set_limit((char *)&gdt
[APM_40
>> 3], 4095 - (0x40 << 4));
1459 apm_bios_entry
.offset
= apm_bios_info
.offset
;
1460 apm_bios_entry
.segment
= APM_CS
;
1461 set_base(gdt
[APM_CS
>> 3],
1462 __va((unsigned long)apm_bios_info
.cseg
<< 4));
1463 set_base(gdt
[APM_CS_16
>> 3],
1464 __va((unsigned long)apm_bios_info
.cseg_16
<< 4));
1465 set_base(gdt
[APM_DS
>> 3],
1466 __va((unsigned long)apm_bios_info
.dseg
<< 4));
1467 #ifndef APM_RELAX_SEGMENTS
1468 if (apm_bios_info
.version
== 0x100)
1471 /* For ASUS motherboard, Award BIOS rev 110 (and others?) */
1472 _set_limit((char *)&gdt
[APM_CS
>> 3], 64 * 1024 - 1);
1473 /* For some unknown machine. */
1474 _set_limit((char *)&gdt
[APM_CS_16
>> 3], 64 * 1024 - 1);
1475 /* For the DEC Hinote Ultra CT475 (and others?) */
1476 _set_limit((char *)&gdt
[APM_DS
>> 3], 64 * 1024 - 1);
1478 #ifndef APM_RELAX_SEGMENTS
1480 _set_limit((char *)&gdt
[APM_CS
>> 3],
1481 (apm_bios_info
.cseg_len
- 1) & 0xffff);
1482 _set_limit((char *)&gdt
[APM_CS_16
>> 3],
1483 (apm_bios_info
.cseg_16_len
- 1) & 0xffff);
1484 _set_limit((char *)&gdt
[APM_DS
>> 3],
1485 (apm_bios_info
.dseg_len
- 1) & 0xffff);
1489 ent
= create_proc_entry("apm", 0, 0);
1491 ent
->get_info
= apm_get_info
;
1493 misc_register(&apm_device
);
1495 kernel_thread(apm
, NULL
, CLONE_FS
| CLONE_FILES
| CLONE_SIGHAND
| SIGCHLD
);