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