<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
     "http://docbook.org/xml/4.4/docbookx.dtd" []>
<article>

<articleinfo>
<title>Linux ACPI-HOWTO, The Sequel</title>
<author>
  <firstname>Ariel</firstname>
  <surname>Glenn</surname>
  <affiliation>
    <address><email>ariel@columbia.edu</email></address>
  </affiliation>
</author>

<pubdate>2005-09-25</pubdate>

<revhistory>
  <revision>
    <revnumber>0.2a</revnumber>
    <date></date>
    <authorinitials>atg</authorinitials>
    <revremark>
      Clean up markup and typos; update Jens Axboe SATA patch info; 2.6.14-rc2; video patch not needed
    </revremark>
  </revision>
  <revision>
    <revnumber>0.2</revnumber>
    <date></date>
    <authorinitials>atg</authorinitials>
    <revremark>
      Get a laptop 4 years later and rewrite the whole fscking thing for kernel 2.6.13
    </revremark>
  </revision>
  <revision>
    <revnumber>0.1e</revnumber>
    <date></date>
    <authorinitials>atg</authorinitials>
    <revremark>
      Fix typos; move full text of GPL to separate document;
      bug reports now go to Andy Grover
     </revremark>
  </revision>
  <revision>
    <revnumber>0.1d</revnumber>
    <date></date>
    <authorinitials>atg</authorinitials>
    <revremark>
      Added information about libpopt, required for build
      of acpictl (included in acpid)
    </revremark>
  </revision>
  <revision>
    <revnumber>0.1c</revnumber>
    <date></date>
    <authorinitials>atg</authorinitials>
    <revremark>
       describe pmtest util, /proc
       interface, reduced functionality of new acpid, 
       changes to driver options
    </revremark>
  </revision>
</revhistory>

<abstract>
  <para>
    This document provides an overview of the APCI subsystem in Linux, including kernel configuration, 
    acpid support daemon, supporting user applications, and common problems.
  </para>
</abstract>
</articleinfo>
		
<sect1 id="about_this_document">
  <title>About this document</title>
  <sect2 id="introduction">
    <title>Introduction</title>
    <para>
      ACPI, which stands for Advanced Configuration and Power Interface, is the
      successor to APM (Advanced Power Management).  The specification provides
      for many functions besides power management, such as thermal management
      and plug-and-play events.  This document covers those functions supported
      by Linux to-date.  This document describes how to compile, install, and use
      the ACPI driver for Linux and its associated applications.
    </para>
    <para>
      I test ACPI on a 32-bit x86 system, so this document is biased towards
      that hardware.  In particular, I do not discuss the ARM or x86_64 implementations
      at all, nor ACPI on embedded systems.  For information on those topics,
      see the links in <link linkend="other_architectures">ACPI on other architectures</link>.
    </para>
    <para>
      The current Linux kernel is 2.6.13, and this document covers configuration,
      installation, patches and problems for that kernel.  Some options or capabilities
      discussed here may not be available in earlier 2.6 or 2.5 series kernels.
      For information about the (early) 2.4 kernel series, please check the
      previous version of this document, at
      <ulink url="http://www.columbia.edu/~ariel/acpi/acpi_howto-01e.txt">
      http://www.columbia.edu/~ariel/acpi/acpi_howto-01e.txt</ulink>.
    </para>
    <para>
      The current version of this document can always be found at 
      <ulink url="http://www.columbia.edu/~ariel/acpi/acpi_howto.html">
      http://www.columbia.edu/~ariel/acpi/acpi_howto.html</ulink>.
      You can also find other formats of this document at 
      <ulink url="http://www.columbia.edu/~ariel/acpi/">
      http://www.columbia.edu/~ariel/acpi/</ulink>.
    </para>
  </sect2>

  <sect2 id="copyright">
    <title>Copyright and License</title>
    <para>
      This document, <emphasis>ACPI HOWTO</emphasis>,
      is copyrighted (c) 2005 by <emphasis>Ariel T. Glenn</emphasis>.
      Permission is granted to copy, distribute and/or modify this
      document under the terms of the GNU Free Documentation
      License, Version 1.2, or any later version published
      by the Free Software Foundation; with no Invariant Sections,
      with no Front-Cover Texts, and with no Back-Cover Texts.
      A copy of the license is available at
      <ulink url="http://www.gnu.org/copyleft/fdl.html">
      http://www.gnu.org/copyleft/fdl.html</ulink>.
    </para>

    <para>
     Linux is a registered trademark of Linus Torvalds.
    </para>
  </sect2>

  <sect2 id="disclaimer">
    <title>Disclaimer</title>
    <para>
      This document is provided ``AS IS'', with no express or implied
      warranties.  No liability for the contents of this document can 
      be accepted.  There may be errors and inaccuracies that could be 
      damaging to your system.  The author(s) do not take any responsibility;
      use the concepts, examples and information at your own risk.
    </para>
    <para>
      All copyrights are held by their by their respective owners,
      unless specifically noted otherwise.  Use of a term in this
      document should not be regarded as affecting the validity of any
      trademark or service mark.  Naming of particular products or
      brands should not be seen as endorsements.
    </para>
  </sect2>

  <sect2 id="credits">
    <title>Credits/Contributors</title>
    <para>
      I've been paying great attention to the postings of Len Brown, Matthew
      Garrett, Pavel Machek, Jon Smirl, Li-Ta Lo, and Carl-Daniel Hailfinger.
      Emma Jane Hogbin nagged me last year to get back to work on this stuff so
      I finally did.  The City of Oakland kindly provided money for this laptop
      (lawsuit settlement, that's another story).  Greg Michalec loaned
      me hardware to test suspend on ATI Radeon hardware. My housemates endured
      long days of obscure rambling about these topics.  Thanks to everyone.
    </para>
  </sect2>

  <sect2 id="feedback">
    <title>Feedback</title>
    <para>
      Please send suggestions, complaints or comments about this document
      to ariel@columbia.edu. Please do NOT send me bug reports about the driver;
      see <link linkend="what_to_put_in_bug_report">
      Submitting useful bug reports</link> for more information on
      reporting ACPI bugs.
    </para>
  </sect2>

  <sect2 id="fixmes">
    <title>[FIXME]s</title>
    <para>
      This document is a work in progress.  Since it's been 4 years since I updated
      this, there has been a lot of catching up to do.  I have left some sections
      blank and they'll get filled in Real Soon Now.  Other sections are marked with
      the warning [FIXME] which tells me I have more work to do on that section,
      and it tells you that you should be extra careful when using information from
      that section.  Thanks for your patience.
    </para>
    <para>
      <itemizedlist>
	<listitem>
	  <para>
	    I have not done any work yet with suspend to disk.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    I heard rumors that the earlier nVidia X drivers, version .6xxx, may suspend to RAM properly where
	    the .7xxx series does not.  I need to test this.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    I have not worked with the Radeon patches, though a friend of mine has generously offered
	    to let me borrow his hardware to do some testing.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The section on DSDT tables needs to be completed.  Fortunately, other HOWTOs
	    fill in that gap.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The FADT needs a description.  Actually, I should add a basic description of all
	    of the ACPI tables and how they interrelate.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    I should check what linux does when it has to poll the battery for status, and what action
	    it takes when capacity gets low.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    If there are utilities for suspend to RAM or additional notes on suspend on lid close,
	    I should add them, or remove those sections.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Some kernel CONFIG options have yet to be documented, and explanations of a few of
	    the boot parameters are incomplete.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    I need to add pointers to information for ACPI on other architectures, especially 64-bit
	    platforms.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The description of the <filename class="directory">/proc</filename> interface for the video driver is almost nonexistent.
	  </para>
	</listitem>
      </itemizedlist>
    </para>
  </sect2>

</sect1>

<sect1 id="acpi_overview">
  <title>Overview of ACPI</title>
  <sect2 id="what_is_power_management">
    <title>What is power management?</title>
    <para>
      Power management is a catch-all term for functionality that lets you
      conserve power or use power resources for your computer more efficiently.  
      For example, you may wish to reduce the brightness of your LCD panel when you're
      running your laptop off of batteries, or you may want your CPU to run
      in a lower power state if it's idle, or you may want the system to
      hibernate after 20 minutes if you haven't been typing.  All of these
      are examples of power management.
    </para>
    <para>
      These days, power management includes support for things like automated system
      wakeup at a given time, switching video displays, and monitoring fan speed or chipset
      temperature.  Eventually it will probably grow to replace the desktop
      OS. (Just kidding...)
    </para>
  </sect2>

  <sect2 id="what_is_acpi">
    <title>What is ACPI?</title>
    <para>
      ACPI, or Advanced Configuration and Power Interface, is a set of
      specifications for power management functions of devices and
      the OS interface to them.  It consists of descriptions of
      power specifications for classes of devices that describe
      which power states and what other functionality a class of
      devices must support, the definition of AML, an interpreted language
      for describing these various functions, and a description
      of how the OS calls these functions and in what context.
    </para>
    <para>
      You may want ACPI if you are running a laptop and power conservation
      is a big concern, or if you want to put your desktop system to
      sleep during inactive periods, or if you want to monitor the
      temperature of various chipsets and to increase or decrease fan
      speed depending on those temperatures.  You may want it so
      that you can shut your laptop lid, take your laptop to work,
      and open it up again, ready to go at the touch of the power button.
      And your computer vendor may expect you to be using ACPI so that the OS
      will take appropriate action if the CPU or other chipsets get too hot.
    </para>
    <para>
      But I prefer to think of ACPI not as an optional add-on component but 
      as an integral part of your system; in today's world, where we are all 
      conscious of our energy use and we don't think twice about turing off the 
      light switch when we leave a room, enabling basic ACPI functionality 
      is common sense.
    </para>
    <para>
      In very specific cases you may be required to enable ACPI for your
      system to function properly.  64-bit Itanium platforms require this;
      you won't get a choice in the kernel configuration menu to choose it or not, 
      it will just be done for you.  NUMA-enabled systems often
      require it, and systems with new Intel processors that support hyperthreading
      require it because they use ACPI tables for virtual processor discovery.
    </para>    
  </sect2>

  <sect2 id="acpi_and_apm">
    <title>What is the difference between ACPI and APM?</title>
    <para>
      APM, or Advanced Power Management, is the predecessor to ACPI.  It
      required the BIOS to handle all power management.  Devices were 
      put into lower power states based on device activity timeouts.
      Only standby and hibernate system sleep states were supported.
      Some power management features such as reducing power usage of various devices
      when switching from ac adapter to battery were not implemented because 
      this would have required building support for more power states
      and for various power usage policies directly into the BIOS.  Adoption
      of the ACPI standard started in 1997 when developers understood that 
      putting most of the code in the OS would allow for more features and 
      greater flexibility.  Version 3.0, the current ACPI specification, 
      was released in 2004.
    </para>
    <para>
      The Linux APM driver is very stable.  It supports standby and hibernation, but 
      some newer systems may not have support for APM in the BIOS at all.
      Although APM support in the kernel is very mature, patches still come in once
      in a while.  ACPI, by contrast, is under furious development.  A feature
      may be broken in one release, work in the next, and disappear completely
      in the next. This is no joke.  As I type this, the latest FC4 kernel 
      (2.6.12-1.1447_FC4) has suddenly made the 
      <filename class="directory">/proc/acpi/button directory</filename>
      disappear; acpid relies on this to do the right thing (TM) when you
      close or open your laptop, or press the power button on resume.  
      It was there in the previous version; an overaggressive patch in
      2.6.13-rc5 made it go away.
    </para>
  </sect2>

  <sect2 id="acpi_and_linux">
    <title>What ACPI capabilities are supported under Linux?</title>
    <para>
      As of kernel 2.6.13, you can do the following (if you are lucky):
    </para>

    <itemizedlist>
    <listitem>
      <para>Suspend to RAM (S3 power state)</para>
    </listitem>
    <listitem>
      <para>Suspend to disk (S4 power state)</para>
    </listitem>
    <listitem>
      <para>Enter standby (S1 power state)</para>
    </listitem>
    <listitem>
      <para>monitor your battery and set an action to take on low charge</para>
    </listitem>
    <listitem>
      <para>monitor CPU temperature and set actions to take when it gets too hot</para>
    </listitem>
    <listitem>
      <para>monitor CPU speed, throttle your CPU, and put your CPU into different power states</para>
    </listitem>
    <listitem>
      <para>monitor and turn on or off your fan</para>
    </listitem>
    <listitem>
      <para>change your video display brightness, or enable an external video display</para>
    </listitem>
    <listitem>
      <para>Set an action to take when you close your laptop</para>
    </listitem>
    <listitem>
      <para>Set an action to take when you press the power or sleep button</para>
    </listitem>
    <listitem>
      <para>Set your system to wake on a certain event</para>
    </listitem>
    <listitem>
      <para>And much more to come!</para>
    </listitem>
    </itemizedlist>

    <para>
      Not all of these may work depending on what your particular
      hardware/BIOS setup supports and on the state of linux support for that
      hardware.
    </para>
  </sect2>
</sect1>

<sect1 id="hardware_requirements">
  <title>Hardware requirements</title>

  <sect2 id="hardware_supported">
    <title>What hardware is supported?</title>
    <para>
      Older systems have only APM support.  In general, if you are working with
      hardware that is older than 1997,  it will not have ACPI support, and if it's
      older than 2000, it will have only limited support. 
    </para>
    <para>
      Support for modern ATI and nVidia video chipsets  is spotty 
      under Linux. Older video chipsets tend to have better support.  Cards based on the ATI
      Radeon have support with workarounds.  This is very dependent on the version of X you happen
      to be using, and on the version of any X proprietary driver as well.
      [FIXME should test with earlier .6xxx nVidia to see if suspend works, just for shits and grins]
    </para>
    <para>
      For comprehensive lists of laptops, their configuration, and their
      functionality under ACPI in Linux, 
      see <link linkend="acpi_on_laptops">ACPI on Linux laptops</link>.
    </para>
  </sect2>

  <sect2 id="devices_supported">
    <title>What devices are supported?</title>
    <para>
      Suspend/resume for SATA devices is not working well yet.  Jens Axboe
      has a patch that will help for some users; see the <link linkend="sata_patch">SATA driver</link>
      section for more.
    </para>
    <para>
      Brightness controls for LCD panels is sometimes not controllable by ACPI; often, the
      vendor uses some proprietary method, having the BIOS adjust brightness directly
      when certain hotkeys are pressed. In this case you are liable to see odd messages in your log
      like these:
      <screen>
        kernel: atkbd.c: Unknown key pressed (translated set 2, code 0x85 on isa0060/serio0).
        kernel: atkbd.c: Use 'setkeycodes e005 &lt;keycode&gt;' to make it known.
      </screen>
    </para>
    <para>
      Various ethernet cards have problems, but there are patches. See the
      <link linkend="ethernet_card_patch">Ethernet cards</link> section
      for more.
    </para>
    <para>
      ATI Radeon cards usually need help for suspend to RAM. See the
      <link linkend="radeonfb_patch">RadeonFB patches</link> section
      for more. [FIXME and see if this helps X].
    </para>
    <para>
      See also the note above about supported hardware for information about
      other video devices.
    </para>
  </sect2>

  <sect2 id="bioses_supported">
    <title>Which BIOSes are supported?</title>
    <para>
      Any BIOS that claims to support ACPI can be used under Linux.  In practice,
      BIOSes older than 2001 that claim to have ACPI support are often broken.
      Current BIOSes are often broken too because they have broken DSDT tables 
      or missing ECDT tables.  
    </para>
    <para>
      If your DSDT is buggy, in the best case, Linux ACPI functionality will be enabled
      but some functions will not work; in the worst case, your system
      may freeze.  Fortunately, there is often a workaround available.
      See <link linkend="dsdt_editing">DSDT editing</link> for more
      information.
    </para>
    <para>
      If your ECDT is missing, there's a boot parameter, acpi_fake_ecdt, which 
      can help you.  See <link linkend="boot_reference">Boot parameters reference</link>
      for more information.
    </para>
    <para>
      Some BIOSes are known to be broken and they are included in a blacklist
      in the ACPI driver.  Systems with those BIOSes at this writing are:
    </para>

    <itemizedlist>
    <listitem>
      <para>Compaq Presario 1700</para>
    </listitem>
    <listitem>
      <para>Sony FX120, FX140, FX150M</para>
    </listitem>
    <listitem>
      <para>Compaq Presario 800, Insyde BIOS</para>
    </listitem>
    <listitem>
      <para>IBM 600E</para>
    </listitem>
    <listitem>
      <para>all systems with ASUS P2B-S BIOS</para>
    </listitem>
    </itemizedlist>
  </sect2>

  <sect2 id="check_bios">
    <title>How can I tell if my BIOS supports APCI?</title>
    <para>
      The most reliable way to tell is to boot with an ACPI-enabled
      kernel and look for ACPI messages in the log.
      You should see at least
    </para>
    <para>
      <screen>
        kernel: ACPI: Interpreter enabled
      </screen>
    </para>
    <para>
      and messages like this if you have PCI slots:
    </para>
    <para>
      <screen>
        kernel: ACPI: PCI Interrupt 0000:00:1d.7[A] -> Link [LNKA] -> GSI 11 (level, low) -> IRQ 11
      </screen>
    </para>
    <para>
      If you see messages like this:
      <screen>
	ACPI: System description tables not found
	ACPI-0084: *** Error: acpi_load_tables: Could not get RSDP, AE_NOT_FOUND
	ACPI-0134: *** Error: acpi_load_tables: Could not load tables: AE_NOT_FOUND
	ACPI: Unable to load the System Description Tables
      </screen>
      then your BIOS does *not* have ACPI support.
    </para>
    <para>
      If you want other ways to check your system, you can look at your BIOS settings; many
      systems have ACPI-related options in their BIOS menus, though not all. For
      example, the Dell XPS Gen 2, while fully ACPI-compliant, has no mention
      of ACPI in the BIOS settings at all.
    </para>
    <para>
      You can also
      run <application>acpidump</application>, which is packaged with most distributions. To run it, be
      root and at the command prompt, type
      <command>acpidump</command>.
    </para>
    <para>
      If your system is ACPI-compliant, <application>acpidump</application> should print out a long list
      of tables and their contents, including the RSDT and the DSDT.
      If you don't see a line something like
      <screen>
        DSDT @ [some hex address here]
      </screen>
      you may have a problem.  If <application>acpidump</application> produces no output, it probably
      has failed to find any tables.  Check the exit code; if it's
      0x0005 then you (probably) don't have ACPI support at all.
    </para>
    <para>
      If you want to look through memory yourself, and you have 32-bit hardware
      which is not EISA/MCA based, you could try looking
      for "RSD PTR" in 0e0000h through 0fffffh by grepping it out
      of /dev/mem, like this:
      <screen>
        # dd if=/dev/mem of=blot bs=64K skip=14 count=2
        # od -c -A x blot | grep 'R   S   D'
        01c9b0   R   S   D       P   T   R     312   D   E   L   L          \0
      </screen>
    </para>
    <para>
      If you see output like this, you know you have the root
      table stricture for ACPI, which means that you have at least
      some degree of support.
    </para>
    <para>
      Note that none of these methods guarantee that the BIOS support
      for ACPI is bug free, just that it exists.
    </para>
  </sect2>

  <sect2 id="unsupported_laptops">
    <title>When will my (unsupported) laptop be supported?</title>
    <para>
      If the problem is related to the video card, and you're using a proprietary
      driver,  the outlook is not good.  It depends however on your particular card
      and BIOS.  If posting your video card after resume helps your problem, then
      eventually that will be fixed because sooner or later that code will make it
      into X or into the kernel.  It's also possible that your video card vendor
      may provide X drivers that do the proper card reinitialization at some point.
    </para>
    <para>
      If the problem is related to hotkey support, some laptops have specific 
      hotkey drivers, but a generic hotkey driver is available which you should check
      out as well.  See the <link linkend="config_reference">
      Kernel configuration reference</link> for the CONFIG_ACPI_HOTKEY option.
    </para>
    <para>
      Detailed bug reports are extremely helpful, as are volunteers to do testing and
      debugging on their hardware.  See <link linkend="debugging_tips">Debugging tips</link>
      to get started.
    </para>
  </sect2>
</sect1>

<sect1 id="software_requirements">
  <title>Software requirements</title>

  <sect2 id="kernels_supported">
    <title>Which kernels are supported?</title>
    <para>
      All Linux 2.6 kernels and the current 2.4 series have ACPI support out
      of the box.  If you are running one of the 2.2 series, you are out
      of luck. Not all new features from 2.6 are backported into the 2.4 series 
      kernels.  Your favorite distribution probably has ACPI support turned
      on by default.  Checked for: Fedora Core x; Suse 9.x; Debian 3.x, Ubuntu, Gentoo.
    </para>
    <para>
      If a feature doesn't work for you in one kernel, try the next one, or even an 
      rc intermediate release, because so much changes from one week to the next.  
    </para>
    <para>
      For the very latest in ACPI support, however, you should build your own kernel
      and look at the most recent ACPI patches, as there is much hard work being done 
      on this subsystem.  The most recent patches can be found at
      <ulink url="ftp://ftp.kernel.org/pub/linux/kernel/peple/lenb/acpi/patches/release/">
      ftp://ftp.kernel.org/pub/linux/kernel/peple/lenb/acpi/patches/release/</ulink>.
    </para>
  </sect2>

  <sect2 id="latest_driver_and_utils">
    <title>What are the latest acpi driver / supporting utilities
       and where can I get them?</title>
    <para>
      Basic ACPI support is included in the linux kernel.  You need acpid if you want to
      capture ACPI events and take certain actions based on those events.  You do not
      need to use acpid if you want to do suspend to RAM or suspend to disk and you are
      willing to run a script by hand or work directly with the sysfs interface.  If you
      want to be able to shut down cleanly by pressing the power button, you should
      use acpid; in addition, if you want to hibernate or suspend on latop lid close,
      you need acpid.  See <link linkend="acpid">the acpid event handling daemon</link> 
      to learn how to build and use it.
    </para>
    <para>
      Here are some of the userspace utilities for APCI power management.  You don't
      have to use any of them to get APCI functioning, but they can be much more convenient
      than accessing <filename class="directory">/proc/acpi</filename>
      or sysfs directly.  This is not meant to be a comprehensive list.
      However, if you know of an application that
      is currently maintained and that you think should be on this list, 
      <ulink url="mailto:ariel@columbia.edu">let me know.</ulink>
    </para>
    <itemizedlist>
    <listitem>
      <para>
	acpitool -- command line utility to get battery/fan/temperature/cpu information or to
        suspend to RAM/disk, turn on/off fans, and control wakeup capable devices
      </para>
    </listitem>
    <listitem>
      <para>
	battstat-applet-2, bbacpi, wmacpi -- battery monitoring
      </para>
    </listitem>
    <listitem>
      <para>
	wmpower, yacpi -- battery, temperature and other monitoring
      </para>
    </listitem>
    <listitem>
      <para>
	powersave, with front ends kpowersave, gkrellm-powersave, wmpowersave -- all
	purpose utility covering APM, ACPI and other power management features
      </para>
    </listitem>
    <listitem>
      <para>
	xrg -- all purpose monitor that watches everything from CPU activity and battery
	status to the weather and stock market data
      </para>
    </listitem>
    <listitem>
      <para>
      </para>
    </listitem>
    </itemizedlist>
  </sect2>

  <sect2 id="binary_distributions">
    <title>Are binary distributions available?</title>
    <para>
      All major distributions come with ACPI support built into the kernel by default.
      Fedora ships out of the box with acpid and battstat-applet-2, Debian  
      has acpid and wmacpi, Suse has acpid and powersave, and Gentoo has acpid and quite
      a number of monitoring/power management utilities.  Check your distribution's documentation
      to see what prepackaged options you have.
    </para>
  </sect2>

</sect1>

<sect1 id="compilation_installation">
  <title>Compilation and installation</title>

  <sect2 id="prereqs_and_kernel_setup">
    <title>Prerequisites and kernel setup</title>
    <para>
      To build your own kernel with ACPI support, you need the following:
    </para>
    <para>
      Make sure that you're building with the appropriate version of 
      <application>gcc</application>
      (at this writing, at least version 3.2).
    </para>
    <para>
      Turn on these confguration options for base ACPI support:
      CONFIG_PM, CONFIG_ACPI and CONFIG_PNPACPI.
    </para>
    <para>
      For ACPI control of some basic devices, set these:
      CONFIG_ACPI_AC, CONFIG_ACPI_BATTERY, CONFIG_ACPI_BUTTON, CONFIG_ACPI_VIDEO, CONFIG_ACPI_FAN,
      CONFIG_ACPI_PROCESSOR, and CONFIG_ACPI_THERMAL.
    </para>
    <para>
      For suspend to RAM, set CONFIG_ACPI_SLEEP, and for suspend to disk, set
      CONFIG_SOFTWARE_SUSPEND, and also supply the name of the partition
      reserved for writing suspend data to CONFIG_PM_STD_PARTITION.
    </para>
    <para>
      For more details on these config options or for the other kernel configuration
      options for ACPI, see the
      <link linkend="config_reference">Kernel configuration reference</link>.
    </para>
  </sect2>

  <sect2 id="bios_settings">
    <title>Useful BIOS settings</title>
    <para>
      Most ACPI-capable BIOSes have settings that the user can tweak
      for power management.  For example, recent versions of the
      AMI BIOS have an entire section for ACPI settings, including
      ACPI-Aware OS, ACPI 2.0 compliance, BIOS->AML ACPI table, all of
      which should be enabled; Suspend to RAM support, and Repost video 
      on S3 resume which may be useful if your video doesn't come back
      after resume from suspend to RAM.  Check your BIOS to see what
      power management features it offers you.
    </para>
    <para>
      If you see APM settings in your BIOS you can ignore those.
      As long as you have ACPI built into your kernel and enabled,
      the APM settings will not be used.
    </para>
  </sect2>

  <sect2 id="boot_parameters">
    <title>Boot parameters</title>
    <para>
      You should not need to pass any special boot parameters
      once ACPI is built into the kernel.  If you run into problems,
      or you have special requirements,
      check the <link linkend="boot_reference">Boot parameters reference</link>
      for a comprehensive list.
    </para>
  </sect2>

</sect1>

<sect1 id="acpid">
  <title>The acpid event handling daemon</title>
  <sect2 id="what_is_acpid">
    <title>What is acpid and where do I get it?</title>
    <para>
      Older versions of acpid used to act as an intermediary between
      the kernel and the BIOS, looking up hex values that could
      be used to invoke certain sleep types and installing sleep methods; it also used to
      provide battery information and it had the entire AML interpreter
      in it.  But it didn't support suspend to disk or suspend to RAM.
    </para>
    <para>
      These days, the entire interpreter for AML now lives in the kernel.
      I stopped maintaining this document shortly after that patch
      <ulink url="http://www.linuxhq.com/kernel/v2.4/3-ac8/acpi-20010413.diff">
      (http://www.linuxhq.com/kernel/v2.4/3-ac8/acpi-20010413.diff)</ulink>
      got accepted about 4 years ago.
      It singlehandedly added around 72000 lines of code to the kernel. One developer [fn1] is pretty
      sure that ACPI was designed by a bunch of monkeys on LSD, but if it had,
      it would at least be visually appealing.  And this ain't.
    </para>
    <para>
      OTOH, the acpid daemon has become much simpler. It now watches for all acpi-generated
      events and allows the user to define the appropriate action to take on receiving those
      events.
    </para>
    <para>
      Most distributions come with acpid out of the box.  If you want to
      build your own,  you'll find the latest version at
      <ulink url="http://sourceforge.net/projects/acpid/">
      http://sourceforge.net/projects/acpid/</ulink>
    </para>
    <para>
      [fn1] See <ulink url="http://lkml.org/lkml/2005/7/31/219">
      http://lkml.org/lkml/2005/7/31/219</ulink>.
    </para>
  </sect2>

  <sect2 id="compiling_acpid">
    <title>How do I build and install acpid?</title>
    <para>
      Make yourself a build directory and untar the file:
      <command>zcat acpid-1.0.4.tar.gz | tar xvfp -</command>
      cd into the directory:
      <command>cd acpid-1.0.4</command>
    </para>
    <para>
      If you download the tarball, edit the Makefile if you're using gcc 4.x:
      change the line
      <code>
      CFLAGS = -Wall -Werror -g $(DEFS)
      </code>
      to read
      <code>
      CFLAGS = -Wall -g $(DEFS)
      </code>
      (This is fixed in cvs.)
    </para>
    <para>
      build it:
      <command>make</command>
      install it:
      <command>make install</command>
        This puts acpid in /usr/sbin and acpi_listen in /usr/bin
        It also installs the man pages.
    </para>
    <para>
      These programs use <filename class="directory">/proc/acpi/events</filename>
      (boo).   When will they use <filename class="directory">/sys</filename>?
    </para>
  </sect2>

  <sect2 id="running_acpid">
    <title>How do I use acpid?</title>
    <para>
      Linux sees ACPI events, in some cases takes an action, and then writes
      a description of the event to <filename class="directory">/proc/acpi/events</filename>
      so that userspace
      applications can take actions as well. Acpid watches 
      <filename class="directory">/proc/acpi/events</filename>
      and, for every event logged there, looks at its set of rules to see 
      what action(s) to take.  These actions are specified
      by you, the user.  
    </para>
    <para>
      Acpid looks for its rules by default in /etc/acpi/events at all files in 
      that directory (no subdirectory walking though).  Each file in there is 
      expected to contain rules that tell acpid what to do on each event.
    </para>
    <para>
      Each file may have blank lines  or comments starting with #
      Then you must include at least one line defining
      an event and one line defining an action.
    </para>
    <para>
      Here's an example:
    </para>
    <para>
    <programlisting>
      # This is a sample ACPID configuration

      event=button/power.*
      action=/sbin/shutdown -h now
    </programlisting>
    </para>
    <para>
      That file ships with Fedora Core 4 and tells acpid to shut down when the power button
      is pressed (so you don't have to give the three-finger salute).
    </para>
    <para>
      %e and %% are special strings; if you use %e in the event description
      or in the action description, the full text of the event as described
      in the previous section will be substituted into the string, and
      if you use %% in either description, the character % will be substituted in.
      If you use % in any other combination, you'll get an error.
    </para>
    <para>
      You can define multiple actions for the same event, but they won't
      necessarily be processed in the order you list them in the file.
    </para>
    <para>
      You can also put multiple event lines in one file and use the same action for
      all of them.  [FIXME examples would be nice]
    </para>
    <para>
      If you have acpid source from CVS or tarball, you can look at
      more interesting examples such as the battery.sh script
      which is intended to be used from one of these rule files.
      It reacts on any battery event, checks to see whether
      the system is on AC or battery, and sets or disables hard
      drive spindown time appropriately.  Note that this script
      may not work for you out of the box, as your AC adapter
      may have a different name (mine is called 
      <filename class="directory">/proc/acpi/ac_adapter/AC</filename>);
      it's here as an example only.
    </para>
    <para>
      On FC4 you are expected to put all your fancy scripts
      into /etc/acpi/actions but nothing in the acpid
      code requires this.  Put them where you want.
    </para>
  </sect2>

  <sect2 id="acpid_events">
    <title>What events will acpid respond to?</title>
    <para>
      It is not possible to provide a comprehensive list, because the list
      of events depends on your vendor's hardware and their ACPI implementation.
      However, it is possible for you to figure out what events will be
      issued on your hardware by looking at 
      <filename class="directory">/sys/firmware/acpi</filename> and collecting
      some information.
    </para>
    <para>
      First, let's see what an event looks like.
      If you are running acpid, and you are running ACPI with any applet to monitor
      battery status of control cpu speed, you can look in 
      <filename>/var/log/acpid</filename> at
      events it has received.  You may see messages like this:
    </para>
    <screen>
      completed event "processor CPU0 00000080 00000004"
      received event "ac_adapter AC 00000080 00000001"
      received event "battery BAT0 00000080 00000001"
      received event "button/power PBTN 00000080 00000001"
    </screen>
    <para>
      Each event as logged consists of the device class name, the bus id name, the event 
      type, and the event data.  Device class names are standardized, and you can get 
      the list by looking for all #defines of "CLASS" in the kernel code in drivers/acpi.  
      My list is:
    </para>
    <para>
      ac_adapter, battery, button, container, embedded_controller, fan,
      Hotkey (because the asus driver got the word "hotkey"),
      lid, memory, pci_bridge, pci_irq_routing, power, power_resource,
      processor, sleep, system_bus, system, thermal_zone, video
    </para>
    <para>
      Note that some of these are subclasses; power, sleep and lid are subclasses of 
      button, and they'll get written as button/lid, button/power and button/sleep in the log.
    </para>
    <para>
      Bus IDs are not standardized; they are defined in a vendor's implementation.  Fortunately, 
      the names vendors use are similar and usually recognizable.
    </para>
    <para>
      You can find out which Bus IDs your vendor is using on your current hardware by looking in
      <filename class="directory">/sys/firmware/acpi/namespace/ACPI/</filename>.
      My system shows
     </para>

    <screen>
      ls /sys/firmware/acpi/namespace/ACPI/
      CPU0  CPU1  _SB  _TZ
      ls /sys/firmware/acpi/namespace/ACPI/_SB
      AC  BAT0  LID  MB1  PBTN  PCI0  SBTN
      ls /sys/firmware/acpi/namespace/ACPI/_SB/PCI0/
      AGP  AUD  IDE0  ISAB  LNKA  LNKB  LNKC  LNKD  LNKE  LNKF  LNKH  MB2  MB3  MODM  PCIE  USB0  USB1  USB2  USB3  USB4
    </screen>

    <para>
      You may decide you don't need to know what the event type is; for example, if you get a 
      battery event, you might look at <filename>/proc/acpi/battery/BAT0/info</filename>
      (or <filename>BAT1/state</filename>, or whatever your battery device is called), check
      the remaining capacity and take any appropriate actions.
    </para>
    <para>
      However, there is a list of event types in the ACPI specification.  Here's the summary:
    </para>
    <para>
       For all devices, 0 = bus check (time to rescan the bus); 2 = device removed or added;
       3  = device awakened; 4 = device eject, 5 = device removed or added ("device check light",
       don't ask me what the difference between this and 2 is); and some other events
       that you probably won't care about as a user.  See page 142 of the specification
       if you want the rest.
    </para>
    <para>
      For specific devices:
    </para>
    <para>
      Battery: 0x80 = battery status changed, 0x81 = battery information has changed
      (i.e. you have a different battery in there now); 0x82 = check battery maintenance flags.
    </para>
    <para>
      Power source: 0x80 = power source status changed. (Think AC adapter.)
    </para>      
    <para>
      Thermal zone: 0x80 = thermal zone temperature changed; 0x81 = thermal zone trip points
      changed; 0x82 = thermal zone device lists changed; 0x83 = values in thermal relationship
      table changed
    </para>
    <para>
      Power button: 0x80 = power button pressed.  <emphasis>Warning:</emphasis> If the power
      button is pressed with the system in S1 through S4, you will not see this event;
      instead you will see a Device Wake (0x02)!
    </para>
    <para>
      Sleep button: 0x80 = sleep button pressed. <emphasis>Warning:</emphasis> If the sleep
      button is pressed with the system in S1 through S4, you will not see this event;
      instead you will see a Device Wake (0x02)! 
    </para>
    <para>
      Lid: 0x80 = Lid status changed (either open or closed).
    </para>
    <para>
      Processor: 0x80 = number of supported processor performance states (P states) has changed;
      0x81 = number or type of supported power states (C states) has changed; 0x82 =
      number of supported throttling states has changed.
    </para>
    <para>
      <!-- p574 -->    
      video (part 1): 0x80 = state of one of the displays attached to the graphics adapter has
      been toggled; 0x81 = re-enumerate all devices on the adapter (i.e. a device has been 
      added or removed); 0x82 = cycle display output (next display activated and if 
      the last one was active then the first one now is); 
      0x83 = next display activated; 0x84 = previous display activated.
      Note: for these events, when a new display is activated, Linux deactivates the previously active one.
      If you want more than one display to be active, you should activate them by using the
      <filename>/proc/acpi/video/VID/*/state</filename> interface.  See 
      <link linkend="proc_entries">Proc entries reference</link> for the /proc
      entries.  Also, I'm unsure if cycling the display output really should put you back to 
      the first device if you are at the end of the list; at least, Linux doesn't appear
      to do this, from a quick scan of the code.
    </para>
    <para>
      <!-- p 578 -->
      video (part 2): 0x85 = display brightness increased one level and if it was at max, it got set to
      min level; 0x86 = display brightness increased one level and if it was at max, it 
      stayed there; 0x87 = display brightness decreased one level and if it was at min, it 
      stayed there; 0x88 = display backlight turned off; 0x89 = display off
      WARNING: these values are right out of the ACPI 3.0 spec.  But they are not the
      values Linux uses!  It uses: 0x82, 0x83, 0x84, 0x85, 0x86 for each of these things
      in order.  Uh oh... I don't have (ACPI) brightness control support, so I can't test this to 
      see what should happen.  Anybody?
    </para>  
    <para>
      Some events that Linux passes on are not defined in the spec; that is, I can't find 
      a table with numbers for these. I got the values by looking for invocations of 
      acpi_bus_generate_event() in the kernel acpi driver code, and checking the event 
      passed in that function.  
    </para>
    <para>
      thermal zone: 0xf0 = critical temperature trip point is being passed which requires
      immediate shutdown; at this point Linux will shut down by calling 
      <application>/sbin/poweroff</application>.  You don't really have much time to process this 
      event. :-) 0xf1 = critical temperature trip point is being passed which requires
      the OS to put the system into S4 (hbernate) if that state is supported.  The Linux kernel
      does not yet do this.  It has a comment placeholder where the code ought to go.
    </para>
    <para>
      If you use the generic hotkey driver (CONFIG_ACPI_HOTKEY), then when you
      press an authorized hotkey, you'll get an event sent to 
      <filename>/proc/acpi/events</filename> for
      it.  That list is described in <link linkend="hotkeys">How do I use the hotkey driver?</link>
    </para>
    <para>
      No, I'm not documenting the state data; look it up your own darn self :-) 
    </para>
  </sect2>

  <sect2 id="acpid_tracking">
    <title>How can I keep track of what acpid thinks it's doing?</title>
    <para>
      Apcid logs all of its activity to <filename>/var/log/acpid</filename> by default.
      Check your init scripts to see where your distribution
      directs its logging.
    </para>
    <para>
      You can also run <command>acpi_listen</command>.  This command will connect to acpid
      and write every event that acpid sees to stdout, in exactly the format the event
      appears in <filename>/var/log/acpid</filename>, but without the extra commentary.
    </para>
  </sect2>

  <sect2 id="acpid_scripts">
    <title>Where can I find other cool acpid scripts?</title>
    <para>
      A few nice Thinkpad scripts can be found at
      <ulink url="http://www.thinkwiki.org/wiki/Category:Scripts">
      http://www.thinkwiki.org/wiki/Category:Scripts</ulink>
    </para>
    <para>
      Unfortunately, scripts are very dependent on your particular hardware
      configuration.
    </para>
    <para>
      Some folks have put up acpid scripts on their pages
      describing the installation of some distribution on
      their laptop.  Check <link linkend="acpi_on_laptops">these resources</link>
      for more information.
    </para>
  </sect2>

</sect1>

<sect1 id="cpu_management">
  <title>CPU management under ACPI</title>
  
  <sect2 id="cpu_management_overview">
    <title>CPU management overview</title>
    <para>
      APCI gives you unprecedented control over your CPU's power consumption.  You can control
      power usage in three different ways: setting idling power states, changing cpu frequency, and 
      throttling the CPU.
    </para>
  </sect2>

  <sect2 id="cpu_management_idle">
    <title>CPU idle power states</title>
    <para>
      First, the CPU can enter different idle power states, C1 through Cn (usually C1 through C4).
      If a processor is in state C0, it is working normally; in any other state, it is
      idle (doing no work).  Lower power states use less power but the CPU will take longer to 
      transition to a higher power state. So if your CPU is in C4 it will use less power than in 
      C3 but it will take longer to come out of idle than from C3.  
    </para>
    <para>
      You don't have to do anything
      to make the CPU go into the appropriate idle state; the kernel will place the CPU into a 
      lower power state automatically when it is not busy.  However, you do need to build
      this capacity into the kernel by enabling CONFIG_ACPI_PROCESSOR.
      See the <link linkend="config_reference">kernel configuration reference</link>
      for the CONFIG options.  
    </para>
    <para>
      You can look at the <filename>/proc/acpi/processor/power</filename> file to see
      how long your CPU spends in each state; see 
      <link linkend="proc_entries">Proc entries reference</link> for more on this
      file.  You can also look at 
      <filename>/sys/module/processor/parameters/max_cstate</filename> to see what the lowest
      power state the kernel will give you is; see 
      <link linkend="sysfs_entries">Sysfs entries reference</link> for more on
      that.
    </para>
    <para>
      And you can adjust max_cstate by using the processor.max_cstate boot parameter.  In some cases
      machines that enter C3 or C4 produce a loud whine, and you may want to limit your system
      to C1 and C2.  In some cases you may want your system to enter C3 or C4 but it's been blacklisted 
      by the kernel and limited to C2; you can use this same parameter to override the blacklist.
      See <link linkend="boot_reference">Boot parameter reference</link> for details.
    </para>
  </sect2>

  <sect2 id="cpu_management_freq">
    <title>CPU frequency management</title>
    <para>
      Second, you can also run the CPU at lower frequencies when it isn't doing so much work.
      If you're spending most of your time typing text instead of compiling, this can be very useful
      for power savings.  In ACPI lingo, the CPU enters various P-States, P0 through Pn, where
      at P0, the CPU is running at its highest frequency and at Pn it runs at a lower frequency
      the greater the value of n.  These performance states are only valid when the CPU is in power
      state C0; the rest of the time the CPU is in some idle state and so adjusting its
      clock frequency doesn't make any sense.
    </para>
    <para>
      To benefit from this, you'll need to 
      enable CPU frequency control by setting CONFIG_CPU_FREQ.  Then you can choose which 
      of several performance managers to build in; these adjust the frequency based on different
      criteria.   Then you can choose which hardware-level driver to build in.  Only certain of these
      drivers support ACPI P-States; the rest use a proprietary method of regulating
      CPU frequency and are not discussed further in this document.
      Further, of those that use the designated P-States, only the ACPI P-States driver 
      (CONFIG_X86_ACPI_CPUFREQ) actually notifies the ACPI subsystem of P-State changes.  
      If you think this is confusing, you're right.
    </para>
    <para>
      After your kernel is set up, you can either use one of several userspace
      applications to automatically set your CPU to a lower fequency depending on the load,
      or you can use an applet that lets you set the frequency manually as you desire,
      or you can use one of the performance managers that adjusts frequency for you in
      kernel space. For all the details, see <link linkend="cpufreq_reference">CPU_FREQ reference</link>.
     </para>
  </sect2>

  <sect2 id="cpu-management_throttling">
    <title>CPU throttling</title>
    <para>
      Third, you can throttle your CPU.  This means that you 
      force the cpu to be idle a fixed percentage of its cycles per second.  Throttling states
      are called T1 through Tn, where in T1 the CPU has no forced idle cycles, and the percentage
      goes up the greater n is. For example, on my system, T4 forces the CPU to be idle 
      for half of the cycles.
    </para>
    <para>
      This is different from changing the frequency, which makes the cpu have fewer cycles
      per second, and it's different from running in a C state other than C1, because 
      those are states where the CPU is idle for all cycles.
    </para>
    <para>
      If you have a certain amount of work to get done, then throttling the CPU will
      cause the work to take longer to get done. However, if temperature is a concern,
      then this will keep your CPU running cooler.
    </para>
    <para>
      Note that this does not reduce voltage, and since all tasks will take longer (since
      the CPU is forced idle part of the time), you actually use more power to get any 
      given task done.
      This is in contrast to CPU frequency management; when the CPU frequency is lowered,
      voltage is lowered too, and any given task should draw less power unless it requires
      the CPU to run full out for the duration of the task.
    </para>
    <para>
      You can check which throttling states are supported by your CPU by looking at
      <filename>/proc/acpi/processor/CPU*/throttling</filename>.  
      This file will also show you what percentage
      of idle time each state enforces.
      You can set the current throttling state for your CPU by writing the state number to 
      <filename>/proc/acpi/processor/CPU*/throttling</filename>.   
      Read it back to make sure the change works;
      if it doesn't, you may have a bug in your DSDT or elsewhere.
    </para>
    <para>
      Note that throttling states only work when the CPU is in the power state C0.  But 
      they work for any 
      performance state (P-state);  this means that no matter what frequency the CPU is running at, 
      you can still do throttling.   
      For information on how to do this, see 
      <link linkend="thermal_management">Thermal management</link>.
    </para>
  </sect2>
</sect1>

<sect1 id="thermal_management">
  <title>Thermal management</title>
  <!-- trip points for system shutdown etc, cpu thermal stuff. thermal zones. -->

  <sect2 id="thermal_overview">
    <title>Overview of thermal management</title>
    <para>
      ACPI provides several means for monitoring and controlling system temperature.
      Via thermal zones, you can adjust the system cooling mode when it's too hot,
      you can turn on and off fans when you reach certain temperatures, and you
      can throttle your CPU when it gets too hot, taking into account the performance
      state it's running in. Not all platforms support all of these features, but 
      the ACPI 3.0 specification provides all of these mechanisms.
    </para>
  </sect2>

  <sect2 id="thermal_zones">
    <title>What are thermal zones?</title>
    <para>
      If your vendor's implementation of ACPI supports thermal management, you'll have
      one or more thermal zones, which you can monitor by checking 
      <filename class="directory">/proc/acpi/thermal_zone</filename>
      for these devices.  They'll be called something like THM or THRM0.
    </para>
    <para>
      I haven't seen a system with multiple thermal zones.  Typically a system
      has one big thermal zone which includes the entire interior region of
      the case.  Practically speaking, it must be connected to a sensor somewhere,
      probably by the CPU.  
    </para>
    <para>
      Linux should poll the temperature every so many seconds.  In practice, 
      however, Linux tries to figure out how often to poll by invoking the  _TZP method,
      which many vendors don't provide.  When that fails, Linux disables polling altogether.
      Fortunately, you can enable it by echoing a number to the file, for example,
      <command>echo 30 &gt; /proc/acpi/thermal_zone/*/polling_frequency</command>,
      to have Linux check the temperature every 30 seconds.
    </para>
    <para>
      You can monitor the temperature for each thermal zone yourself by reading the file
      <filename>/proc/acpi/thermal_zone/*/temperature</filename>.
    </para>
  </sect2>

  <sect2 id="cooling_modes">
    <title>What are cooling modes and how do I change them?</title>
    <para>
      A cooling mode is a description of how your system is cooled in a certain
      temperature range.
      Your cooling mode can be critical, passive, or active.  Active cooling means
      that a fan or other cooling device can be turned on when the temperature
      passes a critical point.  Passive cooling means that devices can be
      put into a lower power state when the temperature is too hot.
      Critical cooling means that when the temperature passes one trip point,
      the so-called "hot point", 
      the OS will transition into S4 (suspend to disk) if possible,
      and if the temperature passes a second trip point, called the
      "critical point", the OS will shut down the system.
    </para>
    <para>
      If your platform supports it, Linux will set the cooling mode to 
      active by default.  If this isn't successful, but both
      active and passive modes are supported, then 
      the cooling mode which supports the lowest trip point is
      the one in use.  If only one of passive or active cooling
      modes is supported, Linux will use that.  Failing that, it will fall back to critical
      cooling mode, which must be supported by your vendor.
    </para>
    <para>
      Some platforms allow you to change the cooling mode.  You can do this by 
      echoing 1 to <filename>/proc/acpi/thermal_zone/*/cooling_mode</filename>
      to set passive cooling, 
      or 0 to <filename>/proc/acpi/thermal_zone/*/cooling_mode</filename>
      to set active cooling.
      Critical cooling will always be active, in case your system heats
      up so much that drastic measures must be taken, even with fan use
      or power reduction.
    </para>
  </sect2>

  <sect2 id="trip_points">
    <title>What are trip points and how do I set them?</title>

    <para>
      Trip points are set temperatures that, when the system temperature
      reaches them, trigger some sort of action.  Typically this can
      be a change in cooling mode, or something more drastic. 
      The critical cooling mode has two predefined trip points.  If 
      the system reaches the first one, called the "hot point", Linux will try to put the
      system into S4 (suspend to disk) if possible, 
      and if the temperature passes the second one, called the
      "critical point", Linux will call /sbin/shutdown -h now.
    </para>
    <para>
      You can define multiple trip points each with their own
      cooling policy.  If you do, they'll show up in 
      <filename>/proc/acpi/thermal_zone/*/trip_points</filename> like this:
      <screen>
	critical (S5): 100 C
	passive: 97 C: tc1=4 tc2=3 tsp=40 devices=0xcf6b6d80
      </screen>
    </para>
    <para>
      You can set critical, hot, passive, and up to 9 active trip points. 
      Here's how you do it: echo a string of numbers to 
      <filename>/proc/acpi/thermal_zone/*/trip_points</filename>
      separated by a colon.  These numbers are the various trip points in Celsius.
      NOT IN Fahrenheit!  So you *can*
      <command>echo 99:80:35:75:60:55:50:45 &gt; /proc/acpi/thermal_zone/*/trip_points</command>
      to set the critical trip point at 99C, the "too hot, suspend now" trip point at 80C,
      the passive trip point at 35C, the first active trip point at 75C, the next
      one at 60C, and so on through the fifth active trip point at 45C, but in practice
      that's a lot of trip points.  You probably only need one or two; after all,
      how many extra fans do you have?  However, Linux expects to see at least 5 values,
      and if it doesn't see them it throws an error and refuses to process the change.
      So even if your system only does passive cooling, you must supply values for active[0] and
      active[1].  Just set them to 0 if they don't make sense for your platform.
    </para>
    <para>
      Unfortunately, if you write values to trip_points (at least 5) and these other cooling
      methods are not supported, Linux will not inform you about it.  It will
      silently accept the values and move on. On my system I can't even reset
      the lone critical trip point permitted me; but no errors are generated; the
      only way I can tell is to read the trip_points file again and see that it hasn't 
      changed.
    </para>
  </sect2>

  <sect2 id="throttling_and_pstate_limits">
    <title>What are throttling/performance state limits and how do I use them?</title>
    <para>
      These limits set the highest (highest frequency) P-State, and highest (least throttling) T-state
      your platform is permitted to use under certain circumstances, where P0 is a higher
      P-State than P1, and T0 is a higher T-state than T1. Sorry for the lousy terminology.
    </para>
    <para>
      You can see what the current throttling/p-state limit is, by looking at the file
      <filename>/proc/acpi/processor/limit</filename>.  
      Look at the active limit, which will show a performance state, like P0, 
      and then a throttling state, like T0. 
    </para>
    <para>
      To set a limit, write two numbers separated by a colon, like "0:0" into 
      <filename>limit</filename>.  
      The first number is the processor performance state, and the next number is the 
      processor throttling state.
      This will set the user limit, which you also see when you read that file.  The active limit
      is chosen as the maximum of the user and thermal limit T-state numbers; i.e. if the user 
      limit is T2 and
      the thermal limit is T3 then the active limit will be T3.
    </para>
    <para>
      Unfortunately, Linux does not seem to use the first number for anything.  It always uses the value
      of 0 to update its internal copy of what it thinks the P-State is for display in the limit file.  
      Maybe that's ok, since it never actually sets the P-State from that value :-(
    </para>
    <para>
      Warning, esoterica: Only the ACPI P-States cpufreq driver updates the CPU's P-States.  This file could
      either show the actual P-State (and update it on demand) for that one driver,
      or it could map frequency changes from all drivers into P-States by name, 
      and reflect the change by changing frequency according to the registered
      cpufreq driver.  Right now it just leaves the Px value around in the limits
      file to be confusing to the user, the worst of both worlds. 
    </para>
    <para>
      In any case, the second value does get stuffed into the user limit thermal value, and you
      can verify that by reading the file.  It takes effect immediately.  Note that the user limit
      can never be a higher (less throttling) state than the thermal limit; for example, if
      the thermal limit is T1, then the user limit cannot be T0.
    </para>
  </sect2>

</sect1>

<sect1 id="hotkeys">
  <title>ACPI generic hotkey driver</title>
  <sect2 id="what_is_hotkey_driver">
    <title>What is the generic hotkey driver and how do I use it?</title>
    <para>
      The generic hotkey driver allows you to make those nifty hotkeys on your
      laptop work.  The concept is simple; your laptop has a hotkey that Linux
      doesn't understand and that has no effect.  You expect it to actually
      set the brightness of your LCD to max, for example.  So, you define a function that
      includes the ACPI event number generated by your hotkey, the hotkey driver
      event number that corresponds to the function you want the key to do 
      (here, increase brightness),  information required to find the right
      video device, and the ACPI method name for increasing brightness.
      Once the function is set up, any time you press the hotkey, 
      an event will be generated that acpid can pick up, and once
      you define the right rule for acpid, you'll have your hotkey
      working.
    </para>
  </sect2>

  <sect2 id="hotkey_supported_laptops">
    <title>How can I tell if my laptop supports the generic hotkey driver?</title>
    <para>
      This does not work for all laptops; your laptop must
      generate an ACPI event when you press the particular hotkey you
      want to use.  This means that in your DSDT, you will have something
      like \_SB.PCI0.LPC.EC.HKEY.BTIN () (IBM laptops), or 
      Name (_HID, "ATK0100") (ASUS), or Device (HKEY) (Panasonic).
    </para>
    <para>
      If you want to know if your hotkeys generate ACPI events, 
      one way you may test this is to turn on debugging (CONFIG_ACPI_DEBUG = y)
      in your kernel, boot up, <command>echo '0xffffffff'</command> to both 
      <filename>/proc/acpi/debug_level</filename> and 
      <filename>/proc/acpi/debug_layer</filename>, and then press a hotkey.  Just one!  Once!
      This will either generate a lot of error messages in your log, or
      none at all. If it generates none, you are out of luck.  Otherwise,
      you should be able to use this driver. [FIXME see which parts of the debug
      layer we can minimally turn on to get useful messages.]
    </para>
  </sect2>

  <sect2 id="hotkey_get_event_number">
    <title>How can I get the ACPI event number for my hotkey?</title>
    <para>
      You can try just pressing the key and see if anything shows up in 
      <filename>/var/log/messages</filename>.  If not, you'll have to resort to the method
      described above, i.e. build in ACPI debugging, turn on all
      debugging bits, and then slog through the log.
    </para>
    <para>
      The event number that your hotkey generates can then be retrieved by looking for lines
      in your log like "ev_queue_notify_reques: Dispatching Notify(80)".  
    </para>
  </sect2>

  <sect2 id="hotkey_function">
    <title>How do I set up a hotkey function?</title>
    <para>
      Let's take our earlier example. Say your laptop has a hotkey that should
      set the brightness of your LCD to max.  So, you define a function that
      includes the event number generated by your hotkey (which you must determine
      by looking at log output after pressing the hotkey), the appropriate hotkey driver 
      event number, in this case 0x86, the ACPI bus name on your platform, the ACPI full
      path name for your LCD, and the AML method you are going to call, which in this 
      case is _BCM, the AML method to control the brightness level.  
    </para>
    <para>
      On my system, if Dell actually had hotkeys implemented through ACPI, which it
      doesn't, I'd do the following:
      <screen>
	echo '0:_SB::_SB.PCI0.AGP.VID.LCD:_BCM:128:136' &gt; /proc/acpi/hotkey/event_config
      </screen>
      I've used a made-up value for the event number generated by pressing the hotkey,
      since Dell hotkeys don't generate ACPI events, but the rest is correct for my platform.
      I could then verify that the setup worked by looking in the log for errors and by
      reading <filename>/proc/acpi/hotkey/event_config</filename>, which would give me 
      <screen>
	_SB_:LDD_:_DSS:128:136
      </screen>
    </para>
    <para>
      Let's look at that in a little more detail. 
      In the example above, we have 7 arguments, which you must always provide to add a new key.
      The first argument must be 0 which indicates that this is a new key definition. 
      The second argument is the name of the bus on which your device sits that you're going
      to affect; the LCD panel on my system is on the _SB bus. The third argument must be omitted
      for event-based key definitions.  The fourth argument is the full ACPI namespace
      path name of the device, and the fifth argument is the AML method you are going to 
      call.  The sixth argument is the event number that your key press sends to the
      ACPI driver, and the seventh argument is the hotkey driver event number which the
      driver will use to look up the event in its tables.
      For the seventh argument, you can use any hotkey event number you like (as long as it's
      known to the driver), but you may kick yourself
      later when you have to read your script and understand what it does.
    </para>
    <para>
      You can also set up keys to use a polling method; I'll cover that in a future
      version of this document. [FIXME]
    </para>
    <para>
      Fun fact: you don't have to map the hotkey to a method that has anything to do 
      with the intended function of the hotkey, or with the intended meaning of the
      event number you chose from the hotkey driver event list.  So you could map
      your wireless activation hotkey to turn of your fan via the _OFF control method, 
      if your fan supports  that control method. I'm not saying you should; I'm just saying you *could*.
    </para>
    <para>
      To remove the key definition, just do 
      <command>echo '1:::::128:136' &gt; /proc/acpi/hotkey/event_config</command> where the
      128 should be replaced with the actual ACPI event generated by the key press, and the 136
      should be replaced with the hotkey driver event number you actually used.  
    </para>
    <para>
      To change the definition, just put the new definition to 
      <filename>/proc/acpi/hotkey/event_config</filename>
      but use '2' as the first argument, which indicates that the key definition already
      exists and should be updated with the new values.
    </para>
  </sect2>

  <sect2 id="hotkey_driver_event_nums">
    <title>What are the hotkey driver event numbers?</title>
    <para>
      The list, grabbed from hotkey.c, is
    </para>
    <para>
      video (see video events above for more on what these do): 
      <itemizedlist>
	<listitem>
	  <para>
	    0x80, cycle output device hotkey pressed; 
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x81, output device status change hotkey pressed (maybe it disconnects one of the devices);
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x82, cycle display output hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x83, activate next display output hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x84, activate previous display output hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x85, cycle display brightness hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x86, increase display brightness hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x87, decrease display brightness hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x88, set display brightness to zero hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x89, turn display off hotkey pressed
	  </para>
	</listitem>
      </itemizedlist>
    </para>
    <para>
      sound (why are these here? they aren't ACPI related):
      <itemizedlist>
	<listitem>
	  <para>
	    0x8a, volume mute hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x8b, volume increase hotkey pressed;
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x8c, volume decrease hotkey pressed
	  </para>
	</listitem>
      </itemizedlist>
    </para>
    <para>
      sleep states buttons:
      <itemizedlist>
	<listitem>
	  <para>
	    0x8d, Suspend to Ram hotkey pressed,
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x8e, Suspend to disk hotkey pressed,
	  </para>
	</listitem>
	<listitem>
	  <para>
	    0x8f, Soft power off hotkey pressed
	  </para>
	</listitem>
      </itemizedlist>
    </para>
  </sect2>

  <sect2 id="hotkey_apcid_action">
    <title>What should acpid do after I press a hotkey?</title>
    <para>
      Once the definition is set up, if I pressed the hotkey, an event of type 
      "Hotkey Hotkey 0x00000086 0" would be generated, 
      and acpid could pick it up and do the right thing with it.  
      The right thing is already almost predefined:  
      it should <command>echo "136:1::100" &gt; /proc/acpi/action</command>
      where 136 is the event code that acpid was given in 
      <filename>/proc/acpi/events</filename> converted to decimal, the 
      "1" means it is event based rather than poll-based, i.e. the event was read from 
      <filename>/proc/acpi/events</filename>,  
      the third missing argument is only needed for poll-based hotkeys, and the 100 is the argument
      to _BCM to  set the brightness to the maximum level.
    </para>
    <para>
      The trick is that most of these methods actually don't do exactly what you
      want the hotkey to do. Here's a summary of the relevant AML methods from the
      ACPI spec.
    </para>
    <para>
      _BCM controls brightness.  Pass the number (percent of 100) to set the level to.
      Supported brightness levels can be retrieved by reading the file
      <filename>/proc/acpi/video/VID/*/LCD/brightness</filename>
      (or CRT, or whatever device you are checking).
      That means that if you have a hotkey for increasing brightness, mapping it
      to this method will not be enough.  You should use a script that gets the current
      brightness, checks the supported levels, and sets the next one. That script
      can use <filename>/proc/acpi/action</filename>, but it will have to have 
      figured out the right brightness level as the argument to _BCM first.
    </para>
    <para>
      _DSS makes the display active or inactive. Pass 0x80000000 to inactivate, and
      0x80000001 to activate.  You can see the state of each device by 
      reading the file <filename>/proc/acpi/video/*/LCD/state</filename>
      (or CRT, or whatever device you are checking).
      That means that if you have a hotkey to switch between CRT and LCD, mapping
      it to this method will not be enough.  You should use a script that gets the
      current active device, inactivates it, and sets the other one as active.  
    </para>
    <para>
      There are no methods for sound control in ACPI; that's not really a 
      power management feature.  In order to get the sound-related hotkeys to work,
      you may have to have acpid run alsamixer or some such to do the right thing.
    </para>
    <para>
      The sleep state hotkeys are another bit of a kludge.  What you want to do here
      is to have acpid do any prep work for the suspend or power off; for suspend, you
      may have modules you want to remove, and so on.  Then you want to actually
      do the suspend by echoing the right state into 
      <filename>/sys/power/state</filename>, and finally
      do the right thing on wakeup, by reinserting modules and so on.  For poweroff,
      you can have acpid call /sbin/shutdown -h now, or whatever other shutdown
      mechanism seems good to you. Once again, these hotkeys must be set up
      with placeholder bus names, device paths, and AML method names; these items
      are only there so that the hotkey driver will register the key definition 
      and not throw an error.
    </para>
    <para>
      So what this means is that in all of these cases you are going to use a script to
      handle the event.  There is perhaps one exception: if you have a hotkey that
      turns off the display, or turns the brightness down to zero, you can 
      map that directly to the appropriate method with a fixed argument.
      In the rest of these cases, you still have to pass a valid bus name, 
      device path, and AML method name, so choose something harmless and
      then don't ever use <filename>/proc/acpi/action</filename> with it.  
      I recommend _SB for the bus name,
      _SB.PBTN (or whatever your power button is called) for the device name, 
      and _PSW for the method name, since you won't need these for anything else.
      This assumes your power button supports _PSW; if not you may have to look
      around in your DSDT yourself for some ideas.
    </para>
  </sect2>

  <sect2 id="acpi_bus_names">
    <title>Where do I find ACPI bus names and device paths?</title>
    <para>
      Bus names are easy; see the discussion of bus names as part of
      events in <link linkend="running_acpid">How do I use acpid?</link> 
      Device paths are not easy, because device names are set by the vendor and
      vary from one platform to the next.  You can get valid device paths for your system
      out of the ACPI namespace by looking at 
      <filename class="directory">/sys/firmware/acpi/namespace/</filename>.  
      Find the device you're going to affect somewhere in the directory tree, say LCD, and grab
      the full name, starting with _SB and ending in the device name. You need to put a "." 
      instead of a "/" between directory names, so that you get something like 
      _SB/PCI0/AGP/VID/LCD converted  to _SB.PCI0.AGP.VID.LCD as the device path. Again, this is only
      useful in the rare case where you have a hotkey that does a fixed action (not
      increasing the brightness, but setting it to max/min; not switching the active display
      but turning one off or on).
    </para>
  </sect2>

</sect1>

<sect1 id="suspend_to_ram">
  <title>Suspend to RAM</title>

  <sect2 id="howto_suspend_to_ram">
    <title>How do I suspend to RAM?</title>
      <para>
        Suspend to RAM is part of the kernel.  Make sure you have ACPI enabled in the BIOS
        and the kernel, and that you have the CONFIG_ACPI_SLEEP option set.
      </para>
      <para>
        It's a good idea to remove all usb devices and modules, as well as any
        firewire devices and modules.  If your suspend works well without them,
        try adding them back in.
      </para>
      <para>
        Then
        <command>
          echo mem &gt; /sys/power/state
        </command>
        You'll see some messages on the console about suspension, ending with
        <screen>
          hwsleep-0296 [08] acpi_enter_sleep_state: Entering sleep state [S3]
        </screen>
        Then your system should go to sleep.
      </para>
      <para>
        Pressing the power button should bring the system back, starting with
        some hard disk activity.
      </para>
  </sect2>

  <sect2 id="video_broken_whatnow">
    <title>My video isn't working; what now?</title>
      <para>
        <itemizedlist>
        <listitem>
          <para>
            Type an innocuous command such as <code>ls</code> and press &lt;Enter&gt;; some folks
            report that their display comes back on the first &lt;Enter&gt; key press.
          </para>
        </listitem>
        <listitem>
          <para>
            If your laptop supports display brightness adjustment, and that works on your
            system before suspend, try using that after suspend and see if your video comes back.
          </para>
        </listitem>
        <listitem>
          <para>
            See if  switching your video display from your internal LCD to an external CRT and back
            brings back your video. You can do this even if you don't have an external CRT hooked up.
            See [] on how to do this.
          </para>
        </listitem>
        <listitem>
          <para>
            If none of those things work, see if your system responds to keypresses.  Does pressing the
            Caps Lock key turn the Caps Lock LED on? If not, wait about 5 minutes, and try the same activity
            again.  Sometimes the kernel has gone out to a short snack instead of out to lunch.
            This works for me.
          </para>
        </listitem>
        <listitem>
          <para>
            If you have Caps Lock responsiveness, try suspension with networking enabled, and
            see if your computer is pingable (again, wait 5 minutes if there is no initial
            response).
          </para>
        </listitem>
        <listitem>
          <para>
            If it is, you might try again with sshd and see if you can log into the system.
            Then you can try some <application>vbetool</application> tricks to muck with the 
	    display.  See <link linkend="vbetool">Vbetool</link>
            for vbetool usage and tricks.
          </para>
        </listitem>
        <listitem>
          <para>
            If you don't have network access, see if typing <code>sync</code> gives you
            disk activity.  If so, you can try the <application>vbetool</application> tricks 
	    mentioned above.  Set up a script ahead of time so that you can minimize typing 
	    mistakes while typing blind.
          </para>
        </listitem>
        <listitem>
          <para>
            If none of those things work, you can try a few specialized boot parameters:
            <code>acpi=s3_sleep</code>, <code>acpi=s3_mode</code>, or <code>pci=routeirq</code>.
            See <link linkend="boot_reference">Boot parameters reference</link> for more information.
          </para>
        </listitem>
        <listitem>
          <para>
          </para>
        </listitem>
        <listitem>
          <para>
          </para>
        </listitem>
      </itemizedlist>
    </para>
  </sect2>

  <sect2 id="suspend_to_ram_utils">
    <title>What utilities are there that I can use for this?</title>
    <para>
      [FIXME]
    </para>
  </sect2>

  <sect2 id="suspend_to_ram_lidclose">
    <title>How about suspend to RAM when I close my laptop?</title>
    <para>
      [FIXME]
    </para>

  </sect2>

  <sect2 id="suspend_to_ram_usb">
    <title>My usb/pcmcia/other device doesn't work when the system resumes; what can I do?</title>
      <para>
        Build usb support and the specific driver support for those devices
        as modules and write an acpid script that removes these modules
        before suspension and reinserts them afterwards.  Here's an example,
	adapted from Gentoo's wiki page on the Samsung X20 at
	<ulink url="http://gentoo-wiki.com/HARDWARE_Samsung_X20#ACPI_hotkeys">
	http://gentoo-wiki.com/HARDWARE_Samsung_X20#ACPI_hotkeys</ulink>:
      </para>
      <programlisting>
	#!/bin/sh
	
	if [ -e /tmp/lidclose ]
	then
            echo "[" `date` "] Wakeup from standby (lid opened)" &gt;&gt; /var/log/acpi_events
          
            rm /tmp/lidclose
    	else
            echo "[" `date` "] Go to standby (lid closed)" &gt;&gt; /var/log/acpi_events
 
            touch /tmp/lidclose

            # USB Module
            rmmod uhci_hcd
            rmmod ehci_hcd

            /sbin/hwclock --systohc
            echo mem &gt; /sys/power/state
            /sbin/hwclock --hctosys

            modprobe uhci_hcd
            modprobe ehci_hcd
	fi
      </programlisting>
  </sect2>

  <sect2 id="suspend_to_ram_whatnow">
    <title>Suspend to RAM just doesn't work after everything I've tried; what now?</title>
      <para>
        Help us debug the problem.  Here are some steps to take:
      </para>
      <para>
        Rebuild your kernel with support for
        as few devices as possible, preferably no usb, and no pcmcia
        unless your network is pcmcia and you have network after
        you resume.
      </para>
      <para>
        Turn off optional devices in your BIOS;
        my Dell laptop lets me turn off the modem and wireless devices.
      </para>
      <para>
        Turn off the framebuffer device.
      </para>
      <para>
        Boot as single user, turn on networking and sshd if your
        machine is pingable after resume, turn on syslogging,
        and try suspend/resume from there.
      </para>
      <para>
        Turn off networking for good measure and try that, just to
        see if that has an impact.
      </para>
      <para>
        Make sure your BIOS is the most recent possible.
      </para>
      <para>
        Check your DSDT; see <link linkend="dsdt_editing">DSDT editing</link> for instructions.
      </para>
      <para>
        If you are running an old distribution, in particular an old
        version of X, update it/them.  If you are using proprietary
        drivers, make sure you are using the most recent version.
      </para>
      <para>
        Try suspend from X as well; video drivers don't live in the
        kernel except for framebuffer drivers, and the X drivers sometimes
        know how to reinitialize recent video cards.
      </para>
      <para>
        Look also at Documentation/video/blot.txt for more things you can try.
      </para>
      <para>
        If you still can't resume, get what you can from the logs and
        submit a bug report.
      </para>
  </sect2>

</sect1>

<sect1 id="suspend_to_disk">
  <title>Suspend to disk</title>

  <sect2 id="suspend_to_disk_howto">
    <title>How do I suspend to disk?</title>
    <para>
      [FIXME]
    </para>

  </sect2>

  <sect2 id="swsuspend_vs_suspend2">
    <title>Which should I use, swsuspend or Software Suspend 2?</title>
    <para>
      [FIXME]
    </para>

  </sect2>

  <sect2 id="suspend_to_disk_utils">
    <title>What utilities are there that I can use for this?</title>
    <para>
      [FIXME]
    </para>

  </sect2>

  <sect2 id="suspend_to_disk_usb">
    <title>My usb///other device doesn't work when the system resumes; what can I do?</title>
    <para>
      [FIXME]
    </para>

  </sect2>

  <sect2 id="suspend_to_disk_whatnow">
    <title>Suspend to disk just doesn't work after everything I've tried; what now?</title>
    <para>
      [FIXME]
    </para>

  </sect2>

</sect1>

<sect1 id="vbetool">
  <title>Vbetool</title>

  <sect2 id="what_is_vbetool">
    <title>What is <application>vbetool</application> and where do I get it?</title>
    <para>
      <application>Vbetool</application> is a set of userspace tools for controlling 
      your display by communicating directly with your graphics adapter.  This tool bypasses
      the BIOS.  It is safer to use than the same techniques in the kernel
      which could send the kernel into a hung state.
    </para>
    <para>
      Most distributions come with <application>vbetool</application>.  If you want the latest 
      version, you can find it at
      <ulink url="http://www.srcf.ucam.org/~mjg59/vbetool">
      http://www.srcf.ucam.org/~mjg59/vbetool/</ulink>.
      The file with "orig" in ths name will build on any linux platform;
      the patches are for a debian package.
    </para>
  </sect2>

  <sect2 id="building_vbetool">
    <title>How do I build vbetool?</title>

    <para>
      To build it, unpack the tarball, <command>cd</command> into the directory where you
      unpacked it, <command>./configure</command>, and then you may have to edit the 
      Makefile.  If you try <command>make</command>, and you get these errors:
    </para>
    <para>
      <screen>
	/home/ariel/acpi/vbetool/vbetool-0.2/vbetool.c:180: undefined reference to `pci_scan_bus'
	vbetool.o(.text+0x1b9):/home/ariel/acpi/vbetool/vbetool-0.2/vbetool.c:183: undefined reference to `pci_read_word'
	vbetool.o(.text+0x518): In function `main':
	/home/ariel/acpi/vbetool/vbetool-0.2/vbetool.c:47: undefined reference to `pci_alloc'
	vbetool.o(.text+0x52c):/home/ariel/acpi/vbetool/vbetool-0.2/vbetool.c:49: undefined reference to `pci_init'
	collect2: ...
      </screen>
      then you need to edit the Makefile to change the line <programlisting>LIBS = </programlisting>
      to <programlisting>LIBS = -lpci</programlisting>.  Then <command>make</command>
      should produce the executable <application>vbetool</application>.  Do 
      <command>make install</command> to install it into /usr/sbin and to install the man page.
    </para>
  </sect2>
  
  <sect2 id="using_vbetool">
    <title>How do I use vbetool?</title>

    <sect3 id="vbestate_option">
      <title>What is the vbestate option?</title>
      <para>
	Vbetool will use the VESA 4Fh call to save or restore hardware state. This includes the hardware
	state, the video BIOS data state, the video DAC state, and the Super VGA state.
	The state information is requested directly from the video BIOS of the graphics adapter.
      </para>
      <para>
	Save it into a file just before
	you suspend and then read it back from that file after the resume:
	<command>vbetool vbestate save &gt; video-state</command>
	suspend, resume,  and then
	<command>vbetool vbestate restore &lt; video-state</command>
      </para>
    </sect3>
  
    <sect3 id="dpms_option">
      <title>What is the dpms option?</title>
      <para>
	DPMS stands for Display Power Management Signaling.  DPMS compliant monitors use Hsync and Vsync
	to put the display into normal, standby, suspend and power off modes.  LCD panels don't use the
	same method but they support these same four states.
      </para>
      <para>
	<code>vbetools dpms off</code>  turns the display off and <code>vbetool dpms on</code> 
	turns it on. This is reported to work for some people to re-enable the video, sometimes 
	in combination with other options.
      </para>
    </sect3>
  
    <sect3 id="post_option">
      <title>What is the post option?</title>
      <para>
	The post option reinitializes the video adapter by executing the code at the 3rd byte 
	of the expansion ROM in the card.  Strictly speaking, it jumps to the third byte of a 
	copy of the ROM which Linux has placed into c000:0000h.
      </para>
      <para>
	This approach can fail; the expansion ROM can later jump to someplace in the system BIOS code,
	expecting system BIOS functions to be available to vbetool, and they won't be.  Or, it can
	jump somewhere which has zeros; this can happen because video adapter initialization code
	is typically thrown away by the BIOS after boot, and sometimes not made available
	again after suspend/resume.
      </para>
      <para>
	I have heard rumors that some laptops have expansion ROM that contains compressed data which is
	both the video rom and the system bios; these may not get uncompressed and stuffed back into
	the shadow rom memory area after suspend/resume.
      </para>
      <para>
	Use this option by typing <code>vbetool post</code>.
      </para>
    </sect3>

  </sect2>

</sect1>

<sect1 id="patches">
  <title>Patches</title>

  <sect2 id="sata_patch">
    <title>SATA driver</title>
    <para>
      Suspend to RAM/Resume for the SATA subsystem is incomplete.  Jens Axboe has a patch that has worked for
      some people including me.  If you have a laptop with a device that is recognized as SATA (this
      includes devices that are PATA but have a PATA->SATA bridge, like the Dell XPS Gen 2), you should
      consider using this patch.  You can find it at
      <ulink url="http://lkml.org/lkml/diff/2005/9/23/97/1">http://lkml.org/lkml/diff/2005/9/23/97/1</ulink> 
      and it applies cleanly to this kernel. SUSE, Ubuntu, and some other distributions have this
      patch already applied.  A secondary patch that is needed sometimes on SUSE kernels is at
      <ulink url="http://lkml.org/lkml/diff/2005/9/23/129/1">http://lkml.org/lkml/diff/2005/9/23/129/1</ulink>.
      Fortunately, there is some discussion of getting this patch merged real soon now; see
      <ulink url="http://lkml.org/lkml/2005/9/21/11">http://lkml.org/lkml/2005/9/21/11</ulink>
      for the full thread.
    </para>
    <para>
      Symptoms of the problem include a message in your logs like
      <screen>
        kernel: hda: status timeout: status=0xd0 { Busy }
        kernel: hda: no DRQ after issuing MULTWRITE_EXT
      </screen>
      or having the hard drive LED remain on continuously and your system lock up after resume.
    </para>
  </sect2>

  <sect2 id="radeonfb_patch">
    <title>Radeonfb patches</title>
    <para>
      There is a series of patches for the radeonfb driver which... [FIXME]
    </para>
  </sect2>

  <sect2 id="vga_post_patch">
    <title>VGA post</title>
    <para>
      There is a kernel patch that allows you to specify that your graphics adapter should be
      reinitialized during resume. [Where in the process does the reinit happen?]  You can try
      using this if you have no video after reboot, though it's not clear that this will do
      anything for you that vbetool won't do.
    </para>
  </sect2>

  <sect2 id="ethernet_card_patch">
    <title>Ethernet cards</title>
    <para>
      tgs had some problems, go look them up. I think they are fixed.
    </para>
  </sect2>

  <sect2 id="yenta_patch">
    <title>Yenta CardBus socket</title>
    <para>
      Problems have been reported with the IRQ reassignment after suspend/resume.  One fix
      is [HERE] though it has not yet made it into the kernel.  Here's why...
    </para>
    <para>
      Symptoms of this problem are:...
    </para>
  </sect2>

</sect1>

<sect1 id="debugging_tips">
  <title>Debugging tips</title>
  <sect2 id="acpi_broken_whats_wrong">
    <title>The driver isn't working right for me. How can I figure out what's wrong?</title>
    <para>
      Turn on debugging in your kernel.  Here are the debugging options that produce useful
      messages in the log:
      <screen>
        CONFIG_PM_DEBUG
        CONFIG_ACPI_DEBUG
        CONFIG_PCI_DEBUG
        CONFIG_DEBUG_DRIVER
        CONFIG_DEBUG_KERNEL
        CONFIG_DEBUG_BUGVERBOSE
        CONFIG_DEBUG_INFO
      </screen>
    </para>
    <para>
      Try the <ulink url="http://lkml.org/lkml/2005/6/7/28">hwsleep suspend simulation patch</ulink>.  
      This skips the final step in suspend, i.e. change to power state.  
      If your system does not come back after this, but hangs somewhere weird, you might be able 
      to recover everything out of the logs up to the failure [FIXME is this true?].  
      And if it works well, you may have a problem with BIOS/hardware/initialization issues.
      You probably have to apply this patch manually, right after the lines
      <programlisting>
        PM1Acontrol |= (acpi_gbl_sleep_type_a &lt;&lt; sleep_type_reg_info->bit_position);
	PM1Bcontrol |= (acpi_gbl_sleep_type_b &lt;&lt; sleep_type_reg_info->bit_position);
      </programlisting>
      and right after the lines
      <programlisting>
        /*
         * We split the writes of SLP_TYP and SLP_EN to workaround
         * poorly implemented hardware.
         */
      </programlisting>
    </para>
    <para>
      Look at your DSDT (see below).
    </para>
  </sect2>

  <sect2 id="dsdt_editing">
    <title>DSDT editing</title>

    <sect3 id="what_is_dsdt">
      <title>What is the DSDT?</title>
      <para>
        DSDT stands for Differentiated System Description Table.  This is a pile of code which
        defines all of the devices that ACPI is going to interact with, and all of the methods
        used to interact with them.
      </para>
      <para>
        The ACPI specification requires some functions such as _WAK (wake from suspend) to be
        implemented, and it requires so many arguments, certain return values, and so on.
        If your system's DSDT does not meet these specifications, some functions may not be
        recognized or enabled.
      </para>
    </sect3>
    <sect3 id="how_to_check_dsdt">
      <title>How do I check my DSDT?</title>
      <para>
        There are three quick ways you can check your DSDT.  First, you can look at linux-laptops.net
        (or acpi4linux) at the list of laptops and see what they say about yours.
      </para>
      <para>
        Second, you can use <application>acpidump</application> to extract your dsdt.  
        See <link linkend="pmtools">Extracting ACPI tables with pmtools</link> for information about
        getting and building <application>acpidump</application>.  To get at the dsdt table, do the following:
      <screen>
        acpidump &gt; mytables.all
        cat mytables.all | ./acpixtract DSDT  &gt; mydsdt.bin
      </screen>
      </para>
      <para>
        Now you have the DSDT table in binary form.  To disassemble it, get 
	<application>iasl</application>
        (see <link linkend="iasl">ASL compiler / AML disassembler iasl</link> for how to do this), 
	build it, and then do
      <screen>
        iasl -d mydsdt.bn
      </screen>
        and it will create the output in mydsdt.dsl
      </para>
      <para>
        Alternatively you can <command>cat /proc/acpi/dsdt</command> into a file, then 
	and then run <command>iasl</command> on that file.
      </para>
      <para>
         To see if your DSDT is broken, you recompile it:
         <command>iasl -tc mydsdt.dsl</command>
      </para>
      <para>
        You'll get output like this:
        <screen>
          Intel ACPI Component Architecture
          ASL Optimizing Compiler / AML Disassembler version 20050624 [Aug 11 2005]
          Copyright (C) 2000 - 2005 Intel Corporation
          Supports ACPI Specification Revision 3.0

          dell-xpsgen2-dsdt.dsl   496:     Method (\_WAK, 1, NotSerialized)
          Warning  2026 -                              ^ Reserved method must return a value (_WAK)
  
          dell-xpsgen2-dsdt.dsl  1262:                 Method (_S0D, 0, NotSerialized)
          Warning  2033 -                   Unknown reserved name ^  (_S0D)
        </screen>
        Warnings can generally be ignored; errors must be fixed.
      </para>
    </sect3>
    <sect3 id="fix_dsdt_howto">
      <title>How do I fix my DSDT?</title>
      <para>
        Look at the resources in <link linkend="acpi_on_laptops">ACPI on Linux laptops</link>
        to see if your errors are documented.  If not, check the 
        <link linkend="specifications">ACPI specification</link>.
        Edit the disassembled file, run iasl on it again and see if you have eliminated
        the errors.  An example: [FIXME put one!]
      </para>
    </sect3>
    <sect3 id="use_fixed_dsdt">
       <title>How do I use my newly fixed DSDT?</title>
       <para>
         You need to build it into your kernel or add it to initrd.  Here's how to do either of those:
	 [FIXME document these!]
       </para>
    </sect3>
  </sect2>

  <sect2 id="last_ditch_efforts">
    <title>Last ditch efforts</title>
    <para>
      First, be sure you have read the appropriate sections of this HOWTO and tried all
      of the workarounds documented there.
    </para>
    <para>
      If you are trying Suspend-to-RAM, have you tried the various boot parameters?
      Have you tried all of the vbetool options?  Did you try suspending after booting
      single user and removing all unnecessary  modules?
    </para>
    <para>
      If you are trying suspend to disk, have you...??
    </para>
    <para>
      Are you using the most current BIOS, acpid, kernel included with your distribution
      or vanilla kernel, and X for your system?
    </para>
    <para>
      Second, read Documentation/power/video.txt and make sure that you have tried everything
      listed there. Also read Documentation/power/tricks.txt and try those too.
    </para>
    <para>
      Third, search the existing bug reports at bugzilla.kernel.org under component ACPI to
      see if your problem has been reported for your hardware.
    </para>
    <para>
      If it hasn't, continue on to the next section to see what to put in your bug report.
    </para>
  </sect2>

  <sect2 id="what_to_put_in_bug_report">
    <title>Submitting useful bug reports</title>
    <para>
      Please submit all bugs to bugzilla.kernel.org under the component ACPI.
    </para>
    <para>
      You should include the following information:
    </para>
    <itemizedlist>
    <listitem>
      <para>Name and version of the distribution you are using</para>
    </listitem>
    <listitem>
      <para>Version of the kernel you are using and whether it is provided by your linux distribution
      or whether it is a vanilla kernel</para>
    </listitem>
    <listitem>
      <para>Description of any patches you have applied to your kernel</para>
    </listitem>
    <listitem>
      <para>The full output of <application>acpidump</application> 
      (See <link linkend="acpid">The acpid events handling daemon</link>.)</para>
    </listitem>
    <listitem>
      <para>The output of <application>dmidecode</application> (See <link linkend="dmidecode">dmidecode</link>
	for more information on this utility.)</para>
    </listitem>
    <listitem>
      <para>Output from <application>dmesg</application></para>
    </listitem>
    <listitem>
      <para>Output from <filename>/var/log/messages</filename></para>
    </listitem>
    <listitem>
      <para><command>/sbin/lspci -vvxxxx</command> output from before and after suspend/resume</para>
    </listitem>
    <listitem>
      <para>List of any boot options you used</para>
    </listitem>
    <listitem>
      <para>Your <filename>.config</filename> file for your kernel build</para>
    </listitem>
    <listitem>
      <para>The contents of any script you use for suspend/resume</para>
    </listitem>
    <listitem>
      <para>Step by step description of what you did from boot through suspend/resume
      and what the outcome was</para>
    </listitem>
    <listitem>
      <para>Whether you are using proprietary X drivers, if you are suspending from X</para>
    </listitem>
    </itemizedlist>
  </sect2>

</sect1>

<sect1 id="pmtools">
  <title>Extracting ACPI tables with pmtools</title>

  <sect2 id="compiling_pmtools">
    <title>Compilation and installation of pmtools</title>
    <para> 
      Download <application>pmtools</application> from
      <ulink url="http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils/">
      http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils/</ulink>.  The
      most recent version as of this writing is pmtools-20050823.
    </para>
    <para>
      Unpack the tarball, <command>cd</command> into the directory where
      you unpacked it, and type <command>make</command> to build <application>acpidump</application>.
      Also included are the scripts <application>acpixtract</application> and
      <application>acpitbl</application>.  These three files should now be copied
      into a useful location like <filename>/usr/local/bin</filename>.
    </para>
  </sect2>

  <sect2 id="using_pmtools">
    <title>Using pmtools</title>
    <para> 
      To run <application>acpidump</application>, be root and at the command prompt, type
      <command>acpidump</command>.
    </para>
    <para>
      If your system is ACPI-compliant, <application>acpidump</application> should print out a long list
      of tables and their contents, including the RSDT and the DSDT.
    </para>
    <para>
      You can use <application>acpixtract</application> to extract your dsdt or any specific
      table.  To get at the dsdt table, do the following:
      <screen>
	acpidump &gt; mytables.all
	cat mytables.all | acpixtract DSDT  &gt; mydsdt.bin
      </screen>
      This also works for any other table name including the FACP, SSDT, and RSDT.
    </para>
    <para>
      If you need to extract a table which has more than one instance, such as the SSDT
      on my platform, you can use a slightly different version of acpixtract which I 
      changed to allow you to specify a count after the table name.  So if you do
      <screen>
	cat mytables.all | acpixtract SSDT 3 &gt; ssdt3
      </screen>
      then you'll get the third instance of the SSDT table.  If you have no such
      instance, you'll get an empty file.  If you leave off the count, you'll get
      the default behavior, a dump of the first table instance.
      The <link linkend="acpixtract_mods">
      code for the modified acpixtract</link> is at the end of this HOWTO.
    </para>
  </sect2>

</sect1>

<sect1 id="iasl">
  <title>ASL compiler / AML disassembler iasl</title>

  <sect2 id="what_is_iasl">
    <title>What is iasl and where do I get it?</title>
    <para>
      Iasl is a compiler for ASL, ACPI Source Language, defined in the ACPI specification.
      It is also a disassembler for AML, the ACPI Machine Language, also defined in the 
      ACPI specification. It will disassemble AML into ASL.
      You can use this tool on various ACPI tables, in particular, the DSDT, so that
      you can edit it, compile it, and use the edited version instead of the buggy one your
      vendor may have provided in the BIOS.
    </para>
    <para>
      You can find the most recent version at Intel's ACPI downloads page, at
      <ulink url="http://developer.intel.com/technology/iapc/acpi/downloads.htm">
      http://developer.intel.com/technology/iapc/acpi/downloads.htm</ulink>.  
      Scroll down to the "Source Code" section
      and look for the "ACPI CA - Unix Build Environment" link. The most recent version
      at this writing is acpica-unix-20050902.
    </para>
  </sect2>

  <sect2 id="building_iasl">
    <title>How do I build iasl?</title>
    <para>
      Unpack the tarball, <command>cd</command> into the directory where you unpacked it,
      <command>cd compiler</command>, and <command>make</command>.  This will produce the
      executable <application>iasl</application> which you can put in some useful
      location like <filename>/usr/local/bin/</filename>.  
    </para>
  </sect2>

  <sect2 id="using_iasl">
    <title>How do I use iasl?</title>
    <para>
      To disassemble a table, first get the table in binary form, for example, 
      <command>acpidump | acpixtract DSDT  &gt; mydsdt.bin</command>, and then do
      <command>iasl -d mydsdt.bin</command>.  This will produce an output file
      called mydsdt.dsl which you can now edit.
    </para>
    <para>
      To compile a table into AML, simply do <command>iasl -tc mytable.dsl</command>
      where <filename>mytable.dsl</filename> is the table in ASL.
    </para>
    <para>
      Although these options will probably get you through the uses of iasl described
      in this document, there are many others; type <command>iasl --help</command>
      to se them all.
    </para>
  </sect2>

</sect1>

<sect1 id="dmidecode">
  <title>dmidecode</title>
  <sect2 id="what_is_dmidecode">
    <title>What is dmidecode and where do I get it?</title>
    <para>
      Dmidecode queries your BIOS about your system's hardware details.  This includes, according
      to the dmidecode project page at 
      <ulink url="http://www.nongnu.org/dmidecode/">http://www.nongnu.org/dmidecode/</ulink>,
      the system manufacturer, model name, serial number, BIOS version, and often information
      about expansion slots and I/O ports.  This information is useful in conjunction
      with bug reports about ACPI, when someone is trying to decipher what is going
      wrong on your hardware.
    </para>
    <para>
      Most distributions come with it prepacked.  Fedora Core 4, Gentoo, and Debian ship with it.
      It may be in /usr/sbin rather than your normal path, so poke around. 
    </para>
    <para>
      You can download the sources from <ulink url="http://savannah.nongnu.org/download/dmidecode/">
      http://savannah.nongnu.org/download/dmidecode/</ulink>.  At this writing, the most recent
      version is dmidecode-2.7.
    </para>
  </sect2>

  <sect2 id="compiling_dmidecode">
    <title>How do I compile and install dmidecode?</title>
    <para>
      Uncompress the tarball, <command>cd</command> into the directory where you unpacked
      it, and type <command>make</command> to build it.  This will give you the
      executables <application>dmidecode</application>, <application>biosdecode</application>,
      <application>ownership</application>, and <application>vpddecode</application>.  
      You can install these into <filename>/usr/local/sbin</filename>
      by typing <command>make install</command>.  This will also install the man pages
      and other documentation.
    </para>
  </sect2>

  <sect2 id="using_dmidecode">
    <title>How do I use dmidecode?</title>
    <para>
      Be root, and at the command prompt, just type <command>dmidecode &gt; lots-of-output.txt</command>.
      Volumes of information should now be present in the output file.
    </para>
  </sect2>

</sect1>

<sect1 id="acpi_details">
  <title>ACPI details</title>

  <sect2 id="power_states">
    <title>What are all these power states C1, S4, D3, etc?</title>
      <para>
         There are 6 system power states, S0 through S5; 5 device states,
         D0 through D4; and a number of CPU power states, depending on
         your processor; my Dothan Pentium M supports states C0 through C4.
      </para>
      <para>
        S0 is when the system is functioning normally, with all devices in their highest 
	power state, S5 is when the system is in "soft off", powered off but AC or some other
	power source is still connnected, and the other states are in between.  
	In particular, S3 is suspend to RAM, and S4 is suspend to disk (also called
        hibernation).  The idea is that a given state Sn is closer to S0 (fully
	awake) the smaller n is; it will use more power in that state but take less 
	time to wake.  So in S3, you can resume pretty fast compared to S4, but you 
	use more power staying in S3 for a given length of time than in S4.
      </para>
      <para>
        If a device is in D0, it is completely functional, and if it
        is in D4, it is powered off. The other states are in between; in
        particular, D3-hot is when the device has lost all context but still
        has power; the OS should have saved any context that needs to be
        restored when the device becomes operational again.  D3-cold
        is when the device has lost all context and no power is applied.
        Devices coming back from D3-cold to D0 are expected to be uninitialized
        but D3-hot devices may or may not require initialization upon waking.
        Many devices do not support D1 or D2 states.  As with S0-S5,
	a device in Dn for smaller n should consume less power but have
	lower wake latency than for a larger n.
      </para>
      <para>
        When your system is in S0, some devices may not be in D0 because
        your power management profile suspends them if they are not in use.
      </para>
      <para>
        If a processor is in state C0, it is fully functional; in any other state, it is
	idle (doing no work).  Lower power states use less power but the CPU
	will take longer to transition to a higher power state. So if your 
	PCU is in C4 it will use less power than in C3 but it will take longer
	to transition to C0 than from C3.
	The kernel will place the CPU into a lower power state 
	automatically when it is not busy, if you enabled CONFIG_ACPI_PROCESSOR.  
	See the <link linkend="config_reference">kernel configuration reference</link>
	for the CONFIG options.
      </para>
  </sect2>

</sect1>

<sect1 id="_other_information">
  <title>Other information sources</title>

  <sect2 id="mailing_lists">
    <title>Mailing lists</title>
    <para>
      You should be reading the acpi-devel mailing list at 
      <ulink url="http://sourceforge.net/mailarchive/forum.php?forum=acpi-devel">
      http://sourceforge.net/mailarchive/forum.php?forum=acpi-devel</ulink>, the 
      linux-pm mailing list at 
      <ulink url="http://lists.osdl.org/pipermail/linux-pm/">http://lists.osdl.org/pipermail/linux-pm/</ulink>,
      and, unfortunately, the linux kernel mailing list at
      <ulink url="http://www.lkml.org">http://www.lkml.org</ulink>.
      You can also have a look at linux-pm-devel at
      <ulink url="http://sourceforge.net/mailarchive/forum.php?forum=linux-pm-devel">
      http://sourceforge.net/mailarchive/forum.php?forum=linux-pm-devel</ulink>,
      which is much lower traffic.  That ought to about cover the reading material.
      You can also monitor the bug reports at
      <ulink url="http://sourceforge.net/mailarchive/forum.php?forum=acpi-bugzilla">
      http://sourceforge.net/mailarchive/forum.php?forum=acpi-bugzilla</ulink> for the very latest news.
    </para>
  </sect2>

  <sect2 id="acpi_on_laptops">
    <title>ACPI on Linux laptops</title>
    <para>
      Linux on Laptops 
      (<ulink url="http://www.linux-laptop.net/">http://www.linux-laptop.net/</ulink>)
      entries for specific laptops often contain ACPI related configuration
      information.  This is a great place to start.
    </para>
    <para>
      TuxMobil (<ulink url="http://tuxmobil.org/mylaptops.html">http://tuxmobil.org/mylaptops.html</ulink>)
      collects Linux installation reports which also have great information.
    </para>
    <para>
      Ubuntu has a good list of test results for suspend for various laptops at 
      <ulink url="https://wiki.ubuntu.com//HoaryPMResults">https://wiki.ubuntu.com//HoaryPMResults</ulink>.
    </para>
    <para>
      If you are looking for a fix for your laptop's DSDT, please check the APCI4Linux DSDT repository at
      <ulink url="http://acpi.sourceforge.net/dsdt/view.php">http://acpi.sourceforge.net/dsdt/view.php</ulink>.
      If you don't see it there, and you add fixes yourself, please add the new DSDT to 
      the repository so others can use it.
    </para>
  </sect2>

  <sect2 id="other_howtos">
    <title>Other HOWTOS</title>
    <para>
      In no particular order, here are some HOWTOs I have found helpful.  Notoriously missing is
      the ACPI4Linux Wiki page describing how to update your DSDT; they've updated their
      wiki recently, perhaps to get rid of the spam links, and the pages are almost all empty.
      <itemizedlist>
	<listitem>
	  <para>
	    Emma Jane Hogbin's ACPI HOWTO (August 2004), at 
	    <ulink url="http://www.tldp.org/HOWTO/ACPI-HOWTO/">
	      http://www.tldp.org/HOWTO/ACPI-HOWTO/	
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Gentoo Forum --  HOWTO: Fix Common ACPI Problems (DSDT, ECDT, etc.) (February 2004), at
	    <ulink url="http://forums.gentoo.org/viewtopic.php?t=122145">
	      http://forums.gentoo.org/viewtopic.php?t=122145
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    ThinkWiki -- How to make ACPI work (September 2005), at
	    <ulink url="http://www.thinkwiki.org/wiki/How_to_make_ACPI_work">
	      http://www.thinkwiki.org/wiki/How_to_make_ACPI_work
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    SuseWiki -- Suspend NVidia HOWTO (September 2005), at
	    <ulink url="http://www.susewiki.org/index.php?title=Suspend_NVidia_HOWTO">
	      http://www.susewiki.org/index.php?title=Suspend_NVidia_HOWTO
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Richard Black's Linux ACPI Howto (February 2004), at
	    <ulink url="http://www.cpqlinux.com/acpi-howto.html">
	      http://www.cpqlinux.com/acpi-howto.html
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Powersave Documentation (June 2005), at
	    <ulink url="http://powersave.sourceforge.net/powersave_doku.html">
	      http://powersave.sourceforge.net/powersave_doku.html
	    </ulink>a
	  </para>
	</listitem>

	<listitem>
	  <para>
	    Battery Powered Linux Mini-HOWTO (July 2003), at
	    <ulink url="http://www.tldp.org/HOWTO/Battery-Powered/index.html">
	      http://www.tldp.org/HOWTO/Battery-Powered/index.html
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Gentoo's Power Management Guide (June 2005), at
	    <ulink url="http://www.gentoo.org/doc/en/power-management-guide.xml">
	      http://www.gentoo.org/doc/en/power-management-guide.xml
	    </ulink>
	  </para>
	</listitem>
      </itemizedlist>
    </para>
  </sect2>

  <sect2 id="useful_papers">
    <title>Useful papers</title>
    <para>
      In no particular order, here are some papers I've found useful:
      <itemizedlist>
	<listitem>
	  <para>
	    Takanori Watanabe, ACPI implementation on FreeBSD,  at
	    <ulink url="http://www.usenix.org/events/usenix02/tech/freenix/full_papers/watanabe/watanabe_html/">
	    http://www.usenix.org/events/usenix02/tech/freenix/full_papers/watanabe/watanabe_html/
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Pramode C.E., Dissecting the ACPI Button Driver in Kernel 2.6, at
	    <ulink url="http://linuxgazette.net/106/pramode.html">
	    http://linuxgazette.net/106/pramode.html
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Dominik Brodowski, Current Trends in Linux Kernel Power Management, at
	    <ulink url="http://www.brodo.de/linux/lt05/presentation.pdf">
	    http://www.brodo.de/linux/lt05/presentation.pdf
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Srivatsa Vaddagiri, Power Management in Linux-Based Systems, at
	    <ulink url="http://www.linuxjournal.com/article/6699">
	    http://www.linuxjournal.com/article/6699
	    </ulink>
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Len Brown, July 2004, The State of ACPI in the Linux Kernel, at
	    <ulink url="www.finux.org/Reprints/Reprint-Brown-OLS2004.pdf">
	    www.finux.org/Reprints/Reprint-Brown-OLS2004.pdf 
	    </ulink>
	  </para>
	</listitem>
      </itemizedlist>
    </para>
  </sect2>

  <sect2 id="specifications">
    <title>Official specifications</title>
    <para>
      The main source for official documentation is 
      <ulink url="http://www.acpi.info">www.acpi.info</ulink>.
      They have the most recent specification, ACPI 3.0, available 
      at <ulink url="http://www.acpi.info/spec.htm">http://www.acpi.info/spec.htm</ulink>.
      Microsoft has class specifications for devices at 
      <ulink url="http://www.microsoft.com/whdc/resources/respec/specs/pmref/download.mspx">
      http://www.microsoft.com/whdc/resources/respec/specs/pmref/download.mspx</ulink> 
      which describe each class of device
      does in a given power state -- which parts of the device are powered off, and what functionality 
      it has in the given state.
      Intel's ACPI page at
      <ulink url="http://developer.intel.com/technology/iapc/acpi/downloads.htm">
      http://developer.intel.com/technology/iapc/acpi/downloads.htm</ulink>
      has good information too.  
    </para>
    <para>
      If you spend much time looking at the driver, you are going to want the 
      PCI specifications, but you can't just download them.  Check the PCI SIG website at
      <ulink url="http://www.pcisig.com/specifications/conventional/">
	http://www.pcisig.com/specifications/conventional/</ulink> 
      to get them.  Fortunately, chapter 12 of the Linux Device Drivers book version 3 at
      <ulink url="http://www.oreilly.com/catalog/linuxdrive3/book/ch12.pdf">
	http://www.oreilly.com/catalog/linuxdrive3/book/ch12.pdf</ulink> can get you through
      some of the code. A good deal of Linux-specific information about PCI devices
      and drivers is covered in David A Rusling's The Linux Kernel at 
      <ulink url="http://www.science.unitn.it/~fiorella/guidelinux/tlk/node65.html">
	http://www.science.unitn.it/~fiorella/guidelinux/tlk/node65.html</ulink>, 
      although it was written eight years ago.  You can also look at 
      /usr/src/linux/include/linux/pci.h for a list of every register and bit that
      Linux knows about in the PCI configuration space.
    </para>
    <para>      
      You may want the 
      VESA BIOS extension specs
      at <ulink url="http://www.vesa.org/Public/VBE/vbecore3.pdf">
	http://www.vesa.org/Public/VBE/vbecore3.pdf</ulink> too if you 
      read through the vbetool or ACPI video code.
    </para>
  </sect2>

  <sect2 id="other_architectures">
    <title>ACPI on x86_64 and other architectures</title>
    <para>
      [FIXME put some info here]
    </para>
  </sect2>

</sect1>

<sect1 id="cpufreq_reference">
  <title>CPU_FREQ reference</title>

  <sect2 id="cpu_frequency_managers">
    <title>CPU frequency managers</title>
    <para>
      You can build in a number of kernel-based cpu frequency managers.  Each of these
      has a different policy for what frequencies it sets the CPU to under which
      conditions.
    </para>
    <para>
      To build in support for the "performance" CPU frequency manager, select
      CPU_FREQ_GOV_PERFORMANCE.  Under this manager, the CPU frequency is set to
      the maximum possible at all times.
    </para>
    <para>
      To build in support for the "powersave" CPU frequency manager, select.
      CPU_FREQ_GOV_POWERSAVE.  Under this manager, the CPU frequency is set to
      the minimum possible.
    </para>
    <para>
      To build in support for the user to control CPU frequency directly, via an 
      entry in sysfs, select CPU_FREQ_GOV_USERSPACE.  Most userspace applications 
      that control CPU frequency such as cpuspeed or powernowd require this.
    </para>
    <para>
      To build in support for the "ondemand" policy CPU frequency
      manager, select CPU_FREQ_GOV_ONDEMAND.  Under this manager, the 
      CPU frequency is changed depending on usage.  Your CPU should be able to make very fast 
      frequency changes for this manager to be effective.
    </para>
    <para>
      To build in support for the "conservative" policy CPU frequency
      manager, select CPU_FREQ_GOV_CONSERVATIVE.  Under this manager, 
      the CPU frequency is changed  depending on usage.  However, it changes speed more slowly
      than the "ondemand" manager.  This is a better manager to use
      when your CPU has a higher latency for switching frequencies,
      as laptop CPUs often do.
    </para>
    <para>
      Of course there's no reason you should have to choose just one of these;
      at least one userspace application for frequency management expects you to
      have built in both the "performance" and "powersave" managers, and it 
      switches between them depending on the load.  
    </para>
    <para>
      Once you have built in the managers you want, you must also set the default 
      frequency manager; choose one of CPU_FREQ_DEFAULT_GOV_PERFORMANCE
      or CPU_FREQ_DEFAULT_GOV_USERSPACE which sets the default CPU frequency manager to the "performance"
      or "userspace" manager, respectively.  Currently these are the only defaults supported, but you 
      can always change the manager after boot.
    </para>
  </sect2>

  <sect2 id="cpu_frequency_drivers">
    <!-- these are from /usr/src/linux/arch/i386/kernel/cpu/cpufreq -->
    <title>CPU frequency drivers</title>
    <para>
      Once you enable CONFIG_CPU_FREQ, you can choose a CPU frequency driver.
      Only certain drivers have an ACPI interface option; those are the only ones
      discussed here. 
    </para>
    <para>
      If you have a mobile AMD K7 (AMD Mobile Athlon/Duron), you should select 
      CONFIG_X86_POWERNOW_K7 and CONFIG_X86_POWERNOW_K7_ACPI.
      If you have an AMD K8 (AMD Opteron/Athlon64), you should select 
      CONFIG_X86_POWERNOW_K8 and CONFIG_X86_POWERNOW_K8_ACPI.
      If you have the Centrino chipset (Intel Pentium M), you should select
      CONFIG_X86_SPEEDSTEP_CENTRINO and CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI.
    </para>
    <para>
      If you have none of these, you can select CONFIG_X86_ACPI_CPUFREQ to build in the 
      generic APCI P-states driver.  You can only use this if your system
      supports CPU performance states; in particular, your CPU must support
      the ACPI _PSS method.  If it does not, you'll get an error when you try to
      load the module or initialize the driver.  Most ACPI 2.0 compliant platforms
      should support this.
    </para>
  </sect2>

  <sect2 id="cpu_regulate_frequency">
    <title>How do I regulate my CPU frequency?</title>
    <para>
      Now that you have some cpu freqncy managers and the appropriate driver built into
      your kernel, you'll probably want a userspace application that you can configure
      to change the CPU frequency depending on your needs.  It might regulate frequency
      only when you're not on AC, or it might step through various frequencies depending
      on load, or it might switch between max and min performance.  There are a number
      of such applications, which include cpudyn, cpufreq (formerly cpuspeed), 
      powernowd, and cpufreq-applet.  A discussion of how to build, configure and run these 
      is beyond the scope of this document.  Many Linux distributions supply them as packages,
      however, with some reasonable default configuration.
    </para>
    <para>
      If you want to change your CPU frequency manually, you can write the new frequency, 
      in kHz, into 
      <filename>/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed</filename>.  This means
      that if you want 800MHz, you do 
      <command>echo 800000 &gt; /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed</command>.
      Don't worry; if you forget and put 800, the driver will find the lowest supported
      frequency for you and use that instead.  You can check those supported frequencies
      by looking at 
      <filename>/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies</filename>.
    </para>
  </sect2>

</sect1>

<sect1 id="config_reference">
  <title>Kernel configuration reference</title>
  <para>
    Turn on these configuration options for base ACPI support:
  </para>

  <variablelist>
    <varlistentry>
      <term>CONFIG_PM</term>
      <listitem><para>turns on power management</para></listitem>
    </varlistentry>
    <varlistentry>
      <term>CONFIG_ACPI</term>
      <listitem><para>turns on ACPI</para></listitem>
    </varlistentry>
  </variablelist>

  <para>
    If you build into your kernel both APM and ACPI, and an ACPI-compliant BIOS is found,
    ACPI will be used and the APM-related functions will be disabled.  So it's safe to
    enable both, if you are concerned that your system might not support ACPI.
  </para>
  <para>
    Turn on these options for specific functionality:
  </para>

  <itemizedlist>
    <listitem>
      <para>
	Plug and Play devices
	<variablelist>
          <varlistentry>
            <term>CONFIG_PNPACPI</term>
	    <listitem>
	      <para>
		If you have plug and play devices, setting this option will enable the
		use of ACPI to detect and allocate resources for those devices rather
		than using the PnPBIOS. In almost all cases it's safe to enable this.
	      </para>
            </listitem>
          </varlistentry>
	</variablelist>
      </para>
    </listitem>
  </itemizedlist>

  <itemizedlist>
    <listitem>
      <para>
	Suspend-to-RAM:
	<variablelist>
          <varlistentry>
            <term>CONFIG_ACPI_SLEEP</term>
	    <listitem>
	      <para>
		enable suspend to RAM
	      </para>
            </listitem>
          </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>    
      <para>
	suspend to disk:
	<variablelist>
          <varlistentry>
            <term>CONFIG_SOFTWARE_SUSPEND</term>
	    <listitem>
	      <para>
		enables suspend to disk
	      </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_PM_STD_PARTITION</term>
	    <listitem>
	      <para>
		sets the partition to be used for suspend to disk
	      </para>
            </listitem>
          </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>
      <para>
	Control over various devices:
	<variablelist>
          <varlistentry>
            <term>CONFIG_ACPI_AC</term>
            <listitem>
              <para>
		Allows you to be notified when you switch to 
		or from using an adapter as your system's power source,
		so that you can specify an action to take 
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_BATTERY</term>
            <listitem>
              <para>
		Allows you to retrieve information about your battery, 
		including how much capacity it has left, and be notified
		when battery charge drops below a certain level,
		so that you can specify an action to take 
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_BUTTON</term>
            <listitem>
              <para>
		Allows you to be notified the sleep or power button
		is pressed or you close your laptop lid,
		so that you can specify an action to take 
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_VIDEO</term>
            <listitem>
              <para>
		Allows you to control brightness, set which video display you use, 
		get the EDID (extended display identification data) from a video display, 
		and set which video adapter will be POSTed at next boot if you have 
		more than one video device.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_FAN</term>
            <listitem>
              <para>
		Allows you to turn your fans on or off or check their status
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_PROCESSOR</term>
            <listitem>
              <para>
		Allows the kernel to put your CPU in a lower power state when
		it's idle; allows you to throttle the cpu by forcing the cpu to be
		idle in a percentage of its total clock cycles, when you are
		actually doing computation and you don't want to run the cpu 
		at full load; allows you to limit CPU cycle usage when CPU
		temperature is too hot; required for system thermal management
		described below (CONFIG_ACPI_THERMAL).  You should really set this item,
		even if thermal management is the only feature that gets used.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_THERMAL</term>
            <listitem>
              <para>
		Unless you have a very good reason, set this. Most modern systems
		have temperature sensing, and when the temperature of certain chipsets 
		or the CPU reaches a critical point, the system shuts down, or other actions 
		can be taken, such as turning on additional coolers.  This requires 
		CONFIG_ACPI_PROCESSOR.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_X86_ACPI_CPUFREQ</term>
            <listitem>
              <para>
		This driver adds a CPUFreq driver which utilizes the ACPI Processor Performance States.
		To use this, you must have earlier set CONFIG_CPU_FREQ.  It has the advantage of
		allowing you later to link CPU throttling limits to changes in CPU frequency,
		but it has the disadvantage of being slower in comparison to hardware-specific
		drivers.  But newer BIOSes will conform to APCI 3.0 which uses MSRs instead
		of IO ports to change states, and then this driver will kick *ss.  There is
		a patch in the works to take care of these new features.
		[FIXME test and see if centrino really is slower to change freq than p-state.]
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_X86_ACPI_CPUFREQ_PROC_INTF</term>
            <listitem>
              <para>
		Don't use this; it's deprecated.  It creates the entry 
		<filename>/proc/acpi/processor/../performance</filename>, but you should use
		the sys entries 
		<filename class="directory">/sys/devices/system/cpu/.../cpufreq/</filename> 
		instead.
              </para>
            </listitem>
          </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>
      <para>
	Specific laptop extras:
	<variablelist>
	  <varlistentry>
            <term>CONFIG_ACPI_ASUS</term>
            <listitem>
	      <para>
		If you have an ASUS laptop with ACPI supported, say yes to get support
		for the extra keys, control over the notification LEDs, and for some laptops,
		blacklight and brightness control.
              </para>
            </listitem>
          </varlistentry>
	  <varlistentry>
            <term>CONFIG_ACPI_IBM</term>
            <listitem>
              <para>
		If you have an IBM Thinkpad with ACPI supported, say yes to get support
		for hotkeys, Bluetooth enable/disable, video display switching, UltraBay eject, docking
		and undocking, and several other features. An up to date list of these features is
		available in 
		<ulink url="http://www.linuxhq.com/kernel/file/Documentation/ibm-acpi.txt">
                Documentation/ibm-acpi.txt</ulink>.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_TOSHIBA</term>
            <listitem>
              <para>
		If you have a Toshiba laptop which has no BIOS menu settings
		and no APM support, you probably want this option.  The Toshiba Libretto is one of 
		these laptops.  This driver will give you access to some Toshiba-specific features 
		that are only now being integrated into the generic ACPI driver.  Those include 
		turning on/off the fan, switching the video display device, brightness control, 
		and hotkey support. 
		[FIXME  What about so-called development plans from June 2005?  More about how 
		there is an "experimental" toshiba driver now with more features.]
              </para>
            </listitem>
          </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>
      <para>
	Misc:
	<variablelist>
          <varlistentry>
            <term>CONFIG_ACPI_HOTKEY</term>
            <listitem>
              <para>
		New, lets you map a hotkey to a specific ACPI event which acpid can handle.
		This driver is useful because vendors do not have standard event numbers mapped to
		hotkeys, and this driver lets you convert vendor numbers to a standardized list.
		Note that you must use the boot parameter acpi_generic_hotkey to enable this
		driver even after building it into the kernel.  
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_BLACKLIST_YEAR</term>
            <listitem>
              <para>
		If you set this option in your kernel, and your BIOS is before the year specified,
		ACPI will be disabled by default.  Some distributions default this to 2001.  If you are
		building a kernel to be used on many systems such as a kernel for a Linux distribution,
		this is a useful option.
              </para>
            </listitem>
          </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>
      <para>
	Debugging/fixing broken implementations
	<variablelist>
          <varlistentry>
            <term>CONFIG_ACPI_CUSTOM_DSDT</term>
            <listitem>
              <para>
		Don't use this right away unless you know in advance that
		your laptop has a broken DSDT and that you need to compile in a fixed one.
		See <link linkend="acpi_on_laptops">ACPI on Linux laptops</link> for 
		lists of laptops with their DSDT fixes, 
		and <link linkend="dsdt_editing">DSDT editing</link> for a discussion of DSDT tables.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_CUSTOM_DSDT_FILE</term>
            <listitem>
              <para>
		If you need to compile n a custom DSDT (see previous option),
		you must enable this option and give the full pathname to the DSDT file, compiled
		into AML code.  See <link linkend="dsdt_editing">DSDT editing</link> for how to 
		compile DSDT tables.
              </para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>CONFIG_ACPI_DEBUG</term>
            <listitem>
              <para>
		If you are trying to debug problems with the ACPI subsystem,
		this will produce some useful debugging messages in your log.
              </para>
            </listitem>
          </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>
      <para>
        memory (NUMA)
<!-- CONFIG_ACPI_SRAT is in arch/i396 area -->
        <variablelist>
          <varlistentry>
            <term>CONFIG_ACPI_NUMA</term>
            <listitem>
              <para>
		SRAT and SLIT tables are defined if you set this.  These tables permit the
		system to determine which memory modules ought to be assigned to which nodes. [FIXME 
		get a better description.] If you have a system which has NUMA enabled, set this option.
              </para>
            </listitem>
          </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>
      <para>  
        Hotpluggable memory and cpu
	<variablelist>
          <varlistentry>
            <term>CONFIG_ACPI_CONTAINER</term>
            <listitem>
              <para>
  		FIXME
              </para>
            </listitem>
	  </varlistentry>
	  <varlistentry>
            <term>CONFIG_ACPI_HOTPLUG_MEMORY</term>
            <listitem>
              <para>
		FIXME
              </para>
            </listitem>
	  </varlistentry>
	  <varlistentry>
            <term>CONFIG_ACPI_HOTPLUG_IO</term>
            <listitem>
              <para>
		FIXME
              </para>
            </listitem>
	  </varlistentry>
	  <varlistentry>
            <term>CONFIG_ACPI_HOTPLUG_CPU</term>
            <listitem>
              <para>
		If you have an SMP box with a hotpluggable CPU, and you need to
		be able to swap in a new CPU on failure, set this.
              </para>
            </listitem>
	  </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>
      <para>  
	DSDT (Differentiated System Description Table) options
	To get these, you must choose STANDALONE under "Generic Driver Options".
	<variablelist>
	  <varlistentry>
            <term>CONFIG_ACPI_CUSTOM_DSDT</term>
            <listitem>
	      <para>
		Allows you to use your own edited and fixed DSDT in case
		your BIOS has a broken one.  See <link linkend="dsdt_editing">DSDT editing</link>
		for more information on this.
	      </para>
            </listitem>
	  </varlistentry>
	</variablelist>
	<variablelist>
	  <varlistentry>
            <term>CONFIG_ACPI_CUSTOM_DSDT_FILE</term>
            <listitem>
	      <para>
		Specify the full path to the file that contains your fixed DSDT, so the
		build system can read the file and build the contents right into the kernel
	      </para>
            </listitem>
	  </varlistentry>
	</variablelist>
      </para>
    </listitem>
    <listitem>
      <para>  
	<emphasis>Don't</emphasis> enable this, because it's deprecated:
	<variablelist>
	  <varlistentry>
            <term>CONFIG_ACPI_SLEEP_PROC_SLEEP</term>
            <listitem>
	      <para>
		Creates the entry <filename>/proc/acpi/sleep</filename>, which 
		can be used to put the system
		into various suspend states,  but this is deprecated in
		favor of the sysfs entry <filename>/sys/power/state</filename>.
	      </para>
            </listitem>
	  </varlistentry>
	</variablelist>
	<screen>
	  still missing:
	  X86_PM_TIMER                 [ ]   Power Management Timer Support
	</screen>
      </para>
    </listitem>
  </itemizedlist>
</sect1>

<sect1 id="boot_reference">
  <title>Boot parameter reference</title>
  <variablelist>
    <varlistentry>
      <term>acpi=force</term>
      <listitem>
        <para>
          If you built your kernel with acpi disabled, you can use this
          option to force its use.
        </para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term>apci=off</term>
      <listitem>
        <para>
          If you built your kernel with ACPI enabled, you can use this
          option to turn it off (in case you'd rather use APM, it interferes 
          with something else, or it's just plain broken).
        </para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term>acpi=ht</term>
      <listitem>
        <para>
          Enable ACPI only to the degree needed to support yyperthreading. 
	  If you don't want to use most of the APCI driver, but you
	  want hyperthreading working, use this option so that the ACPI
	  tables will be used for virtual processor discovery.
        </para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term>apci=strict</term>
      <listitem>
        <para>
          Be anal about syntax and method requirements in ACPI tables
          provided by the vendor; if you turn this on, you can find
          potential problems with your DSDT that may not show up by
          other means.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
<!-- see /arch/i386/kernel/acpi/sleep.c  and /arch/i386/kernel/acpi/wakeup.S -->
      <term>acpi_sleep=s3_bios</term>
      <listitem>
        <para>
	  If this boot parameter is passed, upon wake from susend, the
	  kernel will try to initialize your video adapter by calling
	  code at c000:0003h.  In practice, this code may no longer 
	  be available after power on, so your system may crash.  But for some 
	  people, this is the only way to get suspend to RAM to work.  Use with caution.
        </para>
      </listitem>
    </varlistentry>
    </variablelist>

    <variablelist>
    <varlistentry>
      <term>acpi_sleep=s3_mode</term>
      <listitem>
        <para>
	  Upon wake from suspend, the kernel will set the video adapter mode to the 
	  mode it was in before suspend, using the VESA BIOS mode set call (0x4f02).  
	  Use this if your system can get back to VGA text mode from suspend, i.e. 
	  it suspends ok from a text console, but doesn't work from X. This could 
	  crash your system so use with caution.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_sleep=s3_bios,s3_mode</term>
      <listitem>
	<para>
	  On some systems that require acpi_sleep=s3_bios, the system will be left
	  in VGA text mode and so you'll need to do s3_mode as well.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_sci=level|edge|high|low</term>
      <listitem>
        <para>
          Set ACPI System Control Interrupt trigger mode; it's very unlikely that
	  you'll need this, as SCI handling has been stable for some time.  However,
	  if you have a prerelease BIOS, and you see messages in your log about
	  unrecognized SCIs, try using one of these settings.   [If someone who 
	  has to use this option would contact me, I'll add a better description.]
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_irq_balance</term>
      <listitem>
        <para>
          ACPI will balance active IRQs to minimize sharing.  This is 
	  the default in APIC mode.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_irq_nobalance</term>
      <listitem>
        <para>
	  ACPI will not move active IRQs around (the opposite of acpi_irq_balance).
          This is the default in PIC mode.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_irq_pci=...</term>
      <listitem>
        <para>
          If you have set acpi_irq_balance, you have to reserve some IRQs for
	  for use by PCI or else ACPI may use them all; list them here. 
          Format: &lt;irq&gt;,&lt;irq&gt;...
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_irq_isa</term>
      <listitem>
        <para>
          If you have set acpi_irq_balance, you have to reserve some IRQs for
	  for use by ISA or else ACPI may use them all; list them here. Don't 
	  do this unless you have ISA devices.
          Format: &lt;irq&gt;,&lt;irq&gt;...
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_osi=</term>
      <listitem>
        <para>
           By default, the _OSI method in ACPI will tell the BIOS that we are running
	   Microsoft Windows NT. But if you use this option with an empty parameter, 
	   it disables the _OSI method.  (What does the BIOS do then?)
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_os_name=</term>
      <listitem>
        <para>
           By default, the _OSI method in ACPI will tell the BIOS that we are running
	   Microsoft Windows NT. But if you specify a name here, that OS name will be
	   reported to the BIOS instead.  This may enable or disable some methods
	   in your DSDT depending on the OS string you choose.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_serialize</term>
      <listitem>
        <para>
	  If you see errors in your log which include things like
	  <screen>
	    Error: Looking up [some-device-id] in namespace, AE_ALREADY_EXISTS
	  </screen>
	  then try setting this option.  It forces serialization of AML methods in case a method 
	  creates namespace objects, fails to complete cleanly, and leaves its debris around; 
	  this may allow us to track down the specific problem.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_skip_timer_override</term>
      <listitem>
        <para>
	  This option is specific to certain versions of the nForce2 BIOS which
	  map IRQ0 to pin 2 and result in the timer being XT-PIC instead of 
	  IO-APIC-edge.  This isn't really an ACPI issue but it's called
	  acpi_skip_timer_override so it's in this document.  See kernel bug 1203 at
	  <ulink url="http://bugme.osdl.org/show_bug.cgi?id=1203">
	    http://bugme.osdl.org/show_bug.cgi?id=1203</ulink>
	  for more info.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_dbg_layer=</term>
      <listitem>
        <para>
	  Format: &lt;int&gt; ; Turn on or off debugging of a or several acpi debug layers.
	  Each bit of the &lt;int&gt; indicates a separate layer.  Starting from the rightmost bit, 
	  you can turn on debugging for the layers: UTILITIES, HARDWARE, EVENTS, TABLES, 
	  NAMESPACE, PARSER, DISPATCHER, EXECUTER, RESOURCES, CA_DEBUGGER, OS_SERVICES, 
	  CA_DISASSEMBLER, COMPILER, and TOOLS.
	  If you don't do this at boot time you can still enable this by writing to 
	  <filename>/proc/acpi/debug_layer</filename>.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_dbg_level=</term>
      <listitem>
        <para>
	  Format: &lt;int&gt; ; Turn on or off debugging of a or several acpi debug levels.
	  Each bit of the &lt;int&gt; indicates a separate level. Starting from the rightmost bit, 
	  you can turn on debugging for messages logged at the level: ERROR, WARN, INIT, 
	  DEBUG_OBJECT, INFO, INIT_NAMES, PARSE, LOAD, DISPATCH, EXEC, NAMES, OPREGION, 
	  BFIELD, TABLES, VALUES, OBJECTS, RESOURCES, USER_REQUESTS, PACKAGE, ALLOCATIONS, 
	  FUNCTIONS, OPTIMIZATIONS, MUTEX, THREADS, IO, INTERRUPTS, AML_DISASSEMBLE, 
	  VERBOSE_INFO, FULL_TABLES, and EVENTS.
	  If you don't do this at boot time you can still enable this by writing to 
	  <filename>/proc/acpi/debug_level</filename>.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>ec_burst=</term>
      <listitem>
        <para>
	  use burst mode instead of polling mode for embedded controller; this mode
	  is better in the long run than polling mode but not ready for prime time
	  yet.  Use it, however, if you see problems with button failure or battery
	  status failure or other ACPI events just disappearing and not being handled; see 
	  kernel bug 3851 at
	  <ulink url="http://bugzilla.kernel.org/show_bug.cgi?id=3851">
	    http://bugzilla.kernel.org/show_bug.cgi?id=3851</ulink>
	  for more information.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_generic_hotkey</term>
      <listitem>
        <para>
	  There is a generic hotkey driver which will let you map hotkey codes to specific
	  acpi methods.  It's not at all user friendly. Nonetheless, it may be useful
	  for you if your laptop has hotkeys that use the ACPI interface.  If you 
	  compile in the generic hotkey driver, using CONFIG_ACPI_HOTKEY, you must 
	  use this boot option for the driver to be enabled. 
	</para>
	<para>
	  Some laptops have specific hotkey drivers for their setups; see the CONFIG options 
	  above for the list.
	  If you set this option and you have compiled in both the generic hotkey driver and
	  a specific driver for one of those laptops, only the generic hotkey driver will be used.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_fake_ecdt</term>
      <listitem>
        <para>
	  Workaround failure due to BIOS lacking ECDT; use this if you see errors in your log early
	  on about the battery, adapter or the embedded controller.  Setting this option lets
	  the kernel ignore the missing ECDT, and come bakc to complete initialization 
	  of those devices later when it has pulled more complete information from the DSDT.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>acpi_wake_gpes_always_on</term>
      <listitem>
        <para>
	  If your system seems not to be generating APCI events, try
	  setting this option.  Here's the explanation, taken right from the
	  kernel code: 
	</para>
	<para>
	  Wake and Run-Time GPES are expected to be separate.
	  We disable wake-GPEs at run-time to prevent spurious
	  interrupts. However, if a system exists that shares Wake and
	  Run-time events on the same GPE this flag is available
	  to tell Linux to keep the wake-time GPEs enabled at run-time.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>pci=noacpi</term>
      <listitem>
        <para>
	  Do not use ACPI for IRQ routing. ACPI looks at _PRT packages to figure out
	  which interrupt goes with which PCI interrupt link device and then looks up
          the resources that device uses. Instead, use the PCI IRQ routing table.
	  If your kernel hangs during boot, you may have serious IRQ problems; try this option.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>pci=routeirq</term>
      <listitem>
        <para>
	  Do IRQ routing for all PCI devices.  Each device should call pci_enable_device(),
	  which will do this IRQ routing, but some drivers may be broken and not call it,
	  so this option makes sure it gets called for each device outside of the driver.
	  If you have problems with a particular device, try this option.
	  Someday this option should go away.  I wonder about proprietary drivers though...
	  Maybe this option is here to stay.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>pnpacpi=off</term>
      <listitem>
        <para>
	  Try this option if you are having trouble with PNP devices under
	  ACPI; this will disable use of PNPACPI and will use PNPBIOS instead.
        </para>
      </listitem>
    </varlistentry>

    <varlistentry>
      <term>processor.max_cstate</term>
      <listitem>
        <para>
	  Limit processor to maximum C-state; if you enabled CONFIG_ACPI_PROCESSOR
	  so that the CPU is placed in different power states when it is idle, 
	  you may want this.  Various IBM Thinkpad systems emit a high-pitched 
	  whine when the CPU enters C3 or C4, so passing C2 as a parameter will 
	  prevent that. See ThinkWiki at 
          <ulink url="http://www.thinkwiki.org/wiki/Problem_with_high_pitch_noises">
	    http://www.thinkwiki.org/wiki/Problem_with_high_pitch_noises</ulink>
          to check your specific model. 
	</para>
	<para>
	  If you don't want to lose the ability to use these lower power states, you 
	  can try adjusting your timer speed instead: set your default timer speed to HZ_100 
	  (CONFIG_HZ_100). 
	</para>
	<para>
	  If you know that your system should support C3 or C4 and a look at 
          <filename>/sys/module/processor/parameters/max_cstate</filename>
	  shows that it's set lower, you can
	  try to increase it.  Some BIOSes are blacklisted from these lower power states
	  in the kernel.  As of this writing, those are the IBM ThinkPad R40e, 
          the Medion 41700, and the Clevo 5600D.  Set max_cstate=9 to override
	  this limit.
	</para>	
      </listitem>
    </varlistentry>
    </variablelist>
</sect1>

<sect1 id="sysfs_entries">
  <title>Sysfs entries reference</title>
  <sect2 id="sysfs_overview">
    <title>Overview of /sys entries</title>
    <para>
      Most acpi hooks have not been moved over from the 
      <filename class="directory">/proc</filename> filesystem.  There are a few exceptions:
      entries related to cpu power states, cpu frequency, a device or system's power state,
      and the ACPI namespace tree. Also, hotpluggable devices may be controllable via a 
      <filename class="directory">/sys</filename> entry.
    </para>
  </sect2>
  
  <sect2 id="sysfs_power">
    <title>Power entries in /sys</title>
    <para>
      Every device with an entry in <filename class="directory">/sys</filename>, 
      including buses, has an entry which concludes in
      <code>power/state</code>.  Some such entries on my system are
      <screen>
        ./devices/pnp0/00:09/power/state
        ./devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/power/state
        ./devices/platform/i8042/serio1/power/state
      </screen>
      If you <command>cat</command> one of these, you will see the current
      power state of the device.  See <link linkend="power_states">Power states</link>
      for more on power states.
    </para>
    <para>
      <filename>/sys/power/state</filename> controls the power state for the whole system, from
      S0-S5.  If you <command>cat</command> this, you see what types of system sleep
      are supported.  Right now, the kernel supports standby S1), mem (S3) and disk (S4).
      If you echo one of these states into <filename>/sys/power/state</filename>, the system will
      try to enter that sleep state.  For example,
      <command>
        echo disk &gt; /sys/power/state
      </command>
      will do suspend to disk (i.e. hibernation) which is the S4 sleep state.
      This assumes you have built hibernation support into your kernel, of course.
    </para>
  </sect2>
  
  <sect2 id="sysfs_hotpluggable">
    <title>Hotpluggable devices and /sys entries</title>
    <para>
      If you have devices which are hot-pluggable, you will see 
      <filename>/sys/firmware/acpi/eject</filename>
      and you can echo the name of the device -- as seen from the ACPI namespace,
      unfortunately -- into this file and the kernel will prepare the device 
      so that the user can then swap it out.  The name will probably start
      "\_SB." and then you can append the actual name of the device.
      Look in your DSDT for devices with the EJ0 method.  I'd have better information but my system has 
      no hot-swappable devices. Sorry!
    </para>
  </sect2>
  
  <sect2 id="sysfs_max_cstate">
    <title>CPU power states (C-States) and /sys entries</title>
    <para>
      <filename>/sys/module/processor/parameters/max_cstate</filename>
      contains the lowest power state your CPU can 
      enter.  If you know your CPU should support C3 or C4 but you only see C2 listed here,
      your BIOS may be blacklisted.  See 
      <link linkend="boot_reference">Boot parameters reference</link>
      for processor.max_cstate settings to override the blacklist.
    </para>
  </sect2>
  
  <sect2 id="sysfs_cpu_freq">
    <title>CPU frequency management and /sys entries</title>
    <para>
      CPU frequency entries can be found under 
      <filename class="directory">/sys/devices/system/cpu/cpu*/cpufreq/</filename>, 
      assuming you
      built in support for CPU frequency management.  You can find some details in the 
      <link linkend="cpufreq_reference">CPU_FREQ reference</link> although only ACPI-related
      information is covered there.
    </para>
    <para>
      Various IBM Thinkpad systems emit a high-pitched whine when the CPU enters C3 or C4, 
      so echoing '2' into 
      <filename>/sys/module/processor/parameters/max_cstate</filename>
      will prevent that. 
      But see  <link linkend="boot_reference">Boot parameters reference</link> for more about
      that problem.
    </para>
  </sect2>
  
  <sect2 id="sysfs_acpi_namespace">
    <title>ACPI namespace tree and /sys</title>
    <para>
      <filename class="directory">/sys/firmware/acpi/namespace/ACPI</filename>
      shows the ACPI device namespace in tree form.
      If it's not clear to you from the name what a given device is, you can find it in your 
      DSDT and grab the HID (Hardware ID) associated with it, and look it up in this list:
      <ulink url="http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/devids.txt">
	http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/devids.txt</ulink>
      If the _HID isn't listed there, it may be in the ACPI 3.0 specs. 
      For example, in my DSDT, I see 
      <screen>
	Device (MB2)
        {
        Name (_HID, EisaId ("PNP0C01"))
	...
	}
      </screen>
      If I look up PNP0C01 in the list, I find: "PNP0C01         System Board".
    </para>
  </sect2>
  
</sect1>

<sect1 id="proc_entries">
  <title>Proc entries reference</title>
  
  <sect2 id="proc_overview">
    <title>Overview of /proc entries</title>
    <para>
      Many <filename class="directory">/proc</filename> entries have not made it over 
      to sysfs yet.  Those that have are 
      listed as deprecated here so you can avoid using them.  You'll find all the entries
      under <filename class="directory">/proc/apci</filename>.  
      These include access to your DSDT and FADT; the ACPI event queue; 
      battery info; CPU power and throttling state info; info on various buttons, 
      video display info; and much more.
    </para>
  </sect2>
  
  <sect2 id="proc_wake_on_rtc_alarm">
    <title>Wake on RTC alarm entry</title>
    <para>/proc/alarm</para>
    <para>
      If you have an RTC (Real Time Clock) that supports an alarm, an entry that
      lets you set that alarm shows up here.  
      To set the alarm, write to the file, using the following format:
      <screen>
	echo yyyy-mm-dd hh:mm:ss &gt; alarm
      </screen>
      Once the alarm is set, the RTC will generate a hardware wake event when
      the system is in a sleep state.  It's required to work from S1-S3 and optional
      for S4. You can tell if your system supports RTC wake from S4 by
      running this little script.
      It looks at the flags in the FADT for you; there doesn't seem to be a 
      <filename class="directory">/proc</filename> or 
      <filename class="directory">/sys</filename>
      interface that exposes this.
      <programlisting>
	#!/bin/bash
	
	# RTC_S4 flag is 113 bytes in, at bit 8 of the byte (0 is least significant bit).
	# This depends on the FADT not telling us a lie.  But what else do we have?
	
	if [ $(( (`cat /proc/acpi/fadt | od -j 112 -N 1 -t u1 -A n` & 0x10) >> 4)) -eq 1 ]; then
	echo "RTC alarm wakes from S4"
	else
	echo "RTC alarm does NOT wake from S4"
	fi
	exit 0
      </programlisting>
    </para>
  </sect2>
  
  <sect2 id="proc_acpi_info">
    <title>ACPI info entry</title>
    <para>info</para>
    <para>
      If you read the <filename>info</filename> file, it will print 
      the version number of [FIXME].  For example:
      <screen>
	version:                 20050729
      </screen>
      This is the same version that ACPI gives you in your log:
      <screen>
	Sep 11 03:42:58 localhost kernel: ACPI: Subsystem revision 20050729
      </screen>
    </para>
  </sect2>

  <sect2 id="proc_dsdt">
    <title>DSDT entry</title>
    <para>dsdt</para>
    <para>
      This is the binary form of your DSDT; more details about that table are available
      in the section <link linkend="dsdt_editing">DSDT editing</link>.
    </para>
  </sect2>
  
  <sect2 id="proc_fadt">
    <title>FADT entry</title>
    <para>fadt</para>
    <para>
      This is the binary form of your FADT, or Fixed ACPI Description Table. [FIXME more info]
    </para>
  </sect2>
  
  <sect2 id="proc_event">
    <title>Event queue for acpid</title>
    <para>event</para>
    <para>
      This is where ACPI events are written so that userspace applications can
      process them.  If acpid is running, it will read the events and when you
      try to <command>cat</command> them, the file will be empty.  If you have no daemon
      running to process events, you can <command>cat</command> this file to look at them, and
      they will be in the same format as in <filename>/var/log/acpid</filename>.  See 
      <link linkend="acpid_events">Acpid events</link> for more information.
    </para>
  </sect2>
  
  <sect2 id="proc_embedded_controller">
    <title>Embedded Controller entry</title>
    <para>embedded_controller</para>
    <para>
      Embedded controllers are usually used to manage or communicate with smart
      batteries and smart battery chargers.  If you have a smart battery, you'll
      probably also have an embedded controller, and it will show up here.  It may be listed
      as <filename class="directory">/proc/acpi/embedded_controller/EC0</filename>, 
      and in that directory, 
      you'll have the file <filename>info</filename>.  If you read that file, you
      can find out driver-level specifics.  Some sample output is here:
      <screen>
	gpe bit: 0x07
	ports: 0x66, 0x62
	use global lock: no
      </screen>
      If your embedded controller has the _GLK method then you should see "use global lock: yes".
      If your controller supports the _GPE method (which it is supposed to do), then you'll have a 
      reserved GPE bit for events, and that bit will be listed under "gpe bit".  
    </para>
  </sect2>
  
  <sect2 id="proc_battery">
    <title>Battery info</title>
    <para>battery</para>
    <para>
      If you're using a laptop, you should have an entry 
      <filename class="directory">/proc/acpi/battery</filename> for your battery.  Often
      this will be called BAT0 or something similar.  Underneath that directory, you'll have
      entries <filename>alarm</filename>, <filename>info</filename>, and <filename>state</filename>.
    </para>
    <para>
      <filename>alarm</filename> describes at what capacity your battery will generate a [FIXME]
      event.
      Some batteries don't support alarms; in that case you'll see "unknown" instead of a value.
      If your battery supports an alarm, you can set the alarm by writing a number to "alarm", 
      which will be the cutoff point in mAh; once the battery reaches that capacity or lower, 
      it will generate a notify event and the OS will stuff the event into 
      <filename>/proc/acpi/event</filename> where
      acpid can pick it up and allow you, the user, to respond. 
      See <link linkend="acpid">The acpid event handling daemon</link>
      for information on processing these events.  You can set this number higher than the
      manufacturer default, but not lower.  See below the description of "design capacity warning".
    </para>
    <para>
      If your battery doesn't support alarms, Linux will poll the battery to check its
      capacity and will [FIXME] as needed.
    </para>
    <para>
      <filename>info</filename> describes various capabilities of your battery.  
      Here's a breakdown using a sample listing:
    </para>
    
    <itemizedlist>
      <listitem>
	<para>
	  present: yes or no, depending on whether you have a battery inserted or not
	</para>
      </listitem>
      <listitem>
	<para>
	  design capacity: 7200 mAh -- your battery's capacity in milliamp-hours.  My
	  battery will produce 7.2 amps for 1 hour.
	</para>
      </listitem>
      <listitem>
	<para>
	  last full capacity: 7191 mAh -- your battery's capacity when it was last fully charged.
	  This is likely to be a bit lower than the design capacity (i.e. the capacity when
	  the battery came out of the factory).
	</para>
      </listitem>
      <listitem>
	<para>
	  battery technology: rechargeable, non-rechargeable, or unknown.  Know anyone using a
	  non-rechargeable battery?  If your battery reports that it is non-rechargeable, you
	  probably have problems with the ACPI driver; time to visit the kernel bugs list at
	  <ulink url="http://bugzilla.kernel.org">http://bugzilla.kernel.org</ulink> (check the ACPI component).
	</para>
      </listitem>
      <listitem>
	<para>
	  design voltage:  11100 mV -- voltage of the battery when new
	</para>
      </listitem>
      <listitem>
	<para>
	  design capacity warning: 720 mAh  - When the battery capacity crosses this point, it generates
	  a notify event -- whether it is charging, and capacity just got greater than this value, 
	  or draining, and capacity is running low.   Linux will pass that event on to /proc/acpi/event
	  where acpid can pick it up.
	  See <link linkend="acpid">The acpid event handling daemon</link>
	  for information on processing these events.
	</para>
	<para>
	  If your battery supports _BTP, you'll have the <filename>alarm</filename> entry 
	  described earlier, 
	  which allows you to set this number.  Otherwise, it's set at a default value.
	</para>
      </listitem>
      <listitem>
	<para>
	  design capacity low: 218 mAh  - how much energy needed to transition the system to
	  a sleep state.  If battery capacity gets to this point, Linux will put the system
	  into some sleep state [FIXME which one, how?].
	</para>
      </listitem>
      <listitem>
	<para>
	  capacity granularity 1:  72 mAh -- As the APCI spec says, "battery capacity granularity 
	  between low and warning in [mAh] or [mWh]. That is, this is the smallest increment in 
	  capacity that the battery is capable of measuring."
	</para>
      </listitem>
      <listitem>
	<para>
	  capacity granularity 2:  72 mAh -- Same as above, for warning to Full, except that 
	  this number can be different than capacity granularity 1 because in some systems, 
	  the granularity accuracy may change depending on the battery level. 
	</para>
      </listitem>
      <listitem>
	<para>
	  model number: DELL C54475
	</para>
      </listitem>
      <listitem>
	<para>
	  serial number: 1768
	</para>
      </listitem>
      <listitem>
	<para>
	  battery type: LION
	</para>
      </listitem>
      <listitem>
	<para>
	  OEM info: Sanyo
	</para>
      </listitem>
    </itemizedlist>
    
    <para>
      <filename>state</filename> describes the current battery state.  From a sample listing:
      <itemizedlist>
	<listitem>
	  <para>
	    present: yes or no
	  </para>
	</listitem>
	<listitem>
	  <para>
	    capacity state: ok or critical; critical means that the batteries are drained.  If you
	    are on battery power only, Linux should be shutting down your system right now. :-)
	  </para>
	</listitem>
	<listitem>
	  <para>
	    charging state: charged, charging, discharging, charging/discharging
	  </para>
	</listitem>
	<listitem>
	  <para>
	    present rate: 1 mA (or other value) or unknown
	  </para>
	</listitem>
	<listitem>
	  <para>
	    remaining capacity:  7200 mAh (or other value) or unknown
	  </para>
	</listitem>
	<listitem>
	  <para>
	    present voltage: 12441 mV (or other value) or unknown
	  </para>
	</listitem>
      </itemizedlist>
    </para>
  </sect2>
	
  <sect2 id="proc_button">
    <title>Button entries</title>
    <para>button</para>
    <para>
      This is where sleep, power and lid controls are described.  Let's look at each of these.
      <variablelist>
	
	<varlistentry>
	  <term>power</term>
	  <listitem>
	    <para>
	      You'll have an entry under this directory for your power button, something 
	      like <filename class="directory">PBTN</filename>.
	      The button will have the entry <filename>info</filename>, which 
	      you can look at to see if your power
	      button is a CM (Control Method) type button, or an FF (Fixed Feature) type button.
	      For more information on the distinction, read the ACPI specification; see
	      <link linkend="specifications">Specifications</link> for the link.
	    </para>
	  </listitem>
	</varlistentry>	    
	
	<varlistentry>
	  <term>sleep</term>
	  <listitem>
	    <para>
	      You'll have an entry under this directory for your sleep button, something 
	      like <filename class="directory">SBTN</filename>.
	      The button will have the entry <filename>info</filename>, which you can 
	      look at to see if your sleep
	      button is a CM (Control Method) type button, or an FF (Fixed Feature) type button.
	      For more information on the distinction, read the ACPI specification; see
	      <link linkend="specifications">Specifications</link> for the link.
	      If you don't have a separate sleep button, there will be an entry here anyways
	      and your button will be classed as CM type.
	    </para>
	  </listitem>
	</varlistentry>	    
	
	<varlistentry>
	  <term>lid</term>
	  <listitem>
	    <para>
	      You'll have an entry under this directory for your laptop lid button, 
	      something like <filename class="directory">LID</filename>.
	      The button will have the entry <filename>info</filename>, 
	      which will tell you that you have a
	      "Lid Switch".  There are no other types defined at this writing.
	      There will also be an entry <filename>state</filename>, which 
	      will either tell you that the lid
	      is "open" or "closed".  If you're thinking that this doesn't give you 
	      much new information, realize that this entry isn't meant for you; it's meant for
	      acpid-related scripts or user applications to check and take appropriate action
	      when they are notified of an APCI lid event.
	    </para>
	  </listitem>
	</varlistentry>	    
      </variablelist>

    </para>
  </sect2>

  <sect2 id="proc_fan">
    <title>Fan control</title>
    <para>fan</para>
    <para>
      For each fan, you'll have an entry in <filename class="directory">/proc/acpi/fan</filename>,
      called <filename class="directory">FAN</filename> or something similar.
      Under this entry, you'll have the file <filename>state</filename> which 
      lets you see whether the fan is
      on or off by reading it.  It also lets you write the fan state by echoing a number
      between 0 and 3, inclusive, to the file.  State 0 corresponds to device power state D0, and
      so on.  If you have variable speed fans that allow this, that's how to keep them quiet
      during low load times and cooling well during high load times.  You'll have to experiment
      to see what RPM each of these states gives you, if you have other software that lets
      you monitor fan speed.  Often, D0 is full on and D3 is off.
    </para>
  </sect2>
  
  <sect2 id="proc_power_resources">
    <title>Power resources</title>
    <para>power_resource</para>
    <para>
      You should also see the directory 
      <filename class="directory">/proc/acpi/power_resource</filename>.  
      Power resources are supposed 
      to be things like power planes, i.e. sources that devices rely on and that can be 
      turned off when all devices using them are turned off.  Having said that, I don't 
      know any specific objects
      that get classified as power resources, although some systems list power fans under this
      category.  
    </para>
    <para>
      Under this directory you'll have an entry for every resource with a file 
      <filename>state</filename> underneath it.  
      You can read this file to see if your resource is on or off.  There's a bit more information
      included: the system level, which is the lowest system sleep level that the OS can put
      the system in and still keep this power resource on;  the order, which lets the OS know which 
      order to turn on or off all resources at a given system sleep state; and the reference count,
      which is for internal bookkeeping.
    </para>
  </sect2>

  <sect2 id="proc_cpu">
    <title>CPU entries</title>
    <para>
      For each cpu, you'll have an entry in 
      <filename class="directory">/proc/acpi/processor</filename>, 
      <filename>CPU0</filename>-<filename>CPUn</filename>, and for each CPU
      you'll have the following entries:
      <variablelist>
	<varlistentry>
	  <term>info</term>
	  <listitem>
	    <para>
	      
	      <variablelist>
		<varlistentry>
		  <term>processor id</term>
		  <listitem>
		    <para>
		      0, unless you have a multiprocessor system, in which case, it'll be the
		      number of the particular CPU.
		    </para>
		  </listitem>
		</varlistentry>
		
		<varlistentry>
		  <term>acpi id</term>
		  <listitem>
		    <para>
		      CPU number by a different scheme.  ACPI gets its cpu numbering via the MADT, 
		      which may result in a different numbering than the processor id.
		    </para>
		  </listitem>
		</varlistentry>
		
		<varlistentry>
		  <term>bus mastering control</term>
		  <listitem>
		    <para>
		      This must be yes in SMP systems for C3 usage (to maintain cache coherency); if you
		      don't have it and your system is SMP, C3 and lower power states will be
		      unavailable to you.
		    </para>
		  </listitem>
		</varlistentry>
		
		<varlistentry>
		  <term>power management</term>
		  <listitem>
		    <para>
		      If yes, the CPU can be placed into a state of type C2 or C3.  This is not the
                      same as being in states C2 or C3!  See below for discussion of power state 
		      *types*.
		    </para>
		  </listitem>
		</varlistentry>
		
		<varlistentry>
		  <term>throttling control</term>
		  <listitem>
		    <para>
		      If yes, the CPU supports some throttling states; see {FIXME} for a discussion of
                      how these work.
		    </para>
		  </listitem>
		</varlistentry>
		
		<varlistentry>
		  <term>limit interface</term>
		  <listitem>
		    <para>
		      It would be nice if this entry had some use.  But it's actually set
                      whenever throttling control is set.  There ya go. [FIXME doublecheck]
		    </para>
		  </listitem>
		</varlistentry>
	      </variablelist>
	      
	    </para>
	  </listitem>
	</varlistentry>
	
	<varlistentry>
	  <term>limit</term>
	  <listitem>
	    <para>
	      If your cpu supports throttling states, you can see the highest throttling state
	      that your cpu is currently permitted to enter.  See 
	      <link linkend="throttling_and_pstate_limits">What are throttling/performance 
		state limits and how do I use them?</link> 
	      for more information on throttling states.
	    </para>
	  </listitem>
	</varlistentry>
	
	<varlistentry>
	  <term>power</term>
	  <listitem>
	    <para>
	      In addition to throttling states and performance states, each CPU supports
	      different power states; see <link linkend="power_states">Power states</link>
	      for more about this.  The power file shows you the current power state,
	      the maximum state that the system will allow the CPU to enter (the state where 
	      it uses the
	      lowest amount of power), [FIXME], and a list of all states the CPU actually supports.
	      In the supported power states list, the type field refers to the sort of preparation
	      that the OS must do in order to place the CPU in that power state.  So for example,
	      in the listing below, both power states C3 and C4 require the OS to disable bus master 
	      arbitration before entering the chosen power state; that's the preparation the
	      OS needs for the "C3 type".
	      <screen>
		active state:            C2 
		max_cstate:              C8 
		bus master activity:     08000000
		
		states:
		C1:                  type[C1] promotion[C2] demotion[--] latency[001] usage[00000010]
		*C2:                 type[C2] promotion[C3] demotion[C1] latency[001] usage[13576208]
		C3:                  type[C3] promotion[C4] demotion[C2] latency[085] usage[01936846]
		C4:                  type[C3] promotion[--] demotion[C3] latency[185] usage[26741344]
	      </screen>
	      One other thing you should pay attention to in this listing is the usage field.
	      This indicates how many times the CPU has been placed in this state (including 
	      from the very same state).  Unless you are always doing very computationally 
	      intensive work,  your listing should look something like the list above, 
	      i.e. your CPU should spend most of its time in the state with the lowest power
	      usage, here C4.  This is true even with cpu frequency management enabled.
	      Your CPU should be idle most of the time and it should spend most of the time
	      in the deepest idle state available. If that is not happening, you should check 
	      your kernel configuration and possibly report it as a bug.
	    </para>
	  </listitem>
	</varlistentry>
	
	<varlistentry>
	  <term>throttling</term>
	  <listitem>
	    <para>
	      The throttling entry shows you how many throttling states your CPU supports,
	      which state your CPU is currently in, and how much of the time your CPU
	      is forced idle for each state.
	      <screen>
		state count:             8
		active state:            T0
		states:
		*T0:                 00%
		T1:                  12%
		T2:                  25%
		T3:                  37%
		T4:                  50%
		T5:                  62%
		T6:                  75%
		T7:                  87%
	      </screen>
	      See <link linkend="cpu-management_throttling">CPU throttling</link> for more on throttling.
	    </para>
	  </listitem>
	</varlistentry>
      </variablelist>
    </para>
  </sect2>

  <sect2 id="proc_sleep">
    <title>Sleep (deprecated)</title>
    <para>
      <filename>/proc/acpi/sleep</filename> is deprecated; use 
      <filename>/sys/power/state</filename> instead.
    </para>
  </sect2>
  
  <sect2 id="proc_thermal_zone">
    <title>Thermal zone info</title>
    <para>thermal_zone</para>
    <para>
      If your system supports thermal management, you'll have entries in 
      <filename class="directory">/proc/acpi/thermal_zone</filename>.
      For each CPU and for any other devices your system can monitor and control via ACPI,
      you'll have an entry that begins <filename>THM</filename> or something similar.  
      The entries for each of these include:
    </para>
    <para>
      <variablelist>
	<varlistentry>
	  <term>cooling_mode</term>
	  <listitem>
	    <para>
	      This entry describes the cooling mode currently in use.   This can be one of 
	      active, passive, or critical.  These are described in more detail in the 
	      <link linkend="thermal_management">Thermal management</link> section.  
	      If your platform supports it, you can set the cooling
	      mode to active by echoing 0 to this file, or passive, by echoing 1 to this file.
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>state</term>
	  <listitem>
	    <para>
	      This shows the state of the thermal zone: either one of the cooling modes, if it
	      is currently activated, i.e. critical, passive, active[0] - active[9], or 
	      ok if no cooling mode is in use.
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>trip_points</term>
	  <listitem>
	    <para>
	      This shows the trip points you have set for the various cooling methods
	      your system supports. If your system only supports the mandatory critical
	      trip point, then that's all you'll see, as on my system:
	      <screen>
		critical (S5):           99 C
	      </screen>
	      If other methods are supported, you'll see trip points for those also, as 
	      in the example below:
	      <screen>
		critical (S5): 103 C
		passive: 100 C: tc1=1 tc2=2 tsp=100 devices=0xdfffed60
		active[0]: 80 C: devices=0xdffe6c00
		active[1]: 65 C: devices=0xdffe6b20
		active[2]: 52 C: devices=0xdffe6aa0
		active[3]: 40 C: devices=0xdffe6a20
		critical (S5): 103 C
		critical (S5): 103 C 
	      </screen>
	    </para>
	    <para>
	      The values for tc1 and tc2 are used to compute the optimal processor throttling state
	      to keep the thermal zone temperature down below the passive cooling limit, and tsp
	      is how often to sample the temperature while doing this adjustment.  These
	      values are fixed by the vendor and are provided here so that folks who
	      are interested in the nitty-gritty can do the computation and see if the
	      hardware behavior makes sense.  See 
	      <filename>/usr/src/linux/drivers/thermal.c</filename>,
	      function acpi_thermal_passive(), for more information.
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>polling_frequency</term>
	  <listitem>
	    <para>
	      This shows how often the temperature is checked, in seconds. By default, Linux sets this
	      to whatever your platform implements via the _TZP method; if this method
	      doesn't exist, then it's disabled.  That means that by default, temperature polling
	      is turned off on a lot of platforms.  Fortunately, you can enable it by
	      echoing a number to the file, where the number is how often to poll in seconds.
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>temperature</term>
	  <listitem>
	    <para>
	      This shows the current temperature in Celsius of the thermal zone.
	    </para>
	  </listitem>
	</varlistentry>
      </variablelist>
    </para>
  </sect2>

  <sect2 id="proc_video">
    <title>Video adapter and display entries</title>
    <para>
      For each video adapter, you'll have an entry under 
      <filename class="directory">/proc/acpi/video</filename> that starts with 
      <filename class="directory">VID</filename>.
      You should have the following subentries:
      <variablelist>
	<varlistentry>
	  <term>DOS</term>
	  <listitem>
	    <para>
	      [FIXME]
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>info</term>
	  <listitem>
	    <para>
	      [FIXME]
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>POST</term>
	  <listitem>
	    <para>
	      [FIXME]
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>POST_info</term>
	  <listitem>
	    <para>
	      [FIXME]
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>ROM</term>
	  <listitem>
	    <para>
	      [FIXME]
	    </para>
	  </listitem>
	</varlistentry>
      </variablelist>
    </para>
    <para>
      For each <filename class="directory">VID</filename> entry, you'll have 
      entries describing displays.  My system supports a variety of
      displays so I have the following entries: 
      <filename>CRT</filename>, <filename>DVI</filename>, <filename>LCD</filename>, and 
      <filename>TV</filename>.
      For each display you have these entries:
      <variablelist>
	<varlistentry>
	  <term>brightness</term>
	  <listitem>
	    <para>
	      This lets you change the brightness of your LCD.  You must use one of the supported
	      brightness levels, which you can obtain by reading the 
	      <filename>brightness</filename> file. Some platforms don't support this.
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>EDID</term>
	  <listitem>
	    <para>
	      Show extended display identification data for the display; this includes 
	      identifying information, hfreq, vfreq, resolution, and supported video modes.  
	      Some platforms don't support this.  If
	      you have one that does, I'd love to get the output so folks can have a sample in this
	      document.
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>info</term>
	  <listitem>
	    <para>
	      device_id: 0x0110   type:   UNKNOWN   known by bios: no
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>state</term>
	  <listitem>
	    <para>
	      This lets you activate/inactivate the display.  
	      <command>echo 0x80000001 &gt; /proc/video/VID/*/state</command> turns
	      on the display, and  
	      <command>echo 0x80000000 &gt; /proc/video/VID/*/state</command> turns it off.
	      These esoteric numbers come from the ACPI specs; bits 1-29 are zero,
	      and if you want to do actual switching and not just cacheing the change,
	      you set bit 31 and clear bit 30.  Bit 0 is set to activate the device
	      and cleared to inactivate it.
	    </para>
	    <para>
	      If you cat the file, you'll see something like 
	      <screen>
		state:     0x1f
		query:     0x00
	      </screen>
	      The value for state also comes straight from the ACPI specs: bits 5-31 are 
	      zero, and the meaningful bits are as follows: bit 4 [optional]: set 
	      if device is attached, bit 3: set if device is not defective,
	      bit 2: set if output is ready to switch, bit 1: output is activated, 
	      and bit 0: output connector exists now.  Given this, we can decipher 
	      0x1f as 11111 = attached, not defective, ready to switch, 
	      activated, connector exists now.  
	    </para>
	  </listitem>
	</varlistentry>
      </variablelist>
    </para>
  </sect2>

  <sect2 id="proc_wake">
    <title>Wake capabilities</title>
    <para>wakeup</para>
    <para>
      The entry <filename>wakeup</filename> has a list of which devices can change the 
      power state of the system, and whether or not that change is enabled.
    </para>
    <para>
      So in the list below, if your system is in S3 (suspend to RAM), and you open the lid, 
      the system will wake to S0.  If your system is in S4 and you press the power button, 
      the system will wake to S0. The other wake events are disabled.
      <screen>
	Device  Sleep state     Status
	LID        3            *enabled
	PBTN       4            *enabled
	PCI0       3            disabled
	USB0       0            disabled
	USB1       0            disabled
	USB2       0            disabled
	USB4       0            disabled
	USB3       0            disabled
	MODM       3            disabled
	PCIE       4            disabled
      </screen>
    </para>
  </sect2>
</sect1>

<sect1 id="acpixtract_mods">
  <title>Modified acpixtract</title>
  <para>
    Retrieve a given instance of a table by specifiying the number of the instance.
    For example, <command>acpidump |  ./acpixtract SSDT 3 &gt; ssdt3</command>
    <programlisting>
      #!/usr/bin/perl
      #
      # acpixtract - extract raw table from acpidmp output
      #
      # Example: cat mail.txt | ./acpixtract DSDT &gt; DSDT
      # iasl -d DSDT
      #
      
      ($ME = $0) =~ s|.*/||;
      
      $table = uc(shift(@ARGV) || "");
      $count = shift(@ARGV) || 1;
      
      if(@ARGV)
      {
          my($file);
          for $file (@ARGV)
          {
              if(open(IN, "$file"))
              {
                  &amp;process(IN, STDOUT, $table, $count);
                  close(IN);
              }
              else
              {
                  print STDERR "$ME: $file: $!\n";
              }
         }
      }
      else
      {
         &amp;process(STDIN, STDOUT, $table, $count);
      }

      exit(0);

      sub
      process
      {
         local(*IN, *OUT, $table, $count) = @_;
         my($interior) = 0;
         my($localcount) = 0;
         while(&lt;IN&gt;)
         {
             if(!$interior && /$table \@ 0x/)
             {
                 $localcount++;
                 if ($localcount != $count) {
                     next;
                 }
                 $interior = 1;
             }
             elsif($interior && /\s+[\dA-Fa-f]{4}:\s+/)
             {
                 $_ = $';
                 /\s{2}/;
                 $length = ((length($`) + 1) / 3) - 1;
                 print OUT pack('C*', map(hex, (split(/\s/, $`))[0..$length]));
             }
             elsif($interior)
             {
                 while(&lt;IN&gt;) {}
                 return;
             }
         }
      }
    </programlisting>
  </para>
</sect1>
</article> 
